Merge remote-tracking branch 'rl-upstream/master' into rl-upstream-200622

This commit is contained in:
JumpIfZero
2022-06-20 12:30:36 +03:00
22 changed files with 354 additions and 145 deletions

View File

@@ -427,4 +427,10 @@ public final class ScriptID
*/ */
@ScriptArguments(integer = 6) @ScriptArguments(integer = 6)
public static final int TRADE_MAIN_INIT = 755; public static final int TRADE_MAIN_INIT = 755;
/**
* Transitions the tob hud into the white flash that happens when sotetseg teleports the players to the maze.
*/
@ScriptArguments(string = 1)
public static final int TOB_HUD_SOTETSEG_FADE = 2308;
} }

View File

@@ -27,6 +27,7 @@ package net.runelite.client;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import lombok.Data; import lombok.Data;
import net.runelite.client.ui.FatalErrorDialog; import net.runelite.client.ui.FatalErrorDialog;
@@ -41,6 +42,8 @@ public class RuntimeConfig
private String outageMessage; private String outageMessage;
private Map<String, String> outageLinks; private Map<String, String> outageLinks;
private Set<Integer> ignoreDeadNpcs;
public boolean showOutageMessage() public boolean showOutageMessage()
{ {
if (Strings.isNullOrEmpty(getOutageMessage())) if (Strings.isNullOrEmpty(getOutageMessage()))

View File

@@ -248,7 +248,12 @@ public class SessionManager
// Save session to disk // Save session to disk
saveSession(); saveSession();
req.getResponseHeaders().set("Location", oauthRedirect); final HttpUrl redirect = HttpUrl.get(oauthRedirect).newBuilder()
.addQueryParameter("username", username)
.addQueryParameter("sessionId", sessionId.toString())
.build();
req.getResponseHeaders().set("Location", redirect.toString());
req.sendResponseHeaders(302, 0); req.sendResponseHeaders(302, 0);
} }
catch (Exception e) catch (Exception e)

View File

@@ -25,11 +25,24 @@
*/ */
package net.runelite.client.game; package net.runelite.client.game;
import java.util.Set;
import javax.inject.Inject;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.NPCComposition;
import net.runelite.api.NpcID; import net.runelite.api.NpcID;
import net.runelite.client.RuntimeConfig;
import org.apache.commons.lang3.ArrayUtils;
public class NpcUtil public class NpcUtil
{ {
private final RuntimeConfig runtimeConfig;
@Inject
private NpcUtil(RuntimeConfig runtimeConfig)
{
this.runtimeConfig = runtimeConfig;
}
/** /**
* Returns whether an NPC is dying and can no longer be interacted with, or if it is still alive or in some special * Returns whether an NPC is dying and can no longer be interacted with, or if it is still alive or in some special
* state where it can be 0hp without dying. (For example, Gargoyles and other slayer monsters with item weaknesses * state where it can be 0hp without dying. (For example, Gargoyles and other slayer monsters with item weaknesses
@@ -38,7 +51,7 @@ public class NpcUtil
* @param npc NPC to check whether it is dying * @param npc NPC to check whether it is dying
* @return {@code true} if the NPC is dying * @return {@code true} if the NPC is dying
*/ */
public static boolean isDying(final NPC npc) public boolean isDying(final NPC npc)
{ {
final int id = npc.getId(); final int id = npc.getId();
switch (id) switch (id)
@@ -72,14 +85,22 @@ public class NpcUtil
case NpcID.DESERT_LIZARD: case NpcID.DESERT_LIZARD:
case NpcID.DESERT_LIZARD_460: case NpcID.DESERT_LIZARD_460:
case NpcID.DESERT_LIZARD_461: case NpcID.DESERT_LIZARD_461:
case NpcID.LIZARD:
case NpcID.SMALL_LIZARD:
case NpcID.SMALL_LIZARD_463:
case NpcID.GROWTHLING: case NpcID.GROWTHLING:
case NpcID.KALPHITE_QUEEN_963: case NpcID.KALPHITE_QUEEN_963: // KQ's first form sometimes regenerates 1hp after reaching 0hp, thus not dying
case NpcID.KALPHITE_QUEEN_965:
case NpcID.VETION:
case NpcID.VETION_REBORN:
return false; return false;
default: default:
return npc.isDead(); Set<Integer> ignoredNpcs = runtimeConfig.getIgnoreDeadNpcs();
if (ignoredNpcs != null && ignoredNpcs.contains(id))
{
return false;
}
final NPCComposition npcComposition = npc.getTransformedComposition();
boolean hasAttack = npcComposition != null && ArrayUtils.contains(npcComposition.getActions(), "Attack");
return hasAttack && npc.isDead();
} }
} }
} }

View File

@@ -107,7 +107,7 @@ public class KourendDiaryRequirement extends GenericDiaryRequirement
new QuestRequirement(Quest.DREAM_MENTOR)); new QuestRequirement(Quest.DREAM_MENTOR));
//ELITE //ELITE
add("Craft one or more Blood runes from Essence.", add("Craft one or more Blood runes from Dark essence fragments.",
new SkillRequirement(Skill.RUNECRAFT, 77), new SkillRequirement(Skill.RUNECRAFT, 77),
new SkillRequirement(Skill.MINING, 38), new SkillRequirement(Skill.MINING, 38),
new SkillRequirement(Skill.CRAFTING, 38), new SkillRequirement(Skill.CRAFTING, 38),

View File

@@ -32,7 +32,7 @@ import net.runelite.api.Skill;
import net.runelite.client.ui.overlay.infobox.InfoBox; import net.runelite.client.ui.overlay.infobox.InfoBox;
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority; import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
public class BoostIndicator extends InfoBox class BoostIndicator extends InfoBox
{ {
private final BoostsPlugin plugin; private final BoostsPlugin plugin;
private final BoostsConfig config; private final BoostsConfig config;
@@ -87,7 +87,7 @@ public class BoostIndicator extends InfoBox
@Override @Override
public boolean render() public boolean render()
{ {
return config.displayInfoboxes() && plugin.canShowBoosts() && plugin.getSkillsToDisplay().contains(getSkill()); return plugin.canShowBoosts() && plugin.getSkillsToDisplay().contains(getSkill()) && config.displayInfoboxes();
} }
@Override @Override

View File

@@ -59,7 +59,7 @@ public interface BoostsConfig extends Config
@ConfigItem( @ConfigItem(
keyName = "relativeBoost", keyName = "relativeBoost",
name = "Use Relative Boosts", name = "Show relative boosts",
description = "Configures whether or not relative boost is used", description = "Configures whether or not relative boost is used",
position = 2 position = 2
) )
@@ -70,8 +70,8 @@ public interface BoostsConfig extends Config
@ConfigItem( @ConfigItem(
keyName = "displayIndicators", keyName = "displayIndicators",
name = "Display as infoboxes", name = "Display infoboxes",
description = "Configures whether or not to display the boost as infoboxes", description = "Configures whether to display boost infoboxes",
position = 3 position = 3
) )
default boolean displayInfoboxes() default boolean displayInfoboxes()
@@ -79,11 +79,33 @@ public interface BoostsConfig extends Config
return true; return true;
} }
@ConfigItem(
keyName = "displayPanel",
name = "Display panel",
description = "Configures whether to display the boost panel",
position = 3
)
default boolean displayPanel()
{
return false;
}
@ConfigItem(
keyName = "compactDisplay",
name = "Compact display",
description = "Displays skill boosts in a more compact panel",
position = 4
)
default boolean compactDisplay()
{
return false;
}
@ConfigItem( @ConfigItem(
keyName = "displayNextBuffChange", keyName = "displayNextBuffChange",
name = "Next buff change", name = "Next buff change",
description = "Configures whether or not to display when the next buffed stat change will be", description = "Configures whether or not to display when the next buffed stat change will be",
position = 4 position = 10
) )
default DisplayChangeMode displayNextBuffChange() default DisplayChangeMode displayNextBuffChange()
{ {
@@ -94,7 +116,7 @@ public interface BoostsConfig extends Config
keyName = "displayNextDebuffChange", keyName = "displayNextDebuffChange",
name = "Next debuff change", name = "Next debuff change",
description = "Configures whether or not to display when the next debuffed stat change will be", description = "Configures whether or not to display when the next debuffed stat change will be",
position = 5 position = 11
) )
default DisplayChangeMode displayNextDebuffChange() default DisplayChangeMode displayNextDebuffChange()
{ {
@@ -105,7 +127,7 @@ public interface BoostsConfig extends Config
keyName = "boostThreshold", keyName = "boostThreshold",
name = "Boost threshold", name = "Boost threshold",
description = "The threshold at which boosted levels will be displayed in a different color. A value of 0 will disable the feature.", description = "The threshold at which boosted levels will be displayed in a different color. A value of 0 will disable the feature.",
position = 6 position = 12
) )
default int boostThreshold() default int boostThreshold()
{ {
@@ -116,7 +138,7 @@ public interface BoostsConfig extends Config
keyName = "notifyOnBoost", keyName = "notifyOnBoost",
name = "Notify on boost threshold", name = "Notify on boost threshold",
description = "Configures whether or not a notification will be sent for boosted stats.", description = "Configures whether or not a notification will be sent for boosted stats.",
position = 7 position = 13
) )
default boolean notifyOnBoost() default boolean notifyOnBoost()
{ {

View File

@@ -30,10 +30,7 @@ import java.awt.Graphics2D;
import java.util.Set; import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import net.runelite.api.Skill; import net.runelite.api.Skill;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPanel; import net.runelite.client.ui.overlay.OverlayPanel;
import net.runelite.client.ui.overlay.OverlayPosition; import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority; import net.runelite.client.ui.overlay.OverlayPriority;
@@ -55,19 +52,18 @@ class BoostsOverlay extends OverlayPanel
this.config = config; this.config = config;
setPosition(OverlayPosition.TOP_LEFT); setPosition(OverlayPosition.TOP_LEFT);
setPriority(OverlayPriority.MED); setPriority(OverlayPriority.MED);
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Boosts overlay"));
} }
@Override @Override
public Dimension render(Graphics2D graphics) public Dimension render(Graphics2D graphics)
{ {
if (config.displayInfoboxes()) final Set<Skill> boostedSkills = plugin.getSkillsToDisplay();
if (boostedSkills.isEmpty() || !config.displayPanel())
{ {
return null; return null;
} }
int nextChange = plugin.getChangeDownTicks(); int nextChange = plugin.getChangeDownTicks();
if (nextChange != -1) if (nextChange != -1)
{ {
panelComponent.getChildren().add(LineComponent.builder() panelComponent.getChildren().add(LineComponent.builder()
@@ -77,7 +73,6 @@ class BoostsOverlay extends OverlayPanel
} }
nextChange = plugin.getChangeUpTicks(); nextChange = plugin.getChangeUpTicks();
if (nextChange != -1) if (nextChange != -1)
{ {
panelComponent.getChildren().add(LineComponent.builder() panelComponent.getChildren().add(LineComponent.builder()
@@ -86,13 +81,6 @@ class BoostsOverlay extends OverlayPanel
.build()); .build());
} }
final Set<Skill> boostedSkills = plugin.getSkillsToDisplay();
if (boostedSkills.isEmpty())
{
return super.render(graphics);
}
if (plugin.canShowBoosts()) if (plugin.canShowBoosts())
{ {
for (Skill skill : boostedSkills) for (Skill skill : boostedSkills)
@@ -136,6 +124,5 @@ class BoostsOverlay extends OverlayPanel
} }
return boost <= config.boostThreshold() ? Color.YELLOW : Color.GREEN; return boost <= config.boostThreshold() ? Color.YELLOW : Color.GREEN;
} }
} }

View File

@@ -34,19 +34,22 @@ import javax.inject.Singleton;
import lombok.Getter; import lombok.Getter;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.Constants; import net.runelite.api.Constants;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import net.runelite.api.Prayer; import net.runelite.api.Prayer;
import net.runelite.api.Skill; import net.runelite.api.Skill;
import net.runelite.client.events.ConfigChanged;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.api.events.StatChanged; import net.runelite.api.events.StatChanged;
import net.runelite.client.Notifier; import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe; import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.events.ConfigChanged;
import net.runelite.client.game.SkillIconManager; import net.runelite.client.game.SkillIconManager;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager; import net.runelite.client.ui.overlay.OverlayManager;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager; import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.ImageUtil; import net.runelite.client.util.ImageUtil;
@@ -85,6 +88,9 @@ public class BoostsPlugin extends Plugin
@Inject @Inject
private BoostsOverlay boostsOverlay; private BoostsOverlay boostsOverlay;
@Inject
private CompactBoostsOverlay compactBoostsOverlay;
@Inject @Inject
private BoostsConfig config; private BoostsConfig config;
@@ -113,14 +119,20 @@ public class BoostsPlugin extends Plugin
@Override @Override
protected void startUp() throws Exception protected void startUp() throws Exception
{ {
OverlayMenuEntry menuEntry = new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Boosts overlay");
boostsOverlay.getMenuEntries().add(menuEntry);
compactBoostsOverlay.getMenuEntries().add(menuEntry);;
overlayManager.add(boostsOverlay); overlayManager.add(boostsOverlay);
overlayManager.add(compactBoostsOverlay);
updateShownSkills(); updateShownSkills();
Arrays.fill(lastSkillLevels, -1); Arrays.fill(lastSkillLevels, -1);
// Add infoboxes for everything at startup and then determine inside if it will be rendered // Add infoboxes for everything at startup and then determine inside if it will be rendered
infoBoxManager.addInfoBox(new StatChangeIndicator(true, ImageUtil.loadImageResource(getClass(), "debuffed.png"), this, config)); infoBoxManager.addInfoBox(new StatChangeIndicator(true, ImageUtil.loadImageResource(getClass(), "buffed.png"), this, config));
infoBoxManager.addInfoBox(new StatChangeIndicator(false, ImageUtil.loadImageResource(getClass(), "buffed.png"), this, config)); infoBoxManager.addInfoBox(new StatChangeIndicator(false, ImageUtil.loadImageResource(getClass(), "debuffed.png"), this, config));
for (final Skill skill : Skill.values()) for (final Skill skill : Skill.values())
{ {
@@ -134,7 +146,10 @@ public class BoostsPlugin extends Plugin
@Override @Override
protected void shutDown() throws Exception protected void shutDown() throws Exception
{ {
boostsOverlay.getMenuEntries().clear();
compactBoostsOverlay.getMenuEntries().clear();
overlayManager.remove(boostsOverlay); overlayManager.remove(boostsOverlay);
overlayManager.remove(compactBoostsOverlay);
infoBoxManager.removeIf(t -> t instanceof BoostIndicator || t instanceof StatChangeIndicator); infoBoxManager.removeIf(t -> t instanceof BoostIndicator || t instanceof StatChangeIndicator);
preserveBeenActive = false; preserveBeenActive = false;
lastChangeDown = -1; lastChangeDown = -1;

View File

@@ -0,0 +1,167 @@
/*
* Copyright (c) 2022, 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.boosts;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.Set;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Skill;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.components.TextComponent;
import net.runelite.client.util.ImageUtil;
class CompactBoostsOverlay extends Overlay
{
private static final int H_PADDING = 2;
private static final int V_PADDING = 1;
private static final int TEXT_WIDTH = 22;
private static final BufferedImage BUFFED = ImageUtil.loadImageResource(CompactBoostsOverlay.class, "buffedsmall.png");
private static final BufferedImage DEBUFFED = ImageUtil.loadImageResource(CompactBoostsOverlay.class, "debuffedsmall.png");
private final Client client;
private final BoostsConfig config;
private final BoostsPlugin plugin;
private final SkillIconManager skillIconManager;
private int curY;
private int maxX;
@Inject
private CompactBoostsOverlay(Client client, BoostsConfig config, BoostsPlugin plugin, SkillIconManager skillIconManager)
{
super(plugin);
this.client = client;
this.config = config;
this.plugin = plugin;
this.skillIconManager = skillIconManager;
setPosition(OverlayPosition.TOP_LEFT);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
final Set<Skill> boostedSkills = plugin.getSkillsToDisplay();
if (boostedSkills.isEmpty() || !config.compactDisplay())
{
return null;
}
curY = maxX = 0;
final FontMetrics fontMetrics = graphics.getFontMetrics();
final int fontHeight = fontMetrics.getHeight();
for (Skill skill : boostedSkills)
{
final int boosted = client.getBoostedSkillLevel(skill);
final int base = client.getRealSkillLevel(skill);
final int boost = boosted - base;
if (boost == 0)
{
continue;
}
drawBoost(graphics, fontMetrics, fontHeight,
skillIconManager.getSkillImage(skill, true),
getTextColor(boost),
getBoostText(boost, base, boosted));
}
int time = plugin.getChangeUpTicks();
if (time != -1)
{
drawBoost(graphics, fontMetrics, fontHeight,
BUFFED,
time < 10 ? Color.RED.brighter() : Color.WHITE,
Integer.toString(plugin.getChangeTime(time)));
}
time = plugin.getChangeDownTicks();
if (time != -1)
{
drawBoost(graphics, fontMetrics, fontHeight,
DEBUFFED,
time < 10 ? Color.RED.brighter() : Color.WHITE,
Integer.toString(plugin.getChangeTime(time)));
}
return new Dimension(maxX, curY);
}
private void drawBoost(Graphics2D graphics, FontMetrics fontMetrics, int fontHeight, BufferedImage image, Color color, String text)
{
graphics.drawImage(image, 0, curY, null);
final int stringWidth = fontMetrics.stringWidth(text);
final TextComponent textComponent = new TextComponent();
textComponent.setColor(color);
textComponent.setText(text);
textComponent.setOutline(true);
textComponent.setPosition(new Point(
image.getWidth()
+ H_PADDING // add a little bit of padding to get the text off the side of the image
+ (TEXT_WIDTH - stringWidth), // right justify to TEXT_WIDTH
// this really should be y + (image.getHeight() / 2) + (fontHeight / 2), but in practice
// it is the same
curY + fontHeight));
textComponent.render(graphics);
curY += Math.max(image.getHeight(), fontHeight)
+ V_PADDING; // padding to keep images from touching
maxX = Math.max(maxX, image.getWidth() + H_PADDING + TEXT_WIDTH);
}
private String getBoostText(int boost, int base, int boosted)
{
if (config.useRelativeBoost())
{
return boost > 0 ? "+" + boost : "-" + boost;
}
else
{
return Integer.toString(boosted);
}
}
private Color getTextColor(int boost)
{
if (boost < 0)
{
return new Color(238, 51, 51);
}
return boost <= config.boostThreshold() ? Color.YELLOW : Color.GREEN;
}
}

View File

@@ -29,7 +29,7 @@ import java.awt.image.BufferedImage;
import net.runelite.client.ui.overlay.infobox.InfoBox; import net.runelite.client.ui.overlay.infobox.InfoBox;
import net.runelite.client.ui.overlay.infobox.InfoBoxPriority; import net.runelite.client.ui.overlay.infobox.InfoBoxPriority;
public class StatChangeIndicator extends InfoBox class StatChangeIndicator extends InfoBox
{ {
private final boolean up; private final boolean up;
private final BoostsPlugin plugin; private final BoostsPlugin plugin;
@@ -61,6 +61,6 @@ public class StatChangeIndicator extends InfoBox
public boolean render() public boolean render()
{ {
final int time = up ? plugin.getChangeUpTicks() : plugin.getChangeDownTicks(); final int time = up ? plugin.getChangeUpTicks() : plugin.getChangeDownTicks();
return config.displayInfoboxes() && time != -1; return time != -1 && config.displayInfoboxes();
} }
} }

View File

@@ -59,6 +59,9 @@ public class EntityHiderPlugin extends Plugin
@Inject @Inject
private Hooks hooks; private Hooks hooks;
@Inject
private NpcUtil npcUtil;
private boolean hideOthers; private boolean hideOthers;
private boolean hideOthers2D; private boolean hideOthers2D;
private boolean hideFriends; private boolean hideFriends;
@@ -191,7 +194,7 @@ public class EntityHiderPlugin extends Plugin
} }
// dead npcs can also be interacting so prioritize it over the interacting check // dead npcs can also be interacting so prioritize it over the interacting check
if (NpcUtil.isDying(npc) && hideDeadNpcs) if (npcUtil.isDying(npc) && hideDeadNpcs)
{ {
return false; return false;
} }

View File

@@ -192,6 +192,9 @@ public class MenuEntrySwapperPlugin extends Plugin
@Inject @Inject
private ChatMessageManager chatMessageManager; private ChatMessageManager chatMessageManager;
@Inject
private NpcUtil npcUtil;
private boolean configuringShiftClick = false; private boolean configuringShiftClick = false;
private boolean configuringLeftClick = false; private boolean configuringLeftClick = false;
@@ -1285,7 +1288,7 @@ public class MenuEntrySwapperPlugin extends Plugin
.filter(e -> .filter(e ->
{ {
final NPC npc = e.getNpc(); final NPC npc = e.getNpc();
return npc == null || !NpcUtil.isDying(npc); return npc == null || !npcUtil.isDying(npc);
}) })
.toArray(MenuEntry[]::new); .toArray(MenuEntry[]::new);
if (oldEntries.length != newEntries.length) if (oldEntries.length != newEntries.length)

View File

@@ -28,6 +28,7 @@ package net.runelite.client.plugins.party;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Keybind;
@ConfigGroup(PartyConfig.GROUP) @ConfigGroup(PartyConfig.GROUP)
public interface PartyConfig extends Config public interface PartyConfig extends Config
@@ -37,7 +38,7 @@ public interface PartyConfig extends Config
@ConfigItem( @ConfigItem(
keyName = "pings", keyName = "pings",
name = "Pings", name = "Pings",
description = "Enables party pings (shift + left-click)", description = "Enables party pings",
position = 1 position = 1
) )
default boolean pings() default boolean pings()
@@ -60,13 +61,24 @@ public interface PartyConfig extends Config
keyName = "recolorNames", keyName = "recolorNames",
name = "Recolor names", name = "Recolor names",
description = "Recolor party members names based on unique color hash", description = "Recolor party members names based on unique color hash",
position = 4 position = 3
) )
default boolean recolorNames() default boolean recolorNames()
{ {
return true; return true;
} }
@ConfigItem(
keyName = "pingHotkey",
name = "Ping hotkey",
description = "Key to hold to send a tile ping",
position = 4
)
default Keybind pingHotkey()
{
return Keybind.NOT_SET;
}
@ConfigItem( @ConfigItem(
keyName = "previousPartyId", keyName = "previousPartyId",
name = "", name = "",

View File

@@ -45,7 +45,6 @@ import lombok.Getter;
import net.runelite.api.ChatMessageType; import net.runelite.api.ChatMessageType;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.GameState; import net.runelite.api.GameState;
import net.runelite.api.KeyCode;
import net.runelite.api.MenuAction; import net.runelite.api.MenuAction;
import net.runelite.api.MenuEntry; import net.runelite.api.MenuEntry;
import net.runelite.api.Player; import net.runelite.api.Player;
@@ -54,6 +53,7 @@ import net.runelite.api.SoundEffectID;
import net.runelite.api.Tile; import net.runelite.api.Tile;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.CommandExecuted; import net.runelite.api.events.CommandExecuted;
import net.runelite.api.events.FocusChanged;
import net.runelite.api.events.GameStateChanged; import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuOptionClicked; import net.runelite.api.events.MenuOptionClicked;
@@ -66,6 +66,7 @@ import net.runelite.client.events.ConfigChanged;
import net.runelite.client.events.OverlayMenuClicked; import net.runelite.client.events.OverlayMenuClicked;
import net.runelite.client.events.PartyChanged; import net.runelite.client.events.PartyChanged;
import net.runelite.client.events.PartyMemberAvatar; import net.runelite.client.events.PartyMemberAvatar;
import net.runelite.client.input.KeyManager;
import net.runelite.client.party.PartyMember; import net.runelite.client.party.PartyMember;
import net.runelite.client.party.PartyService; import net.runelite.client.party.PartyService;
import net.runelite.client.party.WSClient; import net.runelite.client.party.WSClient;
@@ -87,6 +88,7 @@ import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.worldmap.WorldMapPoint; import net.runelite.client.ui.overlay.worldmap.WorldMapPoint;
import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager; import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager;
import net.runelite.client.util.ColorUtil; import net.runelite.client.util.ColorUtil;
import net.runelite.client.util.HotkeyListener;
import net.runelite.client.util.ImageUtil; import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.Text; import net.runelite.client.util.Text;
@@ -128,6 +130,9 @@ public class PartyPlugin extends Plugin
@Inject @Inject
private ClientToolbar clientToolbar; private ClientToolbar clientToolbar;
@Inject
private KeyManager keyManager;
@Inject @Inject
@Named("developerMode") @Named("developerMode")
boolean developerMode; boolean developerMode;
@@ -145,6 +150,23 @@ public class PartyPlugin extends Plugin
private String lastCharacterName = ""; private String lastCharacterName = "";
private WorldPoint lastLocation; private WorldPoint lastLocation;
private final HotkeyListener hotkeyListener = new HotkeyListener(() -> config.pingHotkey())
{
@Override
public void hotkeyPressed()
{
hotkeyPressed = true;
}
@Override
public void hotkeyReleased()
{
hotkeyPressed = false;
}
};
private boolean hotkeyPressed = false;
@Override @Override
public void configure(Binder binder) public void configure(Binder binder)
{ {
@@ -168,6 +190,7 @@ public class PartyPlugin extends Plugin
clientToolbar.addNavigation(navButton); clientToolbar.addNavigation(navButton);
overlayManager.add(partyPingOverlay); overlayManager.add(partyPingOverlay);
keyManager.registerKeyListener(hotkeyListener);
wsClient.registerMessage(SkillUpdate.class); wsClient.registerMessage(SkillUpdate.class);
wsClient.registerMessage(TilePing.class); wsClient.registerMessage(TilePing.class);
wsClient.registerMessage(LocationUpdate.class); wsClient.registerMessage(LocationUpdate.class);
@@ -187,6 +210,7 @@ public class PartyPlugin extends Plugin
pendingTilePings.clear(); pendingTilePings.clear();
worldMapManager.removeIf(PartyWorldMapPoint.class::isInstance); worldMapManager.removeIf(PartyWorldMapPoint.class::isInstance);
overlayManager.remove(partyPingOverlay); overlayManager.remove(partyPingOverlay);
keyManager.unregisterKeyListener(hotkeyListener);
wsClient.unregisterMessage(SkillUpdate.class); wsClient.unregisterMessage(SkillUpdate.class);
wsClient.unregisterMessage(TilePing.class); wsClient.unregisterMessage(TilePing.class);
wsClient.unregisterMessage(LocationUpdate.class); wsClient.unregisterMessage(LocationUpdate.class);
@@ -200,6 +224,15 @@ public class PartyPlugin extends Plugin
return configManager.getConfig(PartyConfig.class); return configManager.getConfig(PartyConfig.class);
} }
@Subscribe
public void onFocusChanged(FocusChanged focusChanged)
{
if (!focusChanged.isFocused())
{
hotkeyPressed = false;
}
}
@Subscribe @Subscribe
public void onOverlayMenuClicked(OverlayMenuClicked event) public void onOverlayMenuClicked(OverlayMenuClicked event)
{ {
@@ -229,7 +262,7 @@ public class PartyPlugin extends Plugin
@Subscribe @Subscribe
public void onMenuOptionClicked(MenuOptionClicked event) public void onMenuOptionClicked(MenuOptionClicked event)
{ {
if (!client.isKeyPressed(KeyCode.KC_SHIFT) || client.isMenuOpen() || party.getMembers().isEmpty() || !config.pings()) if (!hotkeyPressed || client.isMenuOpen() || party.getMembers().isEmpty() || !config.pings())
{ {
return; return;
} }

View File

@@ -1,71 +0,0 @@
/*
* Copyright (c) 2018, Raqes <j.raqes@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.specialcounter;
import com.google.common.collect.Sets;
import java.util.Set;
import lombok.Getter;
import lombok.ToString;
import net.runelite.api.NpcID;
@Getter
@ToString
enum Boss
{
ABYSSAL_SIRE(NpcID.ABYSSAL_SIRE, NpcID.ABYSSAL_SIRE_5887, NpcID.ABYSSAL_SIRE_5888, NpcID.ABYSSAL_SIRE_5889, NpcID.ABYSSAL_SIRE_5890, NpcID.ABYSSAL_SIRE_5891, NpcID.ABYSSAL_SIRE_5908),
CALLISTO(NpcID.CALLISTO, NpcID.CALLISTO_6609),
CERBERUS(NpcID.CERBERUS, NpcID.CERBERUS_5863, NpcID.CERBERUS_5866),
CHAOS_ELEMENTAL(NpcID.CHAOS_ELEMENTAL, NpcID.CHAOS_ELEMENTAL_6505),
CORPOREAL_BEAST(NpcID.CORPOREAL_BEAST),
GENERAL_GRAARDOR(NpcID.GENERAL_GRAARDOR, NpcID.GENERAL_GRAARDOR_6494),
GIANT_MOLE(NpcID.GIANT_MOLE, NpcID.GIANT_MOLE_6499),
KALPHITE_QUEEN(NpcID.KALPHITE_QUEEN, NpcID.KALPHITE_QUEEN_963, NpcID.KALPHITE_QUEEN_965, NpcID.KALPHITE_QUEEN_4303, NpcID.KALPHITE_QUEEN_4304, NpcID.KALPHITE_QUEEN_6500, NpcID.KALPHITE_QUEEN_6501),
KING_BLACK_DRAGON(NpcID.KING_BLACK_DRAGON, NpcID.KING_BLACK_DRAGON_2642, NpcID.KING_BLACK_DRAGON_6502),
KRIL_TSUROTH(NpcID.KRIL_TSUTSAROTH, NpcID.KRIL_TSUTSAROTH_6495),
VENETENATIS(NpcID.VENENATIS, NpcID.VENENATIS_6610),
VETION(NpcID.VETION, NpcID.VETION_REBORN),
ALCHEMICAL_HYDRA(NpcID.ALCHEMICAL_HYDRA, NpcID.ALCHEMICAL_HYDRA_8616, NpcID.ALCHEMICAL_HYDRA_8617, NpcID.ALCHEMICAL_HYDRA_8618, NpcID.ALCHEMICAL_HYDRA_8619, NpcID.ALCHEMICAL_HYDRA_8620, NpcID.ALCHEMICAL_HYDRA_8621, NpcID.ALCHEMICAL_HYDRA_8622, NpcID.ALCHEMICAL_HYDRA_8634);
private final Set<Integer> ids;
Boss(Integer... ids)
{
this.ids = Sets.newHashSet(ids);
}
static Boss getBoss(int id)
{
for (Boss boss : values())
{
if (boss.ids.contains(id))
{
return boss;
}
}
return null;
}
}

View File

@@ -48,6 +48,7 @@ import net.runelite.api.Item;
import net.runelite.api.ItemContainer; import net.runelite.api.ItemContainer;
import net.runelite.api.NPC; import net.runelite.api.NPC;
import net.runelite.api.NpcID; import net.runelite.api.NpcID;
import net.runelite.api.ScriptID;
import net.runelite.api.VarPlayer; import net.runelite.api.VarPlayer;
import net.runelite.api.coords.WorldPoint; import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.CommandExecuted; import net.runelite.api.events.CommandExecuted;
@@ -56,6 +57,7 @@ import net.runelite.api.events.GameTick;
import net.runelite.api.events.HitsplatApplied; import net.runelite.api.events.HitsplatApplied;
import net.runelite.api.events.InteractingChanged; import net.runelite.api.events.InteractingChanged;
import net.runelite.api.events.NpcDespawned; import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.ScriptPostFired;
import net.runelite.api.events.VarbitChanged; import net.runelite.api.events.VarbitChanged;
import net.runelite.client.Notifier; import net.runelite.client.Notifier;
import net.runelite.client.callback.ClientThread; import net.runelite.client.callback.ClientThread;
@@ -101,7 +103,7 @@ public class SpecialCounterPlugin extends Plugin
private boolean wasInInstance; private boolean wasInInstance;
private SpecialWeapon specialWeapon; private SpecialWeapon specialWeapon;
private final Set<Integer> interactedNpcIds = new HashSet<>(); private final Set<Integer> interactedNpcIndexes = new HashSet<>();
private final SpecialCounter[] specialCounter = new SpecialCounter[SpecialWeapon.values().length]; private final SpecialCounter[] specialCounter = new SpecialCounter[SpecialWeapon.values().length];
@Getter(AccessLevel.PACKAGE) @Getter(AccessLevel.PACKAGE)
@@ -156,7 +158,7 @@ public class SpecialCounterPlugin extends Plugin
specialPercentage = -1; specialPercentage = -1;
lastSpecTarget = null; lastSpecTarget = null;
lastSpecTick = -1; lastSpecTick = -1;
interactedNpcIds.clear(); interactedNpcIndexes.clear();
} }
@Override @Override
@@ -166,7 +168,17 @@ public class SpecialCounterPlugin extends Plugin
overlayManager.remove(playerInfoDropOverlay); overlayManager.remove(playerInfoDropOverlay);
wsClient.unregisterMessage(SpecialCounterUpdate.class); wsClient.unregisterMessage(SpecialCounterUpdate.class);
} }
@Subscribe
public void onScriptPostFired(ScriptPostFired event)
{
if (event.getScriptId() == ScriptID.TOB_HUD_SOTETSEG_FADE)
{
log.debug("Resetting spec counter as sotetseg maze script was ran");
removeCounters();
}
}
@Subscribe @Subscribe
public void onGameTick(GameTick event) public void onGameTick(GameTick event)
{ {
@@ -275,6 +287,7 @@ public class SpecialCounterPlugin extends Plugin
NPC npc = (NPC) target; NPC npc = (NPC) target;
int interactingId = npc.getId(); int interactingId = npc.getId();
int npcIndex = npc.getIndex();
if (IGNORED_NPCS.contains(interactingId)) if (IGNORED_NPCS.contains(interactingId))
{ {
@@ -282,10 +295,10 @@ public class SpecialCounterPlugin extends Plugin
} }
// If this is a new NPC reset the counters // If this is a new NPC reset the counters
if (!interactedNpcIds.contains(interactingId)) if (!interactedNpcIndexes.contains(npcIndex))
{ {
removeCounters(); removeCounters();
addInteracting(interactingId); interactedNpcIndexes.add(npcIndex);
} }
if (wasSpec && specialWeapon != null && hitsplat.getAmount() > 0) if (wasSpec && specialWeapon != null && hitsplat.getAmount() > 0)
@@ -300,7 +313,7 @@ public class SpecialCounterPlugin extends Plugin
if (!party.getMembers().isEmpty()) if (!party.getMembers().isEmpty())
{ {
final SpecialCounterUpdate specialCounterUpdate = new SpecialCounterUpdate(interactingId, specialWeapon, hit, client.getWorld(), localPlayerId); final SpecialCounterUpdate specialCounterUpdate = new SpecialCounterUpdate(npcIndex, specialWeapon, hit, client.getWorld(), localPlayerId);
specialCounterUpdate.setMemberId(party.getLocalMember().getMemberId()); specialCounterUpdate.setMemberId(party.getLocalMember().getMemberId());
party.send(specialCounterUpdate); party.send(specialCounterUpdate);
} }
@@ -309,18 +322,6 @@ public class SpecialCounterPlugin extends Plugin
} }
} }
private void addInteracting(int npcId)
{
interactedNpcIds.add(npcId);
// Add alternate forms of bosses
final Boss boss = Boss.getBoss(npcId);
if (boss != null)
{
interactedNpcIds.addAll(boss.getIds());
}
}
@Subscribe @Subscribe
public void onNpcDespawned(NpcDespawned npcDespawned) public void onNpcDespawned(NpcDespawned npcDespawned)
{ {
@@ -331,7 +332,7 @@ public class SpecialCounterPlugin extends Plugin
lastSpecTarget = null; lastSpecTarget = null;
} }
if (actor.isDead() && interactedNpcIds.contains(actor.getId())) if (actor.isDead() && interactedNpcIndexes.contains(actor.getIndex()))
{ {
removeCounters(); removeCounters();
} }
@@ -340,7 +341,8 @@ public class SpecialCounterPlugin extends Plugin
@Subscribe @Subscribe
public void onSpecialCounterUpdate(SpecialCounterUpdate event) public void onSpecialCounterUpdate(SpecialCounterUpdate event)
{ {
if (party.getLocalMember().getMemberId().equals(event.getMemberId())) if (party.getLocalMember().getMemberId().equals(event.getMemberId())
|| event.getWorld() != client.getWorld())
{ {
return; return;
} }
@@ -354,13 +356,13 @@ public class SpecialCounterPlugin extends Plugin
clientThread.invoke(() -> clientThread.invoke(() ->
{ {
// If not interacting with any npcs currently, add to interacting list // If not interacting with any npcs currently, add to interacting list
if (interactedNpcIds.isEmpty()) if (interactedNpcIndexes.isEmpty())
{ {
addInteracting(event.getNpcId()); interactedNpcIndexes.add(event.getNpcIndex());
} }
// Otherwise we only add the count if it is against a npc we are already tracking // Otherwise we only add the count if it is against a npc we are already tracking
if (interactedNpcIds.contains(event.getNpcId())) if (interactedNpcIndexes.contains(event.getNpcIndex()))
{ {
if (config.infobox()) if (config.infobox())
{ {
@@ -368,10 +370,7 @@ public class SpecialCounterPlugin extends Plugin
} }
} }
if (event.getWorld() == client.getWorld()) playerInfoDrops.add(createSpecInfoDrop(event.getWeapon(), event.getHit(), event.getPlayerId()));
{
playerInfoDrops.add(createSpecInfoDrop(event.getWeapon(), event.getHit(), event.getPlayerId()));
}
}); });
} }
@@ -453,7 +452,7 @@ public class SpecialCounterPlugin extends Plugin
private void removeCounters() private void removeCounters()
{ {
interactedNpcIds.clear(); interactedNpcIndexes.clear();
for (int i = 0; i < specialCounter.length; ++i) for (int i = 0; i < specialCounter.length; ++i)
{ {

View File

@@ -32,7 +32,7 @@ import net.runelite.client.party.messages.PartyMemberMessage;
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class SpecialCounterUpdate extends PartyMemberMessage public class SpecialCounterUpdate extends PartyMemberMessage
{ {
private final int npcId; private final int npcIndex;
private final SpecialWeapon weapon; private final SpecialWeapon weapon;
private final int hit; private final int hit;
private final int world; private final int world;

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 B

View File

@@ -48,6 +48,7 @@ import java.util.Set;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.client.RuneLite; import net.runelite.client.RuneLite;
import net.runelite.client.RuneLiteModule; import net.runelite.client.RuneLiteModule;
import net.runelite.client.RuntimeConfig;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
import net.runelite.client.eventbus.EventBus; import net.runelite.client.eventbus.EventBus;
@@ -93,7 +94,7 @@ public class PluginManagerTest
.thenThrow(new RuntimeException("in plugin manager test")); .thenThrow(new RuntimeException("in plugin manager test"));
Injector injector = Guice.createInjector(Modules Injector injector = Guice.createInjector(Modules
.override(new RuneLiteModule(okHttpClient, () -> null, () -> null, true, false, .override(new RuneLiteModule(okHttpClient, () -> null, () -> mock(RuntimeConfig.class), true, false,
RuneLite.DEFAULT_SESSION_FILE, RuneLite.DEFAULT_SESSION_FILE,
RuneLite.DEFAULT_CONFIG_FILE)) RuneLite.DEFAULT_CONFIG_FILE))
.with(BoundFieldModule.of(this))); .with(BoundFieldModule.of(this)));

View File

@@ -238,7 +238,10 @@ public class SpecialCounterPluginTest
{ {
NPC targetA = mock(NPC.class); NPC targetA = mock(NPC.class);
NPC targetB = mock(NPC.class); NPC targetB = mock(NPC.class);
when(targetB.getId()).thenReturn(1); // a different npc type
// a different npc type
when(targetB.getId()).thenReturn(1);
when(targetB.getIndex()).thenReturn(1);
Player player = mock(Player.class); Player player = mock(Player.class);
when(client.getLocalPlayer()).thenReturn(player); when(client.getLocalPlayer()).thenReturn(player);