Merge remote-tracking branch 'runelite/master'

This commit is contained in:
Owain van Brakel
2021-07-21 19:15:43 +02:00
38 changed files with 2789 additions and 172 deletions

View File

@@ -275,13 +275,14 @@ public enum ItemMapping
ITEM_CRYSTAL_AXE(DRAGON_AXE, CRYSTAL_AXE, CRYSTAL_AXE_INACTIVE),
ITEM_CRYSTAL_HARPOON(DRAGON_HARPOON, CRYSTAL_HARPOON, CRYSTAL_HARPOON_INACTIVE),
ITEM_CRYSTAL_PICKAXE(DRAGON_PICKAXE, CRYSTAL_PICKAXE, CRYSTAL_PICKAXE_INACTIVE),
ITEM_BLADE_OF_SAELDOR(BLADE_OF_SAELDOR_INACTIVE, BLADE_OF_SAELDOR, BLADE_OF_SAELDOR_C),
ITEM_BLADE_OF_SAELDOR(BLADE_OF_SAELDOR_INACTIVE, BLADE_OF_SAELDOR, BLADE_OF_SAELDOR_C, BLADE_OF_SAELDOR_C_25870, BLADE_OF_SAELDOR_C_25872, BLADE_OF_SAELDOR_C_25874, BLADE_OF_SAELDOR_C_25876, BLADE_OF_SAELDOR_C_25878, BLADE_OF_SAELDOR_C_25880, BLADE_OF_SAELDOR_C_25882),
ITEM_CRYSTAL_BOW(CRYSTAL_WEAPON_SEED, CRYSTAL_BOW, CRYSTAL_BOW_24123, CRYSTAL_BOW_INACTIVE),
ITEM_CRYSTAL_HALBERD(CRYSTAL_WEAPON_SEED, CRYSTAL_HALBERD, CRYSTAL_HALBERD_24125, CRYSTAL_HALBERD_INACTIVE),
ITEM_CRYSTAL_SHIELD(CRYSTAL_WEAPON_SEED, CRYSTAL_SHIELD, CRYSTAL_SHIELD_24127, CRYSTAL_SHIELD_INACTIVE),
ITEM_CRYSTAL_HELMET(CRYSTAL_ARMOUR_SEED, CRYSTAL_HELM, CRYSTAL_HELM_INACTIVE),
ITEM_CRYSTAL_LEGS(CRYSTAL_ARMOUR_SEED, 2L, CRYSTAL_LEGS, CRYSTAL_LEGS_INACTIVE),
ITEM_CRYSTAL_BODY(CRYSTAL_ARMOUR_SEED, 3L, CRYSTAL_BODY, CRYSTAL_BODY_INACTIVE),
ITEM_BOW_OF_FAERDHINEN(BOW_OF_FAERDHINEN_INACTIVE, BOW_OF_FAERDHINEN, BOW_OF_FAERDHINEN_C, BOW_OF_FAERDHINEN_C_25884, BOW_OF_FAERDHINEN_C_25886, BOW_OF_FAERDHINEN_C_25888, BOW_OF_FAERDHINEN_C_25890, BOW_OF_FAERDHINEN_C_25892, BOW_OF_FAERDHINEN_C_25894, BOW_OF_FAERDHINEN_C_25896),
// Bird nests
ITEM_BIRD_NEST(BIRD_NEST_5075, BIRD_NEST, BIRD_NEST_5071, BIRD_NEST_5072, BIRD_NEST_5073, BIRD_NEST_5074, BIRD_NEST_7413, BIRD_NEST_13653, BIRD_NEST_22798, BIRD_NEST_22800, CLUE_NEST_EASY, CLUE_NEST_MEDIUM, CLUE_NEST_HARD, CLUE_NEST_ELITE),

View File

@@ -81,7 +81,7 @@ public class DesertDiaryRequirement extends GenericDiaryRequirement
new QuestRequirement(Quest.DREAM_MENTOR));
add("Complete a lap of the Pollnivneach agility course.",
new SkillRequirement(Skill.AGILITY, 70));
add("Slay a Dust Devil with a Slayer helmet equipped.",
add("Slay a Dust Devil in the desert cave with a Slayer helmet equipped.",
new SkillRequirement(Skill.SLAYER, 65),
new SkillRequirement(Skill.DEFENCE, 10),
new SkillRequirement(Skill.CRAFTING, 55),

View File

@@ -70,7 +70,7 @@ public class WildernessDiaryRequirement extends GenericDiaryRequirement
// HARD
add("Cast one of the 3 God spells against another player in the Wilderness.",
new SkillRequirement(Skill.MAGIC, 60),
new QuestRequirement(Quest.THE_MAGE_ARENA));
new QuestRequirement(Quest.MAGE_ARENA_I));
add("Charge an Air Orb.",
new SkillRequirement(Skill.MAGIC, 66));
add("Catch a Black Salamander in the Wilderness.",

View File

@@ -237,7 +237,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
.put(new WorldPoint(3188, 3939, 0), new CoordinateClueInfo("Wilderness. Resource Area.", BRASSICAN_MAGE))
.put(new WorldPoint(3304, 3941, 0), new CoordinateClueInfo("Wilderness. East of Rogues' Castle.", ANCIENT_WIZARDS))
.put(new WorldPoint(2994, 3961, 0), new CoordinateClueInfo("Wilderness. Inside Agility Training Area.", BRASSICAN_MAGE))
.put(new WorldPoint(1770, 3417, 0), new CoordinateClueInfo("Crabclaw Isle", ANCIENT_WIZARDS))
.put(new WorldPoint(1769, 3418, 0), new CoordinateClueInfo("Crabclaw Isle", ANCIENT_WIZARDS))
.build();
private final String text;

View File

@@ -27,7 +27,6 @@ package net.runelite.client.plugins.crowdsourcing;
import java.time.temporal.ChronoUnit;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@@ -40,7 +39,6 @@ import net.runelite.client.plugins.crowdsourcing.woodcutting.CrowdsourcingWoodcu
import net.runelite.client.plugins.crowdsourcing.zmi.CrowdsourcingZMI;
import net.runelite.client.task.Schedule;
@Slf4j
@PluginDescriptor(
name = "OSRS Wiki Crowdsourcing",
description = "Send data to the wiki to help figure out skilling success rates, burn rates, more. See osrs.wiki/RS:CROWD"

View File

@@ -56,6 +56,7 @@ import net.runelite.api.Tile;
import net.runelite.api.TileItem;
import net.runelite.api.TileObject;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
@@ -134,9 +135,50 @@ class DevToolsOverlay extends Overlay
renderGraphicsObjects(graphics);
}
if (plugin.getRoofs().isActive())
{
renderRoofs(graphics);
}
return null;
}
private void renderRoofs(Graphics2D graphics)
{
Scene scene = client.getScene();
Tile[][][] tiles = scene.getTiles();
byte[][][] settings = client.getTileSettings();
int z = client.getPlane();
String text = "R";
for (int x = 0; x < Constants.SCENE_SIZE; ++x)
{
for (int y = 0; y < Constants.SCENE_SIZE; ++y)
{
Tile tile = tiles[z][x][y];
if (tile == null)
{
continue;
}
int flag = settings[z][x][y];
if ((flag & Constants.TILE_FLAG_UNDER_ROOF) == 0)
{
continue;
}
Point loc = Perspective.getCanvasTextLocation(client, graphics, tile.getLocalLocation(), text, z);
if (loc == null)
{
continue;
}
OverlayUtil.renderTextLocation(graphics, loc, text, Color.RED);
}
}
}
private void renderPlayers(Graphics2D graphics)
{
List<Player> players = client.getPlayers();
@@ -248,7 +290,11 @@ class DevToolsOverlay extends Overlay
Polygon poly = Perspective.getCanvasTilePoly(client, tile.getLocalLocation());
if (poly != null && poly.contains(client.getMouseCanvasPosition().getX(), client.getMouseCanvasPosition().getY()))
{
toolTipManager.add(new Tooltip("World Location: " + tile.getWorldLocation().getX() + ", " + tile.getWorldLocation().getY() + ", " + client.getPlane()));
WorldPoint worldLocation = tile.getWorldLocation();
String tooltip = String.format("World location: %d, %d, %d</br>" +
"Region ID: %d location: %d, %d", worldLocation.getX(), worldLocation.getY(), worldLocation.getPlane(),
worldLocation.getRegionID(), worldLocation.getRegionX(), worldLocation.getRegionY());
toolTipManager.add(new Tooltip(tooltip));
OverlayUtil.renderPolygon(graphics, poly, GREEN);
}
}

View File

@@ -180,6 +180,8 @@ class DevToolsPanel extends PluginPanel
disconnectBtn.addActionListener(e -> clientThread.invoke(() -> client.setGameState(GameState.CONNECTION_LOST)));
container.add(disconnectBtn);
container.add(plugin.getRoofs());
try
{
ShellFrame sf = plugin.getInjector().getInstance(ShellFrame.class);

View File

@@ -145,6 +145,7 @@ public class DevToolsPlugin extends Plugin
private DevToolsButton soundEffects;
private DevToolsButton scriptInspector;
private DevToolsButton inventoryInspector;
private DevToolsButton roofs;
private DevToolsButton shell;
private NavigationButton navButton;
@@ -191,6 +192,7 @@ public class DevToolsPlugin extends Plugin
soundEffects = new DevToolsButton("Sound Effects");
scriptInspector = new DevToolsButton("Script Inspector");
inventoryInspector = new DevToolsButton("Inventory Inspector");
roofs = new DevToolsButton("Roofs");
shell = new DevToolsButton("Shell");
overlayManager.add(overlay);

View File

@@ -45,7 +45,6 @@ import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.IndexDataBase;
import net.runelite.api.VarClientInt;
@@ -63,7 +62,6 @@ import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.DynamicGridLayout;
import net.runelite.client.ui.FontManager;
@Slf4j
class VarInspector extends DevToolsFrame
{
@Getter

View File

@@ -289,7 +289,8 @@ enum DiscordGameEventType
MG_CLAN_WARS("Clan Wars", DiscordAreaType.MINIGAMES, 12621, 12622, 12623, 13130, 13131, 13133, 13134, 13135, 13386, 13387, 13390, 13641, 13642, 13643, 13644, 13645, 13646, 13647, 13899, 13900, 14155, 14156),
MG_DUEL_ARENA("Duel Arena", DiscordAreaType.MINIGAMES, 13362, 13363),
MG_FISHING_TRAWLER("Fishing Trawler", DiscordAreaType.MINIGAMES, 7499),
MG_GAUNTLET("The Gauntlet", DiscordAreaType.MINIGAMES, 12127, 7512, 7768),
MG_GAUNTLET("The Gauntlet", DiscordAreaType.MINIGAMES, 12127, 7512),
MG_CORRUPTED_GAUNTLET("Corrupted Gauntlet", DiscordAreaType.MINIGAMES, 7768),
MG_HALLOWED_SEPULCHRE("Hallowed Sepulchre", DiscordAreaType.MINIGAMES, 8797, 9051, 9052, 9053, 9054, 9309, 9563, 9565, 9821, 10074, 10075, 10077),
MG_INFERNO("The Inferno", DiscordAreaType.MINIGAMES, 9043),
MG_KELDAGRIM_RAT_PITS("Keldagrim Rat Pits", DiscordAreaType.MINIGAMES, 7753),

View File

@@ -26,6 +26,8 @@ package net.runelite.client.plugins.itemidentification;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.function.Predicate;
import lombok.AllArgsConstructor;
import net.runelite.api.ItemID;
enum ItemIdentification
@@ -364,7 +366,25 @@ enum ItemIdentification
TARGET_TELEPORT(Type.TABLET, "Target", "TRG", ItemID.TARGET_TELEPORT),
VOLCANIC_MINE_TELEPORT(Type.TABLET, "V.Mine", "VM", ItemID.VOLCANIC_MINE_TELEPORT),
WILDERNESS_CRABS_TELEPORT(Type.TABLET, "W.Crab", "CRAB", ItemID.WILDERNESS_CRABS_TELEPORT);
WILDERNESS_CRABS_TELEPORT(Type.TABLET, "W.Crab", "CRAB", ItemID.WILDERNESS_CRABS_TELEPORT),
// Scrolls
NARDAH_TELEPORT(Type.SCROLL, "Nardah", "NAR", ItemID.NARDAH_TELEPORT),
DIGSITE_TELEPORT(Type.SCROLL, "Digsite", "DIG", ItemID.DIGSITE_TELEPORT),
FELDIP_HILLS_TELEPORT(Type.SCROLL, "F.Hills", "F.H", ItemID.FELDIP_HILLS_TELEPORT),
LUNAR_ISLE_TELEPORT(Type.SCROLL, "L.Isle", "L.I", ItemID.LUNAR_ISLE_TELEPORT),
MORTTON_TELEPORT(Type.SCROLL, "Mort'ton", "MORT", ItemID.MORTTON_TELEPORT),
PEST_CONTROL_TELEPORT(Type.SCROLL, "P.Cont", "PEST", ItemID.PEST_CONTROL_TELEPORT),
PISCATORIS_TELEPORT(Type.SCROLL, "Pisca", "PISC", ItemID.PISCATORIS_TELEPORT),
TAI_BWO_WANNAI_TELEPORT(Type.SCROLL, "TaiBwo", "TAI", ItemID.TAI_BWO_WANNAI_TELEPORT),
IORWERTH_CAMP_TELEPORT(Type.SCROLL, "Iorwerth", "IOR", ItemID.IORWERTH_CAMP_TELEPORT),
MOS_LEHARMLESS_TELEPORT(Type.SCROLL, "M.LeHarm", "M.L", ItemID.MOS_LEHARMLESS_TELEPORT),
LUMBERYARD_TELEPORT(Type.SCROLL, "Lumber", "LUMB", ItemID.LUMBERYARD_TELEPORT),
ZUL_ANDRA_TELEPORT(Type.SCROLL, "Zul-andra", "ZUL", ItemID.ZULANDRA_TELEPORT),
KEY_MASTER_TELEPORT(Type.SCROLL, "Key master", "KEY", ItemID.KEY_MASTER_TELEPORT),
REVENANT_CAVE_TELEPORT(Type.SCROLL, "Rev cave", "REV", ItemID.REVENANT_CAVE_TELEPORT),
WATSON_TELEPORT(Type.SCROLL, "Watson", "WATS", ItemID.WATSON_TELEPORT);
final Type type;
final String medName;
@@ -401,20 +421,24 @@ enum ItemIdentification
return itemIdentifications.get(id);
}
@AllArgsConstructor
enum Type
{
SEED,
SACK,
HERB,
LOGS,
PLANK,
SAPLING,
COMPOST,
ORE,
BAR,
GEM,
POTION,
IMPLING_JAR,
TABLET
SEED(ItemIdentificationConfig::showSeeds),
SACK(ItemIdentificationConfig::showSacks),
HERB(ItemIdentificationConfig::showHerbs),
LOGS(ItemIdentificationConfig::showLogs),
PLANK(ItemIdentificationConfig::showPlanks),
SAPLING(ItemIdentificationConfig::showSaplings),
COMPOST(ItemIdentificationConfig::showComposts),
ORE(ItemIdentificationConfig::showOres),
BAR(ItemIdentificationConfig::showBars),
GEM(ItemIdentificationConfig::showGems),
POTION(ItemIdentificationConfig::showPotions),
IMPLING_JAR(ItemIdentificationConfig::showImplingJars),
TABLET(ItemIdentificationConfig::showTablets),
SCROLL(ItemIdentificationConfig::showTeleportScrolls);
final Predicate<ItemIdentificationConfig> enabled;
}
}

View File

@@ -203,4 +203,15 @@ public interface ItemIdentificationConfig extends Config
{
return false;
}
@ConfigItem(
keyName = "showTeleportScrolls",
name = "Teleport Scrolls",
description = "Show identification on teleport scrolls",
section = identificationSection
)
default boolean showTeleportScrolls()
{
return false;
}
}

View File

@@ -58,93 +58,11 @@ class ItemIdentificationOverlay extends WidgetItemOverlay
public void renderItemOverlay(Graphics2D graphics, int itemId, WidgetItem widgetItem)
{
ItemIdentification iden = findItemIdentification(itemId);
if (iden == null)
if (iden == null || !iden.type.enabled.test(config))
{
return;
}
switch (iden.type)
{
case SEED:
if (!config.showSeeds())
{
return;
}
break;
case SACK:
if (!config.showSacks())
{
return;
}
break;
case HERB:
if (!config.showHerbs())
{
return;
}
break;
case LOGS:
if (!config.showLogs())
{
return;
}
break;
case PLANK:
if (!config.showPlanks())
{
return;
}
break;
case SAPLING:
if (!config.showSaplings())
{
return;
}
break;
case COMPOST:
if (!config.showComposts())
{
return;
}
break;
case ORE:
if (!config.showOres())
{
return;
}
break;
case BAR:
if (!config.showBars())
{
return;
}
break;
case GEM:
if (!config.showGems())
{
return;
}
break;
case POTION:
if (!config.showPotions())
{
return;
}
break;
case IMPLING_JAR:
if (!config.showImplingJars())
{
return;
}
break;
case TABLET:
if (!config.showTablets())
{
return;
}
break;
}
graphics.setFont(FontManager.getRunescapeSmallFont());
renderText(graphics, widgetItem.getCanvasBounds(), iden);
}

View File

@@ -247,6 +247,8 @@ public class MenuEntrySwapperPlugin extends Plugin
swap("inspect", "trapdoor", "travel", config::swapTravel);
swap("board", "travel cart", "pay-fare", config::swapTravel);
swap("board", "sacrificial boat", "quick-board", config::swapQuick);
swap("cage", "harpoon", config::swapHarpoon);
swap("big net", "harpoon", config::swapHarpoon);
swap("net", "harpoon", config::swapHarpoon);

View File

@@ -25,7 +25,10 @@
package net.runelite.client.plugins.mining;
import com.google.common.collect.ImmutableMap;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.Getter;
import static net.runelite.api.AnimationID.MINING_3A_PICKAXE;
import static net.runelite.api.AnimationID.MINING_ADAMANT_PICKAXE;
@@ -135,4 +138,11 @@ enum Pickaxe
{
return PICKAXE_ANIM_IDS.get(animId);
}
public static Set<Integer> all()
{
return Arrays.stream(values())
.map(pickaxe -> pickaxe.itemId)
.collect(Collectors.toSet());
}
}

View File

@@ -42,7 +42,6 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.GameState;
@@ -86,7 +85,6 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.tooltip.Tooltip;
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
@Slf4j
@PluginDescriptor(
name = "Music",
description = "Adds search and filter for the music list, and additional volume control",

View File

@@ -37,6 +37,7 @@ import java.time.temporal.ChronoUnit;
import java.util.Date;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.GameState;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
@@ -49,6 +50,7 @@ import net.runelite.client.events.ConfigChanged;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.task.Schedule;
import org.apache.commons.lang3.time.DurationFormatUtils;
@PluginDescriptor(
name = "Report Button",
@@ -180,6 +182,9 @@ public class ReportButtonPlugin extends Plugin
case LOGIN_TIME:
reportButton.setText(getLoginTime());
break;
case IDLE_TIME:
reportButton.setText(getIdleTime());
break;
case DATE:
reportButton.setText(getDate());
break;
@@ -192,6 +197,12 @@ public class ReportButtonPlugin extends Plugin
}
}
private String getIdleTime()
{
long lastActivity = Long.min(client.getMouseIdleTicks(), client.getKeyboardIdleTicks());
return DurationFormatUtils.formatDuration(lastActivity * Constants.CLIENT_TICK_LENGTH, "mm:ss");
}
private String getLoginTime()
{
if (loginTime == null)

View File

@@ -32,7 +32,8 @@ public enum TimeStyle
UTC("UTC Time"),
JAGEX("Jagex HQ Time"),
LOCAL_TIME("Local Time"),
GAME_TICKS("Game Ticks");
GAME_TICKS("Game Ticks"),
IDLE_TIME("Idle Time");
private final String name;

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2021, 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.roofremoval;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(RoofRemovalConfig.CONFIG_GROUP)
public interface RoofRemovalConfig extends Config
{
String CONFIG_GROUP = "roofremoval";
@ConfigItem(
keyName = "removePosition",
name = "Player's position",
description = "Remove roofs above the player's position"
)
default boolean removePosition()
{
return true;
}
@ConfigItem(
keyName = "removeHovered",
name = "Hovered tile",
description = "Remove roofs above the hovered tile"
)
default boolean removeHovered()
{
return true;
}
@ConfigItem(
keyName = "removeDestination",
name = "Destination tile",
description = "Remove roofs above the destination tile"
)
default boolean removeDestination()
{
return true;
}
@ConfigItem(
keyName = "removeBetween",
name = "Between camera & player",
description = "Remove roofs between the camera and the player at low camera angles"
)
default boolean removeBetween()
{
return true;
}
}

View File

@@ -0,0 +1,267 @@
/*
* Copyright (c) 2021 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.roofremoval;
import com.google.common.base.Stopwatch;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Provides;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import static net.runelite.api.Constants.ROOF_FLAG_BETWEEN;
import static net.runelite.api.Constants.ROOF_FLAG_DESTINATION;
import static net.runelite.api.Constants.ROOF_FLAG_HOVERED;
import static net.runelite.api.Constants.ROOF_FLAG_POSITION;
import net.runelite.api.GameState;
import net.runelite.api.Tile;
import net.runelite.api.events.GameStateChanged;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Roof Removal",
description = "Remove only the needed roofs above your player, hovered tile, or destination",
enabledByDefault = false
)
@Slf4j
public class RoofRemovalPlugin extends Plugin
{
private static class FlaggedArea
{
int rx1;
int ry1;
int rx2;
int ry2;
int z1;
int z2;
}
@Inject
private Client client;
@Inject
private ClientThread clientThread;
@Inject
private Gson gson;
@Inject
private RoofRemovalConfig config;
private final Map<Integer, long[]> overrides = new HashMap<>();
@Provides
RoofRemovalConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(RoofRemovalConfig.class);
}
@Override
public void startUp() throws IOException
{
loadRoofOverrides();
clientThread.invoke(() ->
{
if (client.getGameState() == GameState.LOGGED_IN)
{
performRoofRemoval();
}
client.getScene().setRoofRemovalMode(buildRoofRemovalFlags());
});
}
@Override
public void shutDown()
{
overrides.clear();
clientThread.invoke(() ->
{
client.getScene().setRoofRemovalMode(0);
// Reload the scene to clear roof flag overrides
if (client.getGameState() == GameState.LOGGED_IN)
{
client.setGameState(GameState.LOADING);
}
});
}
@Subscribe
public void onGameStateChanged(GameStateChanged e)
{
if (e.getGameState() == GameState.LOGGED_IN)
{
performRoofRemoval();
}
}
@Subscribe
public void onConfigChanged(ConfigChanged e)
{
if (!e.getGroup().equals(RoofRemovalConfig.CONFIG_GROUP))
{
return;
}
client.getScene().setRoofRemovalMode(buildRoofRemovalFlags());
}
private int buildRoofRemovalFlags()
{
int roofRemovalMode = 0;
if (config.removePosition())
{
roofRemovalMode |= ROOF_FLAG_POSITION;
}
if (config.removeHovered())
{
roofRemovalMode |= ROOF_FLAG_HOVERED;
}
if (config.removeDestination())
{
roofRemovalMode |= ROOF_FLAG_DESTINATION;
}
if (config.removeBetween())
{
roofRemovalMode |= ROOF_FLAG_BETWEEN;
}
return roofRemovalMode;
}
private void performRoofRemoval()
{
assert client.isClientThread();
applyRoofOverrides();
Stopwatch sw = Stopwatch.createStarted();
client.getScene().generateHouses();
log.debug("House generation duration: {}", sw.stop());
}
private void loadRoofOverrides() throws IOException
{
try (InputStream in = getClass().getResourceAsStream("overrides.jsonc"))
{
final InputStreamReader data = new InputStreamReader(in, StandardCharsets.UTF_8);
//CHECKSTYLE:OFF
final Type type = new TypeToken<Map<Integer, List<FlaggedArea>>>() {}.getType();
//CHECKSTYLE:ON
Map<Integer, List<FlaggedArea>> parsed = gson.fromJson(data, type);
overrides.clear();
for (Map.Entry<Integer, List<FlaggedArea>> entry : parsed.entrySet())
{
for (FlaggedArea fla : entry.getValue())
{
for (int z = fla.z1; z <= fla.z2; z++)
{
// Given that each region is 64x64, and the override data is a boolean, one of the axis can be stored as
// bits in a long. This removes the need for a boolean[64][64] and an extra array lookup in favour of
// a bitwise &, and results in a consistently smaller amount of memory required to store the overrides.
int packedRegion = entry.getKey() << 2 | z;
long[] regionData = overrides.computeIfAbsent(packedRegion, k -> new long[Constants.REGION_SIZE]);
for (int y = fla.ry1; y <= fla.ry2; y++)
{
long row = regionData[y];
for (int x = fla.rx1; x <= fla.rx2; x++)
{
row |= (1L << x);
}
regionData[y] = row;
}
}
}
}
}
}
private void applyRoofOverrides()
{
Stopwatch sw = Stopwatch.createStarted();
boolean regionsHaveOverrides = false;
outer:
for (int regionID : client.getMapRegions())
{
for (int z = 0; z < Constants.MAX_Z; z++)
{
if (overrides.containsKey(regionID << 2 | z))
{
regionsHaveOverrides = true;
break outer;
}
}
}
if (!regionsHaveOverrides)
{
return;
}
Tile[][][] tiles = client.getScene().getTiles();
byte[][][] settings = client.getTileSettings();
for (int z = 0; z < Constants.MAX_Z; z++)
{
for (int x = 0; x < Constants.SCENE_SIZE; x++)
{
for (int y = 0; y < Constants.SCENE_SIZE; y++)
{
Tile tile = tiles[z][x][y];
if (tile == null)
{
continue;
}
int regionID = tile.getWorldLocation().getRegionID() << 2 | z;
if (!overrides.containsKey(regionID))
{
continue;
}
int rx = tile.getWorldLocation().getRegionX();
int ry = tile.getWorldLocation().getRegionY();
long[] region = overrides.get(regionID);
if ((region[ry] & (1L << rx)) != 0)
{
settings[z][x][y] |= Constants.TILE_FLAG_UNDER_ROOF;
}
}
}
}
log.debug("Roof override duration: {}", sw.stop());
}
}

View File

@@ -520,12 +520,12 @@ public class SlayerPlugin extends Plugin
log.debug("Slayer xp change delta: {}, killed npcs: {}", delta, taggedNpcsDiedPrevTick);
final Task task = Task.getTask(taskName);
if (task != null && task.getExpectedKillExp() > 0)
if (task != null && task.getMinimumKillXp() > 0)
{
// Only decrement a kill if the xp drop matches the expected drop. This is just for Tzhaar tasks.
if (task.getExpectedKillExp() == delta)
// Only decrement a kill if the xp drop is above the minimum threshold. This is for Tzhaar and Sire tasks.
if (delta >= task.getMinimumKillXp())
{
killed(1);
killed(max(taggedNpcsDiedPrevTick, 1));
}
}
else

View File

@@ -39,8 +39,12 @@ enum Task
{
//<editor-fold desc="Enums">
ABERRANT_SPECTRES("Aberrant spectres", ItemID.ABERRANT_SPECTRE, "Spectre"),
ABYSSAL_DEMONS("Abyssal demons", ItemID.ABYSSAL_DEMON),
ABYSSAL_SIRE("Abyssal Sire", ItemID.ABYSSAL_ORPHAN),
// Abyssal demon - 150 xp
// Greater abyssal demon - 4200 xp
// Abyssal sire - 450 xp
// Use 51 for minimum xp to avoid a kill triggering from killing the sire vents
ABYSSAL_DEMONS("Abyssal demons", ItemID.ABYSSAL_DEMON, 51),
ABYSSAL_SIRE("Abyssal Sire", ItemID.ABYSSAL_ORPHAN, 51),
ADAMANT_DRAGONS("Adamant dragons", ItemID.ADAMANT_DRAGON_MASK),
ALCHEMICAL_HYDRA("Alchemical Hydra", ItemID.IKKLE_HYDRA),
ANKOU("Ankou", ItemID.ANKOU_MASK),
@@ -238,7 +242,7 @@ enum Task
private final String[] targetNames;
private final int weaknessThreshold;
private final int weaknessItem;
private final int expectedKillExp;
private final int minimumKillXp;
static
{
@@ -260,7 +264,7 @@ enum Task
this.weaknessThreshold = -1;
this.weaknessItem = -1;
this.targetNames = targetNames;
this.expectedKillExp = 0;
this.minimumKillXp = 0;
}
Task(String name, int itemSpriteId, int weaknessThreshold, int weaknessItem, String... targetNames)
@@ -271,10 +275,10 @@ enum Task
this.weaknessThreshold = weaknessThreshold;
this.weaknessItem = weaknessItem;
this.targetNames = targetNames;
this.expectedKillExp = 0;
this.minimumKillXp = 0;
}
Task(String name, int itemSpriteId, int expectedKillExp)
Task(String name, int itemSpriteId, int minimumKillXp)
{
Preconditions.checkArgument(itemSpriteId >= 0);
this.name = name;
@@ -282,7 +286,7 @@ enum Task
this.weaknessThreshold = -1;
this.weaknessItem = -1;
this.targetNames = new String[0];
this.expectedKillExp = expectedKillExp;
this.minimumKillXp = minimumKillXp;
}
@Nullable

View File

@@ -45,6 +45,7 @@ enum GameTimer
EXANTIFIRE(ItemID.EXTENDED_ANTIFIRE4, GameTimerImageType.ITEM, "Extended antifire", 12, ChronoUnit.MINUTES),
OVERLOAD(ItemID.OVERLOAD_4, GameTimerImageType.ITEM, "Overload", 5, ChronoUnit.MINUTES, true),
CANNON(ItemID.CANNON_BARRELS, GameTimerImageType.ITEM, "Cannon", 25, ChronoUnit.MINUTES),
CANNON_REPAIR(ItemID.TOOLKIT, GameTimerImageType.ITEM, "Broken Cannon", 10, ChronoUnit.MINUTES),
MAGICIMBUE(SpriteID.SPELL_MAGIC_IMBUE, GameTimerImageType.SPRITE, "Magic imbue", 21, GAME_TICKS),
SUPERANTIFIRE(ItemID.SUPER_ANTIFIRE_POTION4, GameTimerImageType.ITEM, "Super antifire", 3, ChronoUnit.MINUTES),
BIND(SpriteID.SPELL_BIND, GameTimerImageType.SPRITE, "Bind", GraphicID.BIND, 8, GAME_TICKS, true),
@@ -85,7 +86,9 @@ enum GameTimer
RESURRECT_THRALL_COOLDOWN(SpriteID.SPELL_RESURRECT_SUPERIOR_SKELETON_DISABLED, GameTimerImageType.SPRITE, "Resurrect thrall cooldown", 12, GAME_TICKS),
WARD_OF_ARCEUUS_COOLDOWN(SpriteID.SPELL_WARD_OF_ARCEUUS_DISABLED, GameTimerImageType.SPRITE, "Ward of Arceuus cooldown", 30, ChronoUnit.SECONDS),
DEATH_CHARGE_COOLDOWN(SpriteID.SPELL_DEATH_CHARGE_DISABLED, GameTimerImageType.SPRITE, "Death charge cooldown", 60, ChronoUnit.SECONDS),
CORRUPTION_COOLDOWN(SpriteID.SPELL_GREATER_CORRUPTION_DISABLED, GameTimerImageType.SPRITE, "Corruption cooldown", 30, ChronoUnit.SECONDS);
CORRUPTION_COOLDOWN(SpriteID.SPELL_GREATER_CORRUPTION_DISABLED, GameTimerImageType.SPRITE, "Corruption cooldown", 30, ChronoUnit.SECONDS),
PICKPOCKET_STUN(SpriteID.SKILL_THIEVING, GameTimerImageType.SPRITE, "Stunned", true)
;
@Nullable
private final Duration duration;

View File

@@ -283,4 +283,14 @@ public interface TimersConfig extends Config
{
return false;
}
@ConfigItem(
keyName = "showPickpocketStun",
name = "Pickpocket stun timer",
description = "Configures whether pickpocket stun timer is displayed"
)
default boolean showPickpocketStun()
{
return true;
}
}

View File

@@ -55,7 +55,6 @@ import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ActorDeath;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.StatChanged;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
@@ -63,6 +62,7 @@ import net.runelite.api.events.GraphicChanged;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.StatChanged;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.widgets.Widget;
import static net.runelite.api.widgets.WidgetInfo.PVP_WORLD_SAFE_ZONE;
@@ -82,7 +82,7 @@ import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "Timers",
description = "Show various timers in an infobox",
tags = {"combat", "items", "magic", "potions", "prayer", "overlay", "abyssal", "sire", "inferno", "fight", "caves", "cape", "timer", "tzhaar"}
tags = {"combat", "items", "magic", "potions", "prayer", "overlay", "abyssal", "sire", "inferno", "fight", "caves", "cape", "timer", "tzhaar", "thieving", "pickpocket"}
)
@Slf4j
public class TimersPlugin extends Plugin
@@ -90,10 +90,14 @@ public class TimersPlugin extends Plugin
private static final String ABYSSAL_SIRE_STUN_MESSAGE = "The Sire has been disorientated temporarily.";
private static final String ANTIFIRE_DRINK_MESSAGE = "You drink some of your antifire potion.";
private static final String ANTIFIRE_EXPIRED_MESSAGE = "<col=7f007f>Your antifire potion has expired.</col>";
private static final String CANNON_BASE_MESSAGE = "You place the cannon base on the ground.";
private static final String CANNON_STAND_MESSAGE = "You add the stand.";
private static final String CANNON_BARRELS_MESSAGE = "You add the barrels.";
private static final String CANNON_FURNACE_MESSAGE = "You add the furnace.";
private static final String CANNON_PICKUP_MESSAGE = "You pick up the cannon. It's really heavy.";
private static final String CANNON_REPAIR_MESSAGE = "You repair your cannon, restoring it to working order.";
private static final String CANNON_DESTROYED_MESSAGE = "Your cannon has been destroyed!";
private static final String CANNON_BROKEN_MESSAGE = "<col=ef1020>Your cannon has broken!";
private static final String CHARGE_EXPIRED_MESSAGE = "<col=ef1020>Your magical charge fades away.</col>";
private static final String CHARGE_MESSAGE = "<col=ef1020>You feel charged with magic power.</col>";
private static final String EXTENDED_ANTIFIRE_DRINK_MESSAGE = "You drink some of your extended antifire potion.";
@@ -122,6 +126,7 @@ public class TimersPlugin extends Plugin
private static final String RESURRECT_THRALL_DISAPPEAR_MESSAGE_START = ">Your ";
private static final String RESURRECT_THRALL_DISAPPEAR_MESSAGE_END = " thrall returns to the grave.</col>";
private static final String WARD_OF_ARCEUUS_MESSAGE = ">Your defence against Arceuus magic has been strengthened.</col>";
private static final String PICKPOCKET_FAILURE_MESSAGE = "You fail to pick the ";
private static final Pattern TELEBLOCK_PATTERN = Pattern.compile("A Tele Block spell has been cast on you(?: by .+)?\\. It will expire in (?<mins>\\d+) minutes?(?:, (?<secs>\\d+) seconds?)?\\.");
private static final Pattern DIVINE_POTION_PATTERN = Pattern.compile("You drink some of your divine (.+) potion\\.");
@@ -498,6 +503,18 @@ public class TimersPlugin extends Plugin
return;
}
if (message.contains(PICKPOCKET_FAILURE_MESSAGE) && config.showPickpocketStun() && message.contains("pocket"))
{
if (message.contains("hero") || message.contains("elf"))
{
createGameTimer(PICKPOCKET_STUN, Duration.ofSeconds(6));
}
else
{
createGameTimer(PICKPOCKET_STUN, Duration.ofSeconds(5));
}
}
if (message.equals(ABYSSAL_SIRE_STUN_MESSAGE) && config.showAbyssalSireStun())
{
createGameTimer(ABYSSAL_SIRE_STUN);
@@ -559,15 +576,27 @@ public class TimersPlugin extends Plugin
}
if (config.showCannon() && (message.equals(CANNON_FURNACE_MESSAGE) || message.contains(CANNON_REPAIR_MESSAGE)))
if (config.showCannon())
{
TimerTimer cannonTimer = createGameTimer(CANNON);
cannonTimer.setTooltip(cannonTimer.getTooltip() + " - World " + client.getWorld());
}
if (config.showCannon() && (message.equals(CANNON_PICKUP_MESSAGE) || message.equals(CANNON_DESTROYED_MESSAGE)))
{
removeGameTimer(CANNON);
if (message.equals(CANNON_BASE_MESSAGE) || message.equals(CANNON_STAND_MESSAGE)
|| message.equals(CANNON_BARRELS_MESSAGE) || message.equals(CANNON_FURNACE_MESSAGE)
|| message.contains(CANNON_REPAIR_MESSAGE))
{
removeGameTimer(CANNON_REPAIR);
TimerTimer cannonTimer = createGameTimer(CANNON);
cannonTimer.setTooltip(cannonTimer.getTooltip() + " - World " + client.getWorld());
}
else if (message.equals(CANNON_BROKEN_MESSAGE))
{
removeGameTimer(CANNON);
TimerTimer cannonTimer = createGameTimer(CANNON_REPAIR);
cannonTimer.setTooltip(cannonTimer.getTooltip() + " - World " + client.getWorld());
}
else if (message.equals(CANNON_PICKUP_MESSAGE) || message.equals(CANNON_DESTROYED_MESSAGE))
{
removeGameTimer(CANNON);
removeGameTimer(CANNON_REPAIR);
}
}
if (config.showMagicImbue() && message.equals(MAGIC_IMBUE_MESSAGE))

View File

@@ -35,7 +35,6 @@ import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.border.EmptyBorder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Constants;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
@@ -44,7 +43,6 @@ import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.SwingUtil;
@Slf4j
@Getter
public class TimeablePanel<T> extends JPanel
{

View File

@@ -35,7 +35,6 @@ import java.util.Set;
import javax.swing.JLabel;
import javax.swing.JToggleButton;
import javax.swing.border.EmptyBorder;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ItemID;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.ItemManager;
@@ -45,7 +44,6 @@ import net.runelite.client.plugins.timetracking.TimeablePanel;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
@Slf4j
public class FarmingTabPanel extends TabContentPanel
{
private final FarmingTracker farmingTracker;

View File

@@ -69,7 +69,9 @@ public class WidgetOverlay extends Overlay
new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_FIXED, OverlayPosition.BOTTOM_RIGHT),
new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_RESIZEABLE_MODERN, OverlayPosition.CANVAS_TOP_RIGHT),
new WidgetOverlay(client, WidgetInfo.MULTICOMBAT_RESIZEABLE_CLASSIC, OverlayPosition.CANVAS_TOP_RIGHT),
new WidgetOverlay(client, WidgetInfo.TEMPOROSS_STATUS_INDICATOR, OverlayPosition.TOP_LEFT)
new WidgetOverlay(client, WidgetInfo.TEMPOROSS_STATUS_INDICATOR, OverlayPosition.TOP_LEFT),
new WidgetOverlay(client, WidgetInfo.BA_HEAL_TEAMMATES, OverlayPosition.BOTTOM_LEFT),
new WidgetOverlay(client, WidgetInfo.BA_TEAM, OverlayPosition.TOP_RIGHT)
);
}

View File

@@ -450,7 +450,7 @@ public class ModelOutlineRenderer
{
y3 = clipY2;
}
if (y1 == y3 || y3 < 0)
if (y1 == y3 || y3 < clipY1)
{
return;
}
@@ -459,16 +459,16 @@ public class ModelOutlineRenderer
x2 <<= 14;
x3 = x1;
if (y1 < 0)
if (y1 < clipY1)
{
x3 -= y1 * slope3;
x1 -= y1 * slope1;
y1 = 0;
x3 -= (y1 - clipY1) * slope3;
x1 -= (y1 - clipY1) * slope1;
y1 = clipY1;
}
if (y2 < 0)
if (y2 < clipY1)
{
x2 -= slope2 * y2;
y2 = 0;
x2 -= (y2 - clipY1) * slope2;
y2 = clipY1;
}
int pixelY = y1;

View File

@@ -162,6 +162,12 @@
"name": "Silver Stall",
"xp": 54
},
{
"level": 50,
"icon": 5560,
"name": "Wall Safe",
"xp": 70
},
{
"level": 53,
"icon": 4625,