From b08c39854bdd4a44ff3ea6a84b9408dd77e70061 Mon Sep 17 00:00:00 2001 From: honeyhoney Date: Mon, 20 Nov 2017 21:05:52 +0000 Subject: [PATCH 1/3] Added support for hiding widgets --- .../src/main/java/net/runelite/api/widgets/Widget.java | 2 ++ runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java | 3 +++ 2 files changed, 5 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index af983ccd6b..3256a9c405 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -66,6 +66,8 @@ public interface Widget boolean isHidden(); + void setHidden(boolean hidden); + Point getCanvasLocation(); int getWidth(); diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java index c8b4b5e49a..fafa22496d 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java @@ -97,6 +97,9 @@ public interface RSWidget extends Widget @Import("isHidden") boolean isRSHidden(); + @Import("isHidden") + void setHidden(boolean hidden); + @Import("index") int getIndex(); From ea810a344eb6fefa5c288c5d208dfdd372fd101a Mon Sep 17 00:00:00 2001 From: honeyhoney Date: Mon, 20 Nov 2017 21:06:34 +0000 Subject: [PATCH 2/3] Added combat style widget info --- .../main/java/net/runelite/api/widgets/WidgetID.java | 12 ++++++++++++ .../java/net/runelite/api/widgets/WidgetInfo.java | 12 ++++++++++++ 2 files changed, 24 insertions(+) diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index 17d2fbf227..d5ef8d902c 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -189,6 +189,18 @@ class WidgetID { static final int WEAPON_NAME = 1; static final int LEVEL = 2; + static final int STYLE_ONE = 3; + static final int STYLE_TWO = 7; + static final int STYLE_THREE = 11; + static final int STYLE_FOUR = 15; + static final int SPELLS = 19; + static final int DEFENSIVE_SPELL_BOX = 20; + static final int DEFENSIVE_SPELL_ICON = 21; + static final int DEFENSIVE_SPELL_SHIELD = 22; + static final int DEFENSIVE_SPELL_TEXT = 23; + static final int SPELL_BOX = 24; + static final int SPELL_ICON = 25; + static final int SPELL_TEXT = 26; } static class VolcanicMine diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index 2818f1b7c0..3f1e7cbd60 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -99,6 +99,18 @@ public enum WidgetInfo PRAYER_PROTECT_FROM_MISSILES(WidgetID.PRAYER_GROUP_ID, WidgetID.Prayer.PROTECT_FROM_MISSILES), COMBAT_LEVEL(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.LEVEL), + COMBAT_STYLE_ONE(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_ONE), + COMBAT_STYLE_TWO(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_TWO), + COMBAT_STYLE_THREE(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_THREE), + COMBAT_STYLE_FOUR(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.STYLE_FOUR), + COMBAT_SPELLS(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPELLS), + COMBAT_DEFENSIVE_SPELL_BOX(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.DEFENSIVE_SPELL_BOX), + COMBAT_DEFENSIVE_SPELL_ICON(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.DEFENSIVE_SPELL_ICON), + COMBAT_DEFENSIVE_SPELL_SHIELD(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.DEFENSIVE_SPELL_SHIELD), + COMBAT_DEFENSIVE_SPELL_TEXT(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.DEFENSIVE_SPELL_TEXT), + COMBAT_SPELL_BOX(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPELL_BOX), + COMBAT_SPELL_ICON(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPELL_ICON), + COMBAT_SPELL_TEXT(WidgetID.COMBAT_GROUP_ID, WidgetID.Combat.SPELL_TEXT), DIALOG_NPC_NAME(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.NAME), DIALOG_NPC_TEXT(WidgetID.DIALOG_NPC_GROUP_ID, WidgetID.DialogNPC.TEXT), From 98380f7803db56917c4db18b2034fc7ff0aecc8f Mon Sep 17 00:00:00 2001 From: honeyhoney Date: Mon, 20 Nov 2017 21:07:02 +0000 Subject: [PATCH 3/3] Added attack style warnings and option to remove warned attack styles --- .../AttackIndicatorConfig.java | 72 +++++- .../AttackIndicatorOverlay.java | 9 +- .../AttackIndicatorPlugin.java | 210 +++++++++++++++++- .../plugins/attackindicator/AttackStyle.java | 27 ++- .../plugins/attackindicator/WeaponType.java | 2 +- 5 files changed, 299 insertions(+), 21 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorConfig.java index 740674fe5c..df96d31219 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorConfig.java @@ -29,7 +29,7 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; @ConfigGroup( - keyName = "attackindicator", + keyName = "attackIndicator", name = "Attack Indicators", description = "Configuration for the attack indicator plugin" ) @@ -37,12 +37,78 @@ public interface AttackIndicatorConfig extends Config { @ConfigItem( keyName = "enabled", - name = "Enabled", - description = "Configures whether or not the attack indicator overlay is displayed" + name = "Show attack style", + description = "Configures whether or not the attack indicator overlay is displayed", + position = 1 ) default boolean enabled() { return true; } + @ConfigItem( + keyName = "warnForDefensive", + name = "Warn for defensive", + description = "Configures whether or not users are warned for selecting a defensive combat option", + position = 2 + ) + default boolean warnForDefensive() + { + return false; + } + + @ConfigItem( + keyName = "warnForAttack", + name = "Warn for attack", + description = "Configures whether or not users are warned for selecting an attack combat option", + position = 3 + ) + default boolean warnForAttack() + { + return false; + } + + @ConfigItem( + keyName = "warnForStrength", + name = "Warn for strength", + description = "Configures whether or not users are warned for selecting a strength combat option", + position = 4 + ) + default boolean warnForStrength() + { + return false; + } + + @ConfigItem( + keyName = "warnForRanged", + name = "Warn for ranged", + description = "Configures whether or not users are warned for selecting a ranged combat option", + position = 5 + ) + default boolean warnForRanged() + { + return false; + } + + @ConfigItem( + keyName = "warnForMagic", + name = "Warn for magic", + description = "Configures whether or not users are warned for selecting a magic combat option", + position = 6 + ) + default boolean warnForMagic() + { + return false; + } + + @ConfigItem( + keyName = "removeWarnedStyles", + name = "Remove warned styles", + description = "Configures whether or not warned styles are removed from the combat options tab", + position = 7 + ) + default boolean removeWarnedStyles() + { + return false; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorOverlay.java index 34234965cd..f002746dab 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorOverlay.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorOverlay.java @@ -105,7 +105,14 @@ public class AttackIndicatorOverlay extends Overlay // Render text with shadow graphics.setColor(Color.BLACK); graphics.drawString(attackStyleString, anchor.x - background.width + 3, anchor.y); - graphics.setColor(Color.WHITE); + if (plugin.isWarnedSkillSelected()) + { + graphics.setColor(Color.RED); + } + else + { + graphics.setColor(Color.WHITE); + } graphics.drawString(attackStyleString, anchor.x - background.width + 2, anchor.y - 1); return null; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorPlugin.java index efb6b2ae0e..5a7fbde05e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackIndicatorPlugin.java @@ -24,33 +24,52 @@ */ package net.runelite.client.plugins.attackindicator; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import com.google.common.eventbus.Subscribe; import com.google.inject.Binder; import com.google.inject.Provides; +import java.time.temporal.ChronoUnit; +import java.util.HashSet; +import java.util.Set; import javax.annotation.Nullable; import javax.inject.Inject; import net.runelite.api.Client; +import net.runelite.api.Skill; import net.runelite.api.Varbits; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.config.ConfigManager; +import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.VarbitChanged; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; -import static net.runelite.client.plugins.attackindicator.AttackStyle.CASTING; -import static net.runelite.client.plugins.attackindicator.AttackStyle.DEFENSIVE_CASTING; +import static net.runelite.client.plugins.attackindicator.AttackStyle.*; +import net.runelite.client.task.Schedule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; @PluginDescriptor( name = "Attack indicator plugin" ) public class AttackIndicatorPlugin extends Plugin { - @Inject - @Nullable - Client client; + private static final Logger logger = LoggerFactory.getLogger(AttackIndicatorPlugin.class); private int attackStyleVarbit = -1; private int equippedWeaponTypeVarbit = -1; private int castingModeVarbit = -1; private AttackStyle attackStyle; + private final Set warnedSkills = new HashSet<>(); + private boolean warnedSkillSelected = false; + private final Table widgetsToHide = HashBasedTable.create(); + + @Inject + @Nullable + Client client; + + @Inject + AttackIndicatorConfig config; @Inject AttackIndicatorOverlay overlay; @@ -78,6 +97,43 @@ public class AttackIndicatorPlugin extends Plugin return attackStyle; } + public boolean isWarnedSkillSelected() + { + return warnedSkillSelected; + } + + @Override + protected void startUp() throws Exception + { + updateWarnedSkills(config.warnForAttack(), Skill.ATTACK); + updateWarnedSkills(config.warnForStrength(), Skill.STRENGTH); + updateWarnedSkills(config.warnForDefensive(), Skill.DEFENCE); + updateWarnedSkills(config.warnForRanged(), Skill.RANGED); + updateWarnedSkills(config.warnForMagic(), Skill.MAGIC); + } + + @Schedule( + period = 600, + unit = ChronoUnit.MILLIS + ) + public void hideWidgets() + { + if (widgetsToHide == null) + { + return; + } + + WeaponType equippedWeaponType = WeaponType.getWeaponType(equippedWeaponTypeVarbit); + + if (widgetsToHide.containsRow(equippedWeaponType)) + { + for (WidgetInfo widgetKey : widgetsToHide.row(equippedWeaponType).keySet()) + { + hideWidget(client.getWidget(widgetKey), widgetsToHide.get(equippedWeaponType, widgetKey)); + } + } + } + @Subscribe public void onAttackStyleChange(VarbitChanged event) { @@ -86,6 +142,7 @@ public class AttackIndicatorPlugin extends Plugin attackStyleVarbit = client.getSetting(Varbits.ATTACK_STYLE); updateAttackStyle(client.getSetting(Varbits.EQUIPPED_WEAPON_TYPE), attackStyleVarbit, client.getSetting(Varbits.DEFENSIVE_CASTING_MODE)); + updateWarning(false); } } @@ -97,6 +154,7 @@ public class AttackIndicatorPlugin extends Plugin equippedWeaponTypeVarbit = client.getSetting(Varbits.EQUIPPED_WEAPON_TYPE); updateAttackStyle(equippedWeaponTypeVarbit, client.getSetting(Varbits.ATTACK_STYLE), client.getSetting(Varbits.DEFENSIVE_CASTING_MODE)); + updateWarning(true); } } @@ -108,6 +166,41 @@ public class AttackIndicatorPlugin extends Plugin castingModeVarbit = client.getSetting(Varbits.DEFENSIVE_CASTING_MODE); updateAttackStyle(client.getSetting(Varbits.EQUIPPED_WEAPON_TYPE), client.getSetting(Varbits.ATTACK_STYLE), castingModeVarbit); + updateWarning(false); + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getGroup().equals("attackIndicator")) + { + boolean enabled = event.getNewValue().equals("true"); + switch (event.getKey()) + { + case "enabled": + break; + case "warnForDefensive": + updateWarnedSkills(enabled, Skill.DEFENCE); + break; + case "warnForAttack": + updateWarnedSkills(enabled, Skill.ATTACK); + break; + case "warnForStrength": + updateWarnedSkills(enabled, Skill.STRENGTH); + break; + case "warnForRanged": + updateWarnedSkills(enabled, Skill.RANGED); + break; + case "warnForMagic": + updateWarnedSkills(enabled, Skill.MAGIC); + break; + case "removeWarnedStyles": + hideWarnedStyles(enabled); + break; + default: + logger.warn("Unreachable default case for config keys"); + } } } @@ -119,13 +212,116 @@ public class AttackIndicatorPlugin extends Plugin attackStyle = attackStyles[attackStyleIndex]; if (attackStyle == null) { - return; + attackStyle = OTHER; } - if ((attackStyle == CASTING) && (castingMode == 1)) + else if ((attackStyle == CASTING) && (castingMode == 1)) { attackStyle = DEFENSIVE_CASTING; } } } + private void updateWarnedSkills(boolean enabled, Skill skill) + { + if (enabled) + { + warnedSkills.remove(skill); + warnedSkills.add(skill); + } + else + { + warnedSkills.remove(skill); + } + updateWarning(false); + } + + private void updateWarning(boolean weaponSwitch) + { + warnedSkillSelected = false; + if (attackStyle != null) + { + for (Skill skill : attackStyle.getSkills()) + { + if (warnedSkills.contains(skill)) + { + if (weaponSwitch) + { + // TODO : chat message to warn players that their weapon switch also caused an unwanted attack style change + } + warnedSkillSelected = true; + break; + } + } + } + hideWarnedStyles(config.removeWarnedStyles()); + } + + private void hideWarnedStyles(boolean enabled) + { + WeaponType equippedWeaponType = WeaponType.getWeaponType(equippedWeaponTypeVarbit); + if (equippedWeaponType == null) + { + return; + } + + AttackStyle[] attackStyles = equippedWeaponType.getAttackStyles(); + + // Iterate over attack styles + for (int i = 0; i < attackStyles.length; i++) + { + if (attackStyles[i] == null) + { + continue; + } + + boolean warnedSkill = false; + for (Skill skill : attackStyles[i].getSkills()) + { + if (warnedSkills.contains(skill)) + { + warnedSkill = true; + break; + } + } + + // Magic staves defensive casting mode + if (equippedWeaponType == WeaponType.TYPE_18) + { + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_DEFENSIVE_SPELL_BOX, enabled && (warnedSkills.contains(Skill.DEFENCE) || warnedSkill)); + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_DEFENSIVE_SPELL_ICON, enabled && (warnedSkills.contains(Skill.DEFENCE) || warnedSkill)); + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_DEFENSIVE_SPELL_SHIELD, enabled && (warnedSkills.contains(Skill.DEFENCE) || warnedSkill)); + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_DEFENSIVE_SPELL_TEXT, enabled && (warnedSkills.contains(Skill.DEFENCE) || warnedSkill)); + } + + // Remove appropriate combat option + switch (i) + { + case 0: + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_STYLE_ONE, enabled && warnedSkill); + break; + case 1: + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_STYLE_TWO, enabled && warnedSkill); + break; + case 2: + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_STYLE_THREE, enabled && warnedSkill); + break; + case 3: + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_STYLE_FOUR, enabled && warnedSkill); + break; + case 4: + widgetsToHide.put(equippedWeaponType, WidgetInfo.COMBAT_SPELLS, enabled && warnedSkill); + break; + default: + logger.warn("Unreachable default case for equipped weapon type attack styles"); + } + } + } + + private void hideWidget(Widget widget, boolean hidden) + { + if (widget != null) + { + widget.setHidden(hidden); + } + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackStyle.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackStyle.java index a3eaea9afa..7f867ed051 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackStyle.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/AttackStyle.java @@ -24,27 +24,36 @@ */ package net.runelite.client.plugins.attackindicator; +import net.runelite.api.Skill; + public enum AttackStyle { - ACCURATE("Accurate"), - AGGRESSIVE("Aggressive"), - DEFENSIVE("Defensive"), - CONTROLLED("Controlled"), - RANGING("Ranging"), - LONGRANGE("Longrange"), - CASTING("Casting"), - DEFENSIVE_CASTING("Defensive Casting"), + ACCURATE("Accurate", Skill.ATTACK), + AGGRESSIVE("Aggressive", Skill.STRENGTH), + DEFENSIVE("Defensive", Skill.DEFENCE), + CONTROLLED("Controlled", Skill.ATTACK, Skill.STRENGTH, Skill.DEFENCE), + RANGING("Ranging", Skill.RANGED), + LONGRANGE("Longrange", Skill.RANGED, Skill.DEFENCE), + CASTING("Casting", Skill.MAGIC), + DEFENSIVE_CASTING("Defensive Casting", Skill.MAGIC, Skill.DEFENCE), OTHER("Other"); private final String name; + private final Skill[] skills; - AttackStyle(String name) + AttackStyle(String name, Skill... skills) { this.name = name; + this.skills = skills; } public String getName() { return name; } + + public Skill[] getSkills() + { + return skills; + } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/WeaponType.java b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/WeaponType.java index 5283fc06cd..7ecf64cb3b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/WeaponType.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/attackindicator/WeaponType.java @@ -37,7 +37,7 @@ public enum WeaponType TYPE_4(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), TYPE_5(RANGING, RANGING, null, LONGRANGE), TYPE_6(AGGRESSIVE, RANGING, DEFENSIVE_CASTING, null), - TYPE_7(RANGING, RANGING, null, DEFENSIVE_CASTING), + TYPE_7(RANGING, RANGING, null, LONGRANGE), TYPE_8(OTHER, AGGRESSIVE, null, null), TYPE_9(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE), TYPE_10(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE),