Merge remote-tracking branch 'runelite/master'

This commit is contained in:
Scott Burns
2019-05-02 17:04:36 +02:00
50 changed files with 1621 additions and 564 deletions

View File

@@ -28,8 +28,8 @@ import java.awt.image.*;
public class ClanChatPlugin extends Plugin
{
private static final int MAX_CHATS = 10;
private static final String CLAN_CHAT_TITLE = "Clan Chat";
private static final String RECENT_TITLE = "Recent Clan Chats";
private static final String CLAN_CHAT_TITLE = "CC";
private static final String RECENT_TITLE = "Recent CCs";
private static final int JOIN_LEAVE_DURATION = 20;
private static final int MESSAGE_DELAY = 10;
@Inject

View File

@@ -41,6 +41,8 @@ class ClueScrollEmoteOverlay extends Overlay
private final ClueScrollPlugin plugin;
private final Client client;
private boolean hasScrolled;
@Inject
private ClueScrollEmoteOverlay(ClueScrollPlugin plugin, Client client)
{
@@ -57,6 +59,7 @@ class ClueScrollEmoteOverlay extends Overlay
if (!(clue instanceof EmoteClue))
{
hasScrolled = false;
return null;
}
@@ -81,19 +84,29 @@ class ClueScrollEmoteOverlay extends Overlay
return null;
}
Widget firstEmoteWidget = null;
Widget secondEmoteWidget = null;
for (Widget emoteWidget : emoteContainer.getDynamicChildren())
{
if (emoteWidget.getSpriteId() == emoteClue.getFirstEmote().getSpriteId())
{
firstEmoteWidget = emoteWidget;
plugin.highlightWidget(graphics, emoteWidget, emoteWindow, null,
emoteClue.getSecondEmote() != null ? "1st" : null);
}
else if (emoteClue.getSecondEmote() != null
&& emoteWidget.getSpriteId() == emoteClue.getSecondEmote().getSpriteId())
{
secondEmoteWidget = emoteWidget;
plugin.highlightWidget(graphics, emoteWidget, emoteWindow, null, "2nd");
}
}
if (!hasScrolled)
{
hasScrolled = true;
plugin.scrollToWidget(WidgetInfo.EMOTE_CONTAINER, WidgetInfo.EMOTE_SCROLLBAR, firstEmoteWidget, secondEmoteWidget);
}
return null;
}

View File

@@ -44,6 +44,8 @@ class ClueScrollMusicOverlay extends Overlay
private final ClueScrollPlugin plugin;
private final Client client;
private boolean hasScrolled;
@Inject
private ClueScrollMusicOverlay(ClueScrollPlugin plugin, Client client)
{
@@ -60,6 +62,7 @@ class ClueScrollMusicOverlay extends Overlay
if (!(clue instanceof MusicClue))
{
hasScrolled = false;
return null;
}
@@ -95,6 +98,11 @@ class ClueScrollMusicOverlay extends Overlay
return null;
}
if (!hasScrolled)
{
hasScrolled = true;
plugin.scrollToWidget(WidgetInfo.MUSIC_TRACK_LIST, WidgetInfo.MUSIC_TRACK_SCROLLBAR, found);
}
plugin.highlightWidget(graphics, found, trackList, PADDING, null);
return null;

View File

@@ -55,6 +55,7 @@ import net.runelite.api.NPC;
import net.runelite.api.ObjectComposition;
import net.runelite.api.Point;
import net.runelite.api.Scene;
import net.runelite.api.ScriptID;
import net.runelite.api.Tile;
import net.runelite.api.TileObject;
import net.runelite.api.coords.LocalPoint;
@@ -81,6 +82,7 @@ import net.runelite.client.plugins.cluescrolls.clues.CoordinateClue;
import net.runelite.client.plugins.cluescrolls.clues.CrypticClue;
import net.runelite.client.plugins.cluescrolls.clues.EmoteClue;
import net.runelite.client.plugins.cluescrolls.clues.FairyRingClue;
import net.runelite.client.plugins.cluescrolls.clues.FaloTheBardClue;
import net.runelite.client.plugins.cluescrolls.clues.HotColdClue;
import net.runelite.client.plugins.cluescrolls.clues.LocationClueScroll;
import net.runelite.client.plugins.cluescrolls.clues.LocationsClueScroll;
@@ -507,6 +509,13 @@ public class ClueScrollPlugin extends Plugin
return fairyRingClue;
}
final FaloTheBardClue faloTheBardClue = FaloTheBardClue.forText(text);
if (faloTheBardClue != null)
{
return faloTheBardClue;
}
final HotColdClue hotColdClue = HotColdClue.forText(text);
if (hotColdClue != null)
@@ -739,4 +748,33 @@ public class ClueScrollPlugin extends Plugin
textComponent.setText(text);
textComponent.render(graphics);
}
void scrollToWidget(WidgetInfo list, WidgetInfo scrollbar, Widget ... toHighlight)
{
final Widget parent = client.getWidget(list);
int averageCentralY = 0;
int nonnullCount = 0;
for (Widget widget : toHighlight)
{
if (widget != null)
{
averageCentralY += widget.getRelativeY() + widget.getHeight() / 2;
nonnullCount += 1;
}
}
if (nonnullCount == 0)
{
return;
}
averageCentralY /= nonnullCount;
final int newScroll = Math.max(0, Math.min(parent.getScrollHeight(),
averageCentralY - parent.getHeight() / 2));
client.runScript(
ScriptID.UPDATE_SCROLLBAR,
scrollbar.getId(),
list.getId(),
newScroll
);
}
}

View File

@@ -0,0 +1,202 @@
/*
* Copyright (c) 2019, Twiglet1022 <https://github.com/Twiglet1022>
* 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.cluescrolls.clues;
import com.google.common.collect.ImmutableList;
import java.awt.Color;
import java.awt.Graphics2D;
import java.util.List;
import javax.annotation.Nonnull;
import lombok.Getter;
import net.runelite.api.Item;
import static net.runelite.api.ItemID.ARMADYL_HELMET;
import static net.runelite.api.ItemID.BARRELCHEST_ANCHOR;
import static net.runelite.api.ItemID.BARROWS_GLOVES;
import static net.runelite.api.ItemID.BASALT;
import static net.runelite.api.ItemID.BOOK_OF_BALANCE;
import static net.runelite.api.ItemID.BOOK_OF_DARKNESS;
import static net.runelite.api.ItemID.BOOK_OF_LAW;
import static net.runelite.api.ItemID.BOOK_OF_WAR;
import static net.runelite.api.ItemID.COOKING_GAUNTLETS;
import static net.runelite.api.ItemID.CRYSTAL_BOW_110;
import static net.runelite.api.ItemID.CRYSTAL_BOW_110_I;
import static net.runelite.api.ItemID.DRAGON_DEFENDER;
import static net.runelite.api.ItemID.DRAGON_SCIMITAR;
import static net.runelite.api.ItemID.FIGHTER_TORSO;
import static net.runelite.api.ItemID.GREENMANS_ALEM;
import static net.runelite.api.ItemID.HOLY_BOOK;
import static net.runelite.api.ItemID.INFERNAL_AXE;
import static net.runelite.api.ItemID.IVANDIS_FLAIL;
import static net.runelite.api.ItemID.LAVA_DRAGON_BONES;
import static net.runelite.api.ItemID.MARK_OF_GRACE;
import static net.runelite.api.ItemID.NEW_CRYSTAL_BOW;
import static net.runelite.api.ItemID.NEW_CRYSTAL_BOW_I;
import static net.runelite.api.ItemID.NUMULITE;
import static net.runelite.api.ItemID.ROD_OF_IVANDIS_1;
import static net.runelite.api.ItemID.ROD_OF_IVANDIS_10;
import static net.runelite.api.ItemID.RUNE_PLATEBODY;
import static net.runelite.api.ItemID.TZHAARKETOM;
import static net.runelite.api.ItemID.UNHOLY_BOOK;
import static net.runelite.api.ItemID.WARRIOR_GUILD_TOKEN;
import net.runelite.api.NPC;
import net.runelite.api.coords.WorldPoint;
import static net.runelite.client.plugins.cluescrolls.ClueScrollOverlay.TITLED_CONTENT_COLOR;
import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin;
import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET;
import net.runelite.client.plugins.cluescrolls.clues.emote.AnyRequirementCollection;
import net.runelite.client.plugins.cluescrolls.clues.emote.ItemRequirement;
import net.runelite.client.plugins.cluescrolls.clues.emote.RangeItemRequirement;
import net.runelite.client.plugins.cluescrolls.clues.emote.SingleItemRequirement;
import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
@Getter
public class FaloTheBardClue extends ClueScroll implements TextClueScroll, NpcClueScroll
{
private static final List<FaloTheBardClue> CLUES = ImmutableList.of(
new FaloTheBardClue("A blood red weapon, a strong curved sword, found on the island of primate lords.", item(DRAGON_SCIMITAR)),
new FaloTheBardClue("A book that preaches of some great figure, lending strength, might, and vigour.", any("Any god book (must be complete)", item(HOLY_BOOK), item(BOOK_OF_BALANCE), item(UNHOLY_BOOK), item(BOOK_OF_LAW), item(BOOK_OF_WAR), item(BOOK_OF_DARKNESS))),
new FaloTheBardClue("A bow of elven craft was made, it shimmers bright, but will soon fade.", any("Crystal Bow", range(NEW_CRYSTAL_BOW, CRYSTAL_BOW_110), range(NEW_CRYSTAL_BOW_I, CRYSTAL_BOW_110_I))),
new FaloTheBardClue("A fiery axe of great inferno, when you use it, you'll wonder where the logs go.", item(INFERNAL_AXE)),
new FaloTheBardClue("A mark used to increase one's grace, found atop a seer's place.", item(MARK_OF_GRACE)),
new FaloTheBardClue("A molten beast with fiery breath, you acquire these with its death.", item(LAVA_DRAGON_BONES)),
new FaloTheBardClue("A shiny helmet of flight, to obtain this with melee, struggle you might.", item(ARMADYL_HELMET)),
// The wiki doesn't specify whether the trimmed dragon defender will work so I've assumed that it doesn't
new FaloTheBardClue("A sword held in the other hand, red its colour, Cyclops strength you must withstand.", item(DRAGON_DEFENDER)),
new FaloTheBardClue("A token used to kill mythical beasts, in hope of a blade or just for an xp feast.", item(WARRIOR_GUILD_TOKEN)),
new FaloTheBardClue("Green is my favorite, mature ale I do love, this takes your herblore above.", item(GREENMANS_ALEM)),
new FaloTheBardClue("It can hold down a boat or crush a goat, this object, you see, is quite heavy.", item(BARRELCHEST_ANCHOR)),
new FaloTheBardClue("It comes from the ground, underneath the snowy plain. Trolls aplenty, with what looks like a mane.", item(BASALT)),
new FaloTheBardClue("No attack to wield, only strength is required, made of obsidian but with no room for a shield.", item(TZHAARKETOM)),
new FaloTheBardClue("Penance healers runners and more, obtaining this body often gives much deplore.", item(FIGHTER_TORSO)),
new FaloTheBardClue("Strangely found in a chest, many believe these gloves are the best.", item(BARROWS_GLOVES)),
new FaloTheBardClue("These gloves of white won't help you fight, but aid in cooking, they just might.", item(COOKING_GAUNTLETS)),
new FaloTheBardClue("They come from some time ago, from a land unto the east. Fossilised they have become, this small and gentle beast.", item(NUMULITE)),
new FaloTheBardClue("To slay a dragon you must first do, before this chest piece can be put on you.", item(RUNE_PLATEBODY)),
new FaloTheBardClue("Vampyres are agile opponents, damaged best with a weapon of many components.", any("Rod of Ivandis or Ivandis flail", range(ROD_OF_IVANDIS_10, ROD_OF_IVANDIS_1), item(IVANDIS_FLAIL)))
);
private static final WorldPoint LOCATION = new WorldPoint(2689, 3550, 0);
private static final String FALO_THE_BARD = "Falo the Bard";
private static SingleItemRequirement item(int itemId)
{
return new SingleItemRequirement(itemId);
}
private static AnyRequirementCollection any(String name, ItemRequirement... requirements)
{
return new AnyRequirementCollection(name, requirements);
}
private static RangeItemRequirement range(int startItemId, int endItemId)
{
return range(null, startItemId, endItemId);
}
private static RangeItemRequirement range(String name, int startItemId, int endItemId)
{
return new RangeItemRequirement(name, startItemId, endItemId);
}
private final String text;
@Nonnull
private final ItemRequirement[] itemRequirements;
private FaloTheBardClue(String text, @Nonnull ItemRequirement... itemRequirements)
{
this.text = text;
this.itemRequirements = itemRequirements;
}
@Override
public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin)
{
panelComponent.getChildren().add(TitleComponent.builder().text("Falo the Bard Clue").build());
panelComponent.getChildren().add(LineComponent.builder().left("NPC:").build());
panelComponent.getChildren().add(LineComponent.builder()
.left(FALO_THE_BARD)
.leftColor(TITLED_CONTENT_COLOR)
.build());
panelComponent.getChildren().add(LineComponent.builder().left("Item:").build());
Item[] inventory = plugin.getInventoryItems();
// If inventory is null, the player has nothing in their inventory
if (inventory == null)
{
inventory = new Item[0];
}
for (ItemRequirement requirement : itemRequirements)
{
boolean inventoryFulfilled = requirement.fulfilledBy(inventory);
panelComponent.getChildren().add(LineComponent.builder()
.left(requirement.getCollectiveName(plugin.getClient()))
.leftColor(TITLED_CONTENT_COLOR)
.right(inventoryFulfilled ? "\u2713" : "\u2717")
.rightColor(inventoryFulfilled ? Color.GREEN : Color.RED)
.build());
}
}
@Override
public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin)
{
if (!LOCATION.isInScene(plugin.getClient()))
{
return;
}
for (NPC npc : plugin.getNpcsToMark())
{
OverlayUtil.renderActorOverlayImage(graphics, npc, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET);
}
}
@Override
public String[] getNpcs()
{
return new String[] {FALO_THE_BARD};
}
public static FaloTheBardClue forText(String text)
{
for (FaloTheBardClue clue : CLUES)
{
if (clue.text.equalsIgnoreCase(text))
{
return clue;
}
}
return null;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@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.customcursor;
import java.awt.image.BufferedImage;
import lombok.Getter;
import net.runelite.client.util.ImageUtil;
public enum CustomCursor
{
RS3_GOLD("RS3 Gold", "cursor-rs3-gold.png"),
RS3_SILVER("RS3 Silver", "cursor-rs3-silver.png"),
DRAGON_DAGGER("Dragon Dagger", "cursor-dragon-dagger.png"),
TROUT("Trout", "cursor-trout.png"),
DRAGON_SCIMITAR("Dragon Scimitar", "cursor-dragon-scimitar.png");
private final String name;
@Getter
private final BufferedImage cursorImage;
CustomCursor(String name, String icon)
{
this.name = name;
this.cursorImage = ImageUtil.getResourceStreamFromClass(CustomCursorPlugin.class, icon);
}
@Override
public String toString()
{
return name;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@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.customcursor;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("customcursor")
public interface CustomCursorConfig extends Config
{
@ConfigItem(
keyName = "cursorStyle",
name = "Cursor",
description = "Select which cursor you wish to use"
)
default CustomCursor selectedCursor()
{
return CustomCursor.RS3_GOLD;
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (c) 2018, Kruithne <kruithne@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.customcursor;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.events.ConfigChanged;
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.ClientUI;
@PluginDescriptor(
name = "Custom Cursor",
description = "Replaces your mouse cursor image",
enabledByDefault = false
)
public class CustomCursorPlugin extends Plugin
{
@Inject
private ClientUI clientUI;
@Inject
private CustomCursorConfig config;
@Provides
CustomCursorConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(CustomCursorConfig.class);
}
@Override
protected void startUp()
{
updateCursor();
}
@Override
protected void shutDown()
{
clientUI.resetCursor();
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (event.getGroup().equals("customcursor") && event.getKey().equals("cursorStyle"))
{
updateCursor();
}
}
private void updateCursor()
{
CustomCursor selectedCursor = config.selectedCursor();
clientUI.setCursor(selectedCursor.getCursorImage(), selectedCursor.toString());
}
}

View File

@@ -111,13 +111,24 @@ public interface DailyTasksConfig extends Config
}
@ConfigItem(
position = 8,
keyName = "showArrows",
name = "Show Claimable Ogre Arrows",
description = "Show a message when you can collect ogre arrows from Rantz."
position = 8,
keyName = "showArrows",
name = "Show Claimable Ogre Arrows",
description = "Show a message when you can collect ogre arrows from Rantz."
)
default boolean showArrows()
{
return true;
}
@ConfigItem(
position = 9,
keyName = "showDynamite",
name = "Show Claimable Dynamite",
description = "Show a message when you can collect Dynamite from Thirus."
)
default boolean showDynamite()
{
return false;
}
}

View File

@@ -66,6 +66,7 @@ public class DailyTasksPlugin extends Plugin
private static final String ARROWS_MESSAGE = "You have ogre arrows waiting to be collected from Rantz.";
private static final String BONEMEAL_MESSAGE = "You have bonemeal and slime waiting to be collected from Robin.";
private static final int BONEMEAL_PER_DIARY = 13;
private static final String DYNAMITE_MESSAGE = "You have dynamite waiting to be collected from Thirus.";
private static final String RELOG_MESSAGE = " (May require a relog)";
@Inject
@@ -159,6 +160,11 @@ public class DailyTasksPlugin extends Plugin
{
checkArrows(dailyReset);
}
if (config.showDynamite())
{
checkDynamite(dailyReset);
}
}
}
@@ -253,6 +259,21 @@ public class DailyTasksPlugin extends Plugin
}
}
private void checkDynamite(boolean dailyReset)
{
if (client.getVar(Varbits.DIARY_KOUREND_MEDIUM) == 1)
{
if (client.getVar(Varbits.DAILY_DYNAMITE_COLLECTED) == 0)
{
sendChatMessage(DYNAMITE_MESSAGE);
}
else if (dailyReset)
{
sendChatMessage(DYNAMITE_MESSAGE);
}
}
}
private void sendChatMessage(String chatMessage)
{
final String message = new ChatMessageBuilder()

View File

@@ -145,7 +145,7 @@ public class IdleNotifierPlugin extends Plugin
case COOKING_FIRE:
case COOKING_RANGE:
case COOKING_WINE:
/* Crafting(Gem Cutting, Glassblowing, Spinning, Battlestaves) */
/* Crafting(Gem Cutting, Glassblowing, Spinning, Battlestaves, Pottery) */
case GEM_CUTTING_OPAL:
case GEM_CUTTING_JADE:
case GEM_CUTTING_REDTOPAZ:
@@ -158,6 +158,8 @@ public class IdleNotifierPlugin extends Plugin
case CRAFTING_SPINNING:
case CRAFTING_BATTLESTAVES:
case CRAFTING_LEATHER:
case CRAFTING_POTTERS_WHEEL:
case CRAFTING_POTTERY_OVEN:
/* Fletching(Cutting, Stringing) */
case FLETCHING_BOW_CUTTING:
case FLETCHING_STRING_NORMAL_SHORTBOW:

View File

@@ -0,0 +1,127 @@
/*
* Copyright (c) 2019, Hydrox6 <ikada@protonmail.ch>
* 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.itemidentification;
import java.util.HashMap;
import java.util.Map;
import net.runelite.api.ItemID;
enum ItemIdentification
{
//Seeds
GUAM_SEED(Type.SEED, "Guam", "G", ItemID.GUAM_SEED),
MARRENTILL_SEED(Type.SEED, "Marren", "M", ItemID.MARRENTILL_SEED),
TARROMIN_SEED(Type.SEED, "Tarro", "TAR", ItemID.TARROMIN_SEED),
HARRALANDER_SEED(Type.SEED, "Harra", "H", ItemID.HARRALANDER_SEED),
RANARR_SEED(Type.SEED, "Ranarr", "R", ItemID.RANARR_SEED),
TOADFLAX_SEED(Type.SEED, "Toad", "TOA", ItemID.TOADFLAX_SEED),
IRIT_SEED(Type.SEED, "Irit", "I", ItemID.IRIT_SEED),
AVANTOE_SEED(Type.SEED, "Avantoe", "A", ItemID.AVANTOE_SEED),
KWUARM_SEED(Type.SEED, "Kwuarm", "K", ItemID.KWUARM_SEED),
SNAPDRAGON_SEED(Type.SEED, "Snap", "S", ItemID.SNAPDRAGON_SEED),
CADANTINE_SEED(Type.SEED, "Cadan", "C", ItemID.CADANTINE_SEED),
LANTADYME_SEED(Type.SEED, "Lanta", "L", ItemID.LANTADYME_SEED),
DWARF_WEED_SEED(Type.SEED, "Dwarf", "D", ItemID.DWARF_WEED_SEED),
TORSTOL_SEED(Type.SEED, "Torstol", "TOR", ItemID.TORSTOL_SEED),
POISON_IVY_SEED(Type.SEED, "Ivy", "I", ItemID.POISON_IVY_SEED),
WHITEBERRY_SEED( Type.SEED, "White", "W", ItemID.WHITEBERRY_SEED),
//Herbs
GUAM(Type.HERB, "Guam", "G", ItemID.GUAM_LEAF, ItemID.GRIMY_GUAM_LEAF),
MARRENTILL(Type.HERB, "Marren", "M", ItemID.MARRENTILL, ItemID.GRIMY_MARRENTILL),
TARROMIN(Type.HERB, "Tarro", "TAR", ItemID.TARROMIN, ItemID.GRIMY_TARROMIN),
HARRALANDER(Type.HERB, "Harra", "H", ItemID.HARRALANDER, ItemID.GRIMY_HARRALANDER),
RANARR(Type.HERB, "Ranarr", "R", ItemID.RANARR_WEED, ItemID.GRIMY_RANARR_WEED),
TOADFLAX(Type.HERB, "Toad", "TOA", ItemID.TOADFLAX, ItemID.GRIMY_TOADFLAX),
IRIT(Type.HERB, "Irit", "I", ItemID.IRIT_LEAF, ItemID.GRIMY_IRIT_LEAF),
AVANTOE(Type.HERB, "Avantoe", "A", ItemID.AVANTOE, ItemID.GRIMY_AVANTOE),
KWUARM(Type.HERB, "Kwuarm", "K", ItemID.KWUARM, ItemID.GRIMY_KWUARM),
SNAPDRAGON(Type.HERB, "Snap", "S", ItemID.SNAPDRAGON, ItemID.GRIMY_SNAPDRAGON),
CADANTINE(Type.HERB, "Cadan", "C", ItemID.CADANTINE, ItemID.GRIMY_CADANTINE),
LANTADYME(Type.HERB, "Lanta", "L", ItemID.LANTADYME, ItemID.GRIMY_LANTADYME),
DWARF_WEED(Type.HERB, "Dwarf", "D", ItemID.DWARF_WEED, ItemID.GRIMY_DWARF_WEED),
TORSTOL(Type.HERB, "Torstol", "TOR", ItemID.TORSTOL, ItemID.GRIMY_TORSTOL),
//Saplings
OAK_SAPLING(Type.SAPLING, "Oak", "OAK", ItemID.OAK_SAPLING, ItemID.OAK_SEEDLING, ItemID.OAK_SEEDLING_W),
WILLOW_SAPLING(Type.SAPLING, "Willow", "WIL", ItemID.WILLOW_SAPLING, ItemID.WILLOW_SEEDLING, ItemID.WILLOW_SEEDLING_W),
MAPLE_SAPLING(Type.SAPLING, "Maple", "MAP", ItemID.MAPLE_SAPLING, ItemID.MAPLE_SEEDLING, ItemID.MAPLE_SEEDLING_W),
YEW_SAPLING(Type.SAPLING, "Yew", "YEW", ItemID.YEW_SAPLING, ItemID.YEW_SEEDLING, ItemID.YEW_SEEDLING_W),
MAGIC_SAPLING(Type.SAPLING, "Magic", "MAG", ItemID.MAGIC_SAPLING, ItemID.MAGIC_SEEDLING, ItemID.MAGIC_SEEDLING_W),
REDWOOD_SAPLING(Type.SAPLING, "Red", "RED", ItemID.REDWOOD_SAPLING, ItemID.REDWOOD_SEEDLING, ItemID.REDWOOD_SEEDLING_W),
SPIRIT_SAPLING(Type.SAPLING, "Spirit", "SPI", ItemID.SPIRIT_SAPLING, ItemID.SPIRIT_SEEDLING, ItemID.SPIRIT_SEEDLING_W),
APPLE_SAPLING(Type.SAPLING, "Apple", "APP", ItemID.APPLE_SAPLING, ItemID.APPLE_SEEDLING, ItemID.APPLE_SEEDLING_W),
BANANA_SAPLING(Type.SAPLING, "Banana", "BAN", ItemID.BANANA_SAPLING, ItemID.BANANA_SEEDLING, ItemID.BANANA_SEEDLING_W),
ORANGE_SAPLING(Type.SAPLING, "Orange", "ORA", ItemID.ORANGE_SAPLING, ItemID.ORANGE_SEEDLING, ItemID.ORANGE_SEEDLING_W),
CURRY_SAPLING(Type.SAPLING, "Curry", "CUR", ItemID.CURRY_SAPLING, ItemID.CURRY_SEEDLING, ItemID.CURRY_SEEDLING_W),
PINEAPPLE_SAPLING(Type.SAPLING, "Pine", "PINE", ItemID.PINEAPPLE_SAPLING, ItemID.PINEAPPLE_SEEDLING, ItemID.PINEAPPLE_SEEDLING_W),
PAPAYA_SAPLING(Type.SAPLING, "Papaya", "PAP", ItemID.PAPAYA_SAPLING, ItemID.PAPAYA_SEEDLING, ItemID.PAPAYA_SEEDLING_W),
PALM_SAPLING(Type.SAPLING, "Palm", "PALM", ItemID.PALM_SAPLING, ItemID.PALM_SEEDLING, ItemID.PALM_SEEDLING_W),
DRAGONFRUIT_SAPLING(Type.SAPLING, "Dragon", "DRAG", ItemID.DRAGONFRUIT_SAPLING, ItemID.DRAGONFRUIT_SEEDLING, ItemID.DRAGONFRUIT_SEEDLING_W),
TEAK_SAPLING(Type.SAPLING, "Teak", "TEAK", ItemID.TEAK_SAPLING, ItemID.TEAK_SEEDLING, ItemID.TEAK_SEEDLING_W),
MAHOGANY_SAPLING(Type.SAPLING, "Mahog", "MAHOG", ItemID.MAHOGANY_SAPLING, ItemID.MAHOGANY_SEEDLING, ItemID.MAHOGANY_SEEDLING_W),
CALQUAT_SAPLING(Type.SAPLING, "Calquat", "CALQ", ItemID.CALQUAT_SAPLING, ItemID.CALQUAT_SEEDLING, ItemID.CALQUAT_SEEDLING_W),
CELASTRUS_SAPLING(Type.SAPLING, "Celas", "CEL", ItemID.CELASTRUS_SAPLING, ItemID.CELASTRUS_SEEDLING, ItemID.CELASTRUS_SEEDLING_W);
final Type type;
final String medName;
final String shortName;
final int[] itemIDs;
ItemIdentification(Type type, String medName, String shortName, int ... ids)
{
this.type = type;
this.medName = medName;
this.shortName = shortName;
this.itemIDs = ids;
}
private static final Map<Integer, ItemIdentification> itemIdentifications = new HashMap<>();
static
{
for (ItemIdentification i : values())
{
for (int id : i.itemIDs)
{
itemIdentifications.put(id, i);
}
}
}
static ItemIdentification get(int id)
{
return itemIdentifications.get(id);
}
enum Type
{
SEED,
HERB,
SAPLING
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2019, Hydrox6 <ikada@protonmail.ch>
* 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.itemidentification;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("itemidentification")
public interface ItemIdentificationConfig extends Config
{
@ConfigItem(
keyName = "identificationType",
name = "Identification Type",
position = -4,
description = "How much to show of the item name"
)
default ItemIdentificationMode identificationType()
{
return ItemIdentificationMode.SHORT;
}
@ConfigItem(
keyName = "textColor",
name = "Color",
position = -3,
description = "The colour of the identification text"
)
default Color textColor()
{
return Color.WHITE;
}
@ConfigItem(
keyName = "showSeeds",
name = "Seeds",
description = "Show identification on Seeds"
)
default boolean showSeeds()
{
return true;
}
@ConfigItem(
keyName = "showHerbs",
name = "Herbs",
description = "Show identification on Herbs"
)
default boolean showHerbs()
{
return false;
}
@ConfigItem(
keyName = "showSaplings",
name = "Saplings",
description = "Show identification on Saplings and Seedlings"
)
default boolean showSaplings()
{
return true;
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2019, Hydrox6 <ikada@protonmail.ch>
* 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.itemidentification;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum ItemIdentificationMode
{
SHORT("Short"),
MEDIUM("Medium");
private final String type;
@Override
public String toString()
{
return type;
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright (c) 2019, Hydrox6 <ikada@protonmail.ch>
* 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.itemidentification;
import com.google.inject.Inject;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import static net.runelite.api.widgets.WidgetID.GUIDE_PRICE_GROUP_ID;
import static net.runelite.api.widgets.WidgetID.KEPT_ON_DEATH_GROUP_ID;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.WidgetItemOverlay;
import net.runelite.client.ui.overlay.components.TextComponent;
class ItemIdentificationOverlay extends WidgetItemOverlay
{
private final ItemIdentificationConfig config;
@Inject
ItemIdentificationOverlay(ItemIdentificationConfig config)
{
this.config = config;
showOnInventory();
showOnBank();
showOnInterfaces(KEPT_ON_DEATH_GROUP_ID, GUIDE_PRICE_GROUP_ID);
}
@Override
public void renderItemOverlay(Graphics2D graphics, int itemId, WidgetItem itemWidget)
{
ItemIdentification iden = ItemIdentification.get(itemId);
if (iden == null)
{
return;
}
switch (iden.type)
{
case SEED:
if (!config.showSeeds())
{
return;
}
break;
case HERB:
if (!config.showHerbs())
{
return;
}
break;
case SAPLING:
if (!config.showSaplings())
{
return;
}
break;
}
graphics.setFont(FontManager.getRunescapeSmallFont());
renderText(graphics, itemWidget.getCanvasBounds(), iden);
}
private void renderText(Graphics2D graphics, Rectangle bounds, ItemIdentification iden)
{
final TextComponent textComponent = new TextComponent();
textComponent.setPosition(new Point(bounds.x, bounds.y + bounds.height));
textComponent.setColor(config.textColor());
switch (config.identificationType())
{
case SHORT:
textComponent.setText(iden.shortName);
break;
case MEDIUM:
textComponent.setText(iden.medName);
break;
}
textComponent.render(graphics);
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2019, Hydrox6 <ikada@protonmail.ch>
* 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.itemidentification;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Item Identification",
description = "Show identifying text over items with difficult to distinguish sprites",
enabledByDefault = false
)
public class ItemIdentificationPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private ItemIdentificationOverlay overlay;
@Provides
ItemIdentificationConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(ItemIdentificationConfig.class);
}
@Override
protected void startUp()
{
overlayManager.add(overlay);
}
@Override
protected void shutDown()
{
overlayManager.remove(overlay);
}
}

View File

@@ -99,6 +99,10 @@ public class LootTrackerPlugin extends Plugin
private static final Pattern CLUE_SCROLL_PATTERN = Pattern.compile("You have completed [0-9]+ ([a-z]+) Treasure Trails.");
private static final int THEATRE_OF_BLOOD_REGION = 12867;
// Herbiboar loot handling
private static final String HERBIBOAR_LOOTED_MESSAGE = "You harvest herbs from the herbiboar, whereupon it escapes.";
private static final String HERBIBOR_EVENT = "Herbiboar";
// Chest loot handling
private static final String CHEST_LOOTED_MESSAGE = "You find some treasure in the chest!";
private static final Map<Integer, String> CHEST_EVENT_TYPES = ImmutableMap.of(
@@ -389,14 +393,15 @@ public class LootTrackerPlugin extends Plugin
}
eventType = CHEST_EVENT_TYPES.get(regionID);
takeInventorySnapshot();
final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY);
if (itemContainer != null)
{
inventorySnapshot = HashMultiset.create();
Arrays.stream(itemContainer.getItems())
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
}
return;
}
if (message.equals(HERBIBOAR_LOOTED_MESSAGE))
{
eventType = HERBIBOR_EVENT;
takeInventorySnapshot();
return;
}
@@ -433,7 +438,7 @@ public class LootTrackerPlugin extends Plugin
@Subscribe
public void onItemContainerChanged(ItemContainerChanged event)
{
if (eventType != null && CHEST_EVENT_TYPES.containsValue(eventType))
if (eventType != null && (CHEST_EVENT_TYPES.containsValue(eventType) || HERBIBOR_EVENT.equals(eventType)))
{
if (event.getItemContainer() != client.getItemContainer(InventoryID.INVENTORY))
{
@@ -445,6 +450,17 @@ public class LootTrackerPlugin extends Plugin
}
}
private void takeInventorySnapshot()
{
final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY);
if (itemContainer != null)
{
inventorySnapshot = HashMultiset.create();
Arrays.stream(itemContainer.getItems())
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
}
}
private void processChestLoot(String chestType, ItemContainer inventoryContainer)
{
if (inventorySnapshot != null)

View File

@@ -109,7 +109,7 @@ import net.runelite.http.api.chat.ChatClient;
public class SlayerPlugin extends Plugin
{
//Chat messages
private static final Pattern CHAT_GEM_PROGRESS_MESSAGE = Pattern.compile("^(?:You're assigned to kill|You have received a new Slayer assignment from .*:) (?:[Tt]he )?(?<name>.+?)(?: (?:in|on) (?:the )?(?<location>[^;]+))?(?:; only | \\()(?<amount>\\d+)(?: more to go\\.|\\))$");
private static final Pattern CHAT_GEM_PROGRESS_MESSAGE = Pattern.compile("^(?:You're assigned to kill|You have received a new Slayer assignment from .*:) (?:[Tt]he )?(?<name>.+?)(?: (?:in|on|south of) (?:the )?(?<location>[^;]+))?(?:; only | \\()(?<amount>\\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.";
@@ -118,10 +118,10 @@ public class SlayerPlugin extends Plugin
private static final Pattern COMBAT_BRACELET_TASK_UPDATE_MESSAGE = Pattern.compile("^You still need to kill (\\d+) monsters to complete your current Slayer assignment");
//NPC messages
private static final Pattern NPC_ASSIGN_MESSAGE = Pattern.compile(".*(?:Your new task is to kill|You are to bring balance to)\\s*(?<amount>\\d+) (?<name>.+?)(?: (?:in|on) (?:the )?(?<location>.+))?\\.");
private static final Pattern NPC_ASSIGN_MESSAGE = Pattern.compile(".*(?:Your new task is to kill|You are to bring balance to)\\s*(?<amount>\\d+) (?<name>.+?)(?: (?:in|on|south of) (?:the )?(?<location>.+))?\\.");
private static final Pattern NPC_ASSIGN_BOSS_MESSAGE = Pattern.compile("^Excellent. You're now assigned to kill (?:the )?(.*) (\\d+) times.*Your reward point tally is (.*)\\.$");
private static final Pattern NPC_ASSIGN_FIRST_MESSAGE = Pattern.compile("^We'll start you off hunting (.*), you'll need to kill (\\d*) of them.");
private static final Pattern NPC_CURRENT_MESSAGE = Pattern.compile("^You're still (?:hunting|bringing balance to) (?<name>.+)(?: (?:in|on) (?:the )?(?<location>.+), with|; you have) (?<amount>\\d+) to go\\..*");
private static final Pattern NPC_CURRENT_MESSAGE = Pattern.compile("^You're still (?:hunting|bringing balance to) (?<name>.+)(?: (?:in|on|south of) (?:the )?(?<location>.+), with|; you have) (?<amount>\\d+) to go\\..*");
private static final int GROTESQUE_GUARDIANS_REGION = 6727;

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2019, Beau Mitchell <beaumitch@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.virtuallevels;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("virtuallevels")
public interface VirtualLevelsConfig extends Config
{
@ConfigItem(
keyName = "virtualTotalLevel",
name = "Virtual Total Level",
description = "Count virtual levels towards total level",
position = 0
)
default boolean virtualTotalLevel()
{
return true;
}
}

View File

@@ -25,12 +25,15 @@
*/
package net.runelite.client.plugins.virtuallevels;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Experience;
import net.runelite.api.Skill;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.ScriptCallbackEvent;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.PluginChanged;
import net.runelite.client.plugins.Plugin;
@@ -38,7 +41,7 @@ import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Virtual Levels",
description = "Configuration for the virtual levels plugin.",
description = "Shows virtual levels (beyond 99) and virtual skill total on the skills tab.",
tags = {"skill", "total", "max"},
enabledByDefault = false
)
@@ -46,12 +49,21 @@ public class VirtualLevelsPlugin extends Plugin
{
private static final String TOTAL_LEVEL_TEXT_PREFIX = "Total level:<br>";
@Inject
private VirtualLevelsConfig config;
@Inject
private Client client;
@Inject
private ClientThread clientThread;
@Provides
VirtualLevelsConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(VirtualLevelsConfig.class);
}
@Override
protected void shutDown()
{
@@ -68,6 +80,17 @@ public class VirtualLevelsPlugin extends Plugin
}
}
@Subscribe
public void onConfigChanged(ConfigChanged configChanged)
{
if (!configChanged.getGroup().equals("virtuallevels"))
{
return;
}
clientThread.invoke(this::simulateSkillChange);
}
@Subscribe
public void onScriptCallbackEvent(ScriptCallbackEvent e)
{
@@ -93,6 +116,10 @@ public class VirtualLevelsPlugin extends Plugin
intStack[intStackSize - 1] = Experience.MAX_VIRT_LEVEL;
break;
case "skillTabTotalLevel":
if (!config.virtualTotalLevel())
{
break;
}
int level = 0;
for (Skill s : Skill.values())

View File

@@ -389,11 +389,21 @@ public class WorldHopperPlugin extends Plugin
// Don't add entry if user is offline
ChatPlayer player = getChatPlayerFromName(event.getTarget());
if (player == null || player.getWorld() == 0 || player.getWorld() == client.getWorld())
if (player == null || player.getWorld() == 0 || player.getWorld() == client.getWorld()
|| worldResult == null)
{
return;
}
World currentWorld = worldResult.findWorld(client.getWorld());
World targetWorld = worldResult.findWorld(player.getWorld());
if (targetWorld == null || currentWorld == null
|| (!currentWorld.getTypes().contains(WorldType.PVP) && targetWorld.getTypes().contains(WorldType.PVP)))
{
// Disable Hop-to a PVP world from a regular world
return;
}
final MenuEntry hopTo = new MenuEntry();
hopTo.setOption(HOP_TO);
hopTo.setTarget(event.getTarget());

View File

@@ -61,6 +61,7 @@ enum TeleportLocationData
ICE_PLATEAU(TeleportType.LUNAR_MAGIC, "Ice Plateau", 89, new WorldPoint(2973, 3939, 0), "ice_plateau_teleport_icon.png"),
LUMBRIDGE_GRAVEYARD(TeleportType.ARCEUUS_MAGIC, "Lumbridge Graveyard", 6, new WorldPoint(3241, 3194, 0), "lumbridge_graveyard_teleport_icon.png"),
DRAYNOR_MANOR(TeleportType.ARCEUUS_MAGIC, "Draynor Manor", 17, new WorldPoint(3108, 3352, 0), "draynor_manor_teleport_icon.png"),
BATTLEFRONT(TeleportType.ARCEUUS_MAGIC, "Battlefront", 23, new WorldPoint(1349, 3739, 0), "battlefront_teleport_icon.png"),
MIND_ALTAR(TeleportType.ARCEUUS_MAGIC, "Mind Altar", 28, new WorldPoint(2979, 3509, 0), "mind_altar_teleport_icon.png"),
SALVE_GRAVEYARD(TeleportType.ARCEUUS_MAGIC, "Salve Graveyard", 40, new WorldPoint(3433, 3461, 0), "salve_graveyard_teleport_icon.png"),
FENKENSTRAINS_CASTLE(TeleportType.ARCEUUS_MAGIC, "Fenkenstrain's Castle", 48, new WorldPoint(3548, 3528, 0), "fenkenstrains_castle_teleport_icon.png"),

View File

@@ -37,6 +37,7 @@ import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
@@ -594,6 +595,38 @@ public class ClientUI
giveClientFocus();
}
/**
* Changes cursor for client window. Requires ${@link ClientUI#open(RuneLite)} to be called first.
* FIXME: This is working properly only on Windows, Linux and Mac are displaying cursor incorrectly
* @param image cursor image
* @param name cursor name
*/
public void setCursor(final BufferedImage image, final String name)
{
if (container == null)
{
return;
}
final java.awt.Point hotspot = new java.awt.Point(container.getX(), container.getY());
final Cursor cursorAwt = Toolkit.getDefaultToolkit().createCustomCursor(image, hotspot, name);
container.setCursor(cursorAwt);
}
/**
* Resets client window cursor to default one.
* @see ClientUI#setCursor(BufferedImage, String)
*/
public void resetCursor()
{
if (container == null)
{
return;
}
container.setCursor(Cursor.getDefaultCursor());
}
/**
* Get offset of game canvas in game window
*