Changes 2 (#43)
* Initial commit for maxhit plugin
* WIP: Magic max hit calculator
* Add chance to obtain a Unique from Chambers of Xeric
Based on the formula from the wiki. Does not handle >80% chance properly (it should go into a second item)
* MaxHit Refactor a lot for magic max hit
* Wip: refactoring
* Pest Control Update
* Pest Control: Add Intermediate portals
* Revert "Remove raids points overlay"
This reverts commit fbd3ea6202.
* Wip: refactoring
* Fixed WidgetInfo merge issue
* Fixed trident
* Implement range
* Refactored according to intellij analyzer
* Run checkstyle from xml and fix code style issues
* Fix copyright
* Replace item names with item id's
* Code cleanup with reformat code
* Fixed checkstyle
* Use game slotitem
* Use game slotitem
* Fixed prayer bonus
* Looked up value for saradomin strike
* Fixed prayer bonus
* Fixed surge spell id's
* Fixed magix max hit tests
* Fixed rounding after obisidian
* Fix dharok custom formula
* Add melee max hit
* Refactored spellbonus items for magic
* Added voidknight
* Use boosted skill levels and add copyright
* Add accurate attack style for ranging
* Add range Tests
* Cleanup code
* Cleanup code
* Rename calculate methods to be more distinguishable
* Add parenthesis to dharok maxhit formula for clarification
* Fix widgetinfo merge
* Remove print in MaxHitPlugin
* Make sure an Item is not null when checking if the player is wearing it.
* Add daily notification for collection of ogre arrows from Rantz.
Add varbit for rantz arrow collection
Fix continuation indent settings
Group ifs to single check.
* Refactor all relevant daily checks to have grouped if check.
Further refactor grouped ifs
* Adds type
* Raids point overlay
This commit is contained in:
@@ -372,6 +372,7 @@ public enum Varbits {
|
||||
DAILY_ESSENCE_COLLECTED(4547),
|
||||
DAILY_RUNES_COLLECTED(4540),
|
||||
DAILY_SAND_COLLECTED(4549),
|
||||
DAILY_ARROWS_STATE(4563),
|
||||
DAILY_FLAX_STATE(4559),
|
||||
/**
|
||||
* This varbit tracks how much bonemeal has been redeemed from Robin
|
||||
@@ -481,6 +482,14 @@ public enum Varbits {
|
||||
*/
|
||||
GE_OFFER_CREATION_TYPE(4397),
|
||||
|
||||
|
||||
/*
|
||||
* Spells being auto-casted
|
||||
*
|
||||
* */
|
||||
AUTO_CAST_SPELL(276),
|
||||
|
||||
|
||||
/**
|
||||
* The active tab within the quest interface
|
||||
*/
|
||||
|
||||
@@ -55,6 +55,8 @@ public class WidgetID
|
||||
public static final int DIARY_GROUP_ID = 259;
|
||||
public static final int PEST_CONTROL_BOAT_GROUP_ID = 407;
|
||||
public static final int PEST_CONTROL_GROUP_ID = 408;
|
||||
public static final int PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID = 243;
|
||||
public static final int PEST_CONTROL_DIALOG_GROUP_ID = 229;
|
||||
public static final int CLAN_CHAT_GROUP_ID = 7;
|
||||
public static final int MINIMAP_GROUP_ID = 160;
|
||||
public static final int LOGIN_CLICK_TO_PLAY_GROUP_ID = 378;
|
||||
@@ -127,6 +129,7 @@ public class WidgetID
|
||||
public static final int FULLSCREEN_MAP_GROUP_ID = 165;
|
||||
public static final int QUESTLIST_GROUP_ID = 399;
|
||||
public static final int SKILLS_GROUP_ID = 320;
|
||||
public static final int EQUIPMENT_PAGE_GROUP_ID = 84;
|
||||
public static final int QUESTTAB_GROUP_ID = 629;
|
||||
public static final int MUSIC_GROUP_ID = 239;
|
||||
public static final int MUSICTAB_GROUP_ID = 239;
|
||||
@@ -164,12 +167,32 @@ public class WidgetID
|
||||
static class PestControlBoat
|
||||
{
|
||||
static final int INFO = 3;
|
||||
|
||||
static final int NEXT_DEPARTURE = 4;
|
||||
static final int PLAYERS_READY = 5;
|
||||
static final int POINTS = 6;
|
||||
}
|
||||
|
||||
static class PestControlExchangeWindow
|
||||
{
|
||||
static final int ITEM_LIST = 2;
|
||||
static final int BOTTOM = 5;
|
||||
static final int POINTS = 8;
|
||||
static final int CONFIRM_BUTTON = 6;
|
||||
}
|
||||
|
||||
static class PestControlDialog
|
||||
{
|
||||
static final int TEXT = 1;
|
||||
static final int CONTINUE = 2;
|
||||
}
|
||||
|
||||
static class PestControl
|
||||
{
|
||||
static final int INFO = 3;
|
||||
|
||||
static final int TIME = 6;
|
||||
|
||||
static final int ACTIVITY_BAR = 12;
|
||||
static final int ACTIVITY_PROGRESS = 14;
|
||||
|
||||
@@ -675,6 +698,28 @@ public class WidgetID
|
||||
static final int DESTROY_ITEM_NO = 3;
|
||||
}
|
||||
|
||||
static class EquipmentWidgetIdentifiers
|
||||
{
|
||||
static final int EQUIP_YOUR_CHARACTER = 3;
|
||||
static final int STAB_ATTACK_BONUS = 23;
|
||||
static final int SLASH_ATTACK_BONUS = 24;
|
||||
static final int CRUSH_ATTACK_BONUS = 25;
|
||||
static final int MAGIC_ATTACK_BONUS = 26;
|
||||
static final int RANGED_ATTACK_BONUS = 27;
|
||||
static final int STAB_DEFENCE_BONUS = 29;
|
||||
static final int SLASH_DEFENCE_BONUS = 30;
|
||||
static final int CRUSH_DEFENCE_BONUS = 31;
|
||||
static final int MAGIC_DEFENCE_BONUS = 32;
|
||||
static final int RANGED_DEFENCE_BONUS = 33;
|
||||
static final int MELEE_STRENGTH = 35;
|
||||
static final int RANGED_STRENGTH = 36;
|
||||
static final int MAGIC_DAMAGE = 37;
|
||||
static final int PRAYER_BONUS = 38;
|
||||
static final int UNDEAD_DAMAGE_BONUS = 40;
|
||||
static final int SLAYER_DAMAGE_BONUS = 41;
|
||||
static final int WEIGHT = 43;
|
||||
}
|
||||
|
||||
static class VarrockMuseum
|
||||
{
|
||||
static final int VARROCK_MUSEUM_QUESTION = 28;
|
||||
|
||||
@@ -83,8 +83,14 @@ public enum WidgetInfo
|
||||
DIARY_QUEST_WIDGET_TITLE(WidgetID.DIARY_QUEST_GROUP_ID, WidgetID.Diary.DIARY_TITLE),
|
||||
DIARY_QUEST_WIDGET_TEXT(WidgetID.DIARY_QUEST_GROUP_ID, WidgetID.Diary.DIARY_TEXT),
|
||||
|
||||
PEST_CONTROL_DIALOG(WidgetID.PEST_CONTROL_DIALOG_GROUP_ID, 0),
|
||||
PEST_CONTROL_DIALOG_TEXT(WidgetID.PEST_CONTROL_DIALOG_GROUP_ID, WidgetID.PestControlDialog.TEXT),
|
||||
PEST_CONTROL_EXCHANGE_WINDOW(WidgetID.PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID, 0),
|
||||
PEST_CONTROL_EXCHANGE_WINDOW_POINTS(WidgetID.PEST_CONTROL_EXCHANGE_WINDOW_GROUP_ID, WidgetID.PestControlExchangeWindow.POINTS),
|
||||
PEST_CONTROL_BOAT_INFO(WidgetID.PEST_CONTROL_BOAT_GROUP_ID, WidgetID.PestControlBoat.INFO),
|
||||
PEST_CONTROL_BOAT_INFO_POINTS(WidgetID.PEST_CONTROL_BOAT_GROUP_ID, WidgetID.PestControlBoat.POINTS),
|
||||
PEST_CONTROL_INFO(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.INFO),
|
||||
PEST_CONTROL_INFO_TIME(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.TIME),
|
||||
PEST_CONTROL_PURPLE_SHIELD(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.PURPLE_SHIELD),
|
||||
PEST_CONTROL_BLUE_SHIELD(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.BLUE_SHIELD),
|
||||
PEST_CONTROL_YELLOW_SHIELD(WidgetID.PEST_CONTROL_GROUP_ID, WidgetID.PestControl.YELLOW_SHIELD),
|
||||
@@ -550,7 +556,12 @@ public enum WidgetInfo
|
||||
MUSICTAB_LOOP_BUTTON(WidgetID.MUSICTAB_GROUP_ID, 12),
|
||||
MUSICTAB_UNLOCKED_SONGS(WidgetID.MUSICTAB_GROUP_ID, 13),
|
||||
|
||||
QUESTTAB_QUEST_TAB(WidgetID.QUESTTAB_GROUP_ID, WidgetID.QuestTab.QUEST_TAB);
|
||||
QUESTTAB_QUEST_TAB(WidgetID.QUESTTAB_GROUP_ID, WidgetID.QuestTab.QUEST_TAB),
|
||||
|
||||
EQUIPMENT_MELEE_STRENGTH(WidgetID.EQUIPMENT_PAGE_GROUP_ID, WidgetID.EquipmentWidgetIdentifiers.MELEE_STRENGTH),
|
||||
EQUIPMENT_RANGED_STRENGTH(WidgetID.EQUIPMENT_PAGE_GROUP_ID, WidgetID.EquipmentWidgetIdentifiers.RANGED_STRENGTH),
|
||||
EQUIPMENT_MAGIC_DAMAGE(WidgetID.EQUIPMENT_PAGE_GROUP_ID, WidgetID.EquipmentWidgetIdentifiers.MAGIC_DAMAGE),
|
||||
EQUIP_YOUR_CHARACTER(WidgetID.EQUIPMENT_PAGE_GROUP_ID, WidgetID.EquipmentWidgetIdentifiers.EQUIP_YOUR_CHARACTER);
|
||||
|
||||
private final int groupId;
|
||||
private final int childId;
|
||||
|
||||
@@ -109,4 +109,15 @@ public interface DailyTasksConfig extends Config
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
keyName = "showArrows",
|
||||
name = "Show Claimable Ogre Arrows",
|
||||
description = "Show a message when you can collect ogre arrows from Rantz."
|
||||
)
|
||||
default boolean showArrows()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ public class DailyTasksPlugin extends Plugin
|
||||
private static final String SAND_MESSAGE = "You have sand waiting to be collected from Bert.";
|
||||
private static final int SAND_QUEST_COMPLETE = 160;
|
||||
private static final String FLAX_MESSAGE = "You have bowstrings waiting to be converted from flax from the Flax keeper.";
|
||||
private static final String ARROWS_MESSAGE = "You have ogre arrows waiting to be collected from Rantz.";
|
||||
private static final String BONEMEAL_MESSAGE = "You have bonemeal and slime waiting to be collected from Robin.";
|
||||
private static final int BONEMEAL_PER_DIARY = 13;
|
||||
private static final String RELOG_MESSAGE = " (May require a relog)";
|
||||
@@ -153,22 +154,21 @@ public class DailyTasksPlugin extends Plugin
|
||||
{
|
||||
checkBonemeal(dailyReset);
|
||||
}
|
||||
|
||||
if (config.showArrows())
|
||||
{
|
||||
checkArrows(dailyReset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkHerbBoxes(boolean dailyReset)
|
||||
{
|
||||
if (client.getAccountType() == AccountType.NORMAL
|
||||
if ((client.getAccountType() == AccountType.NORMAL
|
||||
&& client.getVar(VarPlayer.NMZ_REWARD_POINTS) >= HERB_BOX_COST)
|
||||
&& (dailyReset || client.getVar(Varbits.DAILY_HERB_BOXES_COLLECTED) < HERB_BOX_MAX))
|
||||
{
|
||||
if (client.getVar(Varbits.DAILY_HERB_BOXES_COLLECTED) < HERB_BOX_MAX)
|
||||
{
|
||||
sendChatMessage(HERB_BOX_MESSAGE);
|
||||
}
|
||||
else if (dailyReset)
|
||||
{
|
||||
sendChatMessage(HERB_BOX_MESSAGE);
|
||||
}
|
||||
sendChatMessage(HERB_BOX_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,61 +189,46 @@ public class DailyTasksPlugin extends Plugin
|
||||
|
||||
private void checkEssence(boolean dailyReset)
|
||||
{
|
||||
if (client.getVar(Varbits.DIARY_ARDOUGNE_MEDIUM) == 1)
|
||||
if ((client.getVar(Varbits.DIARY_ARDOUGNE_MEDIUM) == 1)
|
||||
&& (dailyReset || client.getVar(Varbits.DAILY_ESSENCE_COLLECTED) == 0))
|
||||
{
|
||||
if (client.getVar(Varbits.DAILY_ESSENCE_COLLECTED) == 0)
|
||||
{
|
||||
sendChatMessage(ESSENCE_MESSAGE);
|
||||
}
|
||||
else if (dailyReset)
|
||||
{
|
||||
sendChatMessage(ESSENCE_MESSAGE);
|
||||
}
|
||||
sendChatMessage(ESSENCE_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRunes(boolean dailyReset)
|
||||
{
|
||||
if (client.getVar(Varbits.DIARY_WILDERNESS_EASY) == 1)
|
||||
if ((client.getVar(Varbits.DIARY_WILDERNESS_EASY) == 1)
|
||||
&& (dailyReset || client.getVar(Varbits.DAILY_RUNES_COLLECTED) == 0))
|
||||
{
|
||||
if (client.getVar(Varbits.DAILY_RUNES_COLLECTED) == 0)
|
||||
{
|
||||
sendChatMessage(RUNES_MESSAGE);
|
||||
}
|
||||
else if (dailyReset)
|
||||
{
|
||||
sendChatMessage(RUNES_MESSAGE);
|
||||
}
|
||||
sendChatMessage(RUNES_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSand(boolean dailyReset)
|
||||
{
|
||||
if (client.getVar(Varbits.QUEST_THE_HAND_IN_THE_SAND) >= SAND_QUEST_COMPLETE)
|
||||
if ((client.getVar(Varbits.QUEST_THE_HAND_IN_THE_SAND) >= SAND_QUEST_COMPLETE)
|
||||
&& (dailyReset || client.getVar(Varbits.DAILY_SAND_COLLECTED) == 0))
|
||||
{
|
||||
if (client.getVar(Varbits.DAILY_SAND_COLLECTED) == 0)
|
||||
{
|
||||
sendChatMessage(SAND_MESSAGE);
|
||||
}
|
||||
else if (dailyReset)
|
||||
{
|
||||
sendChatMessage(SAND_MESSAGE);
|
||||
}
|
||||
sendChatMessage(SAND_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkFlax(boolean dailyReset)
|
||||
{
|
||||
if (client.getVar(Varbits.DIARY_KANDARIN_EASY) == 1)
|
||||
if ((client.getVar(Varbits.DIARY_KANDARIN_EASY) == 1)
|
||||
&& (dailyReset || client.getVar(Varbits.DAILY_FLAX_STATE) == 0))
|
||||
{
|
||||
if (client.getVar(Varbits.DAILY_FLAX_STATE) == 0)
|
||||
{
|
||||
sendChatMessage(FLAX_MESSAGE);
|
||||
}
|
||||
else if (dailyReset)
|
||||
{
|
||||
sendChatMessage(FLAX_MESSAGE);
|
||||
}
|
||||
sendChatMessage(FLAX_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkArrows(boolean dailyReset)
|
||||
{
|
||||
if ((client.getVar(Varbits.DIARY_WESTERN_EASY) == 1)
|
||||
&& (dailyReset || client.getVar(Varbits.DAILY_ARROWS_STATE) == 0))
|
||||
{
|
||||
sendChatMessage(ARROWS_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,11 +246,7 @@ public class DailyTasksPlugin extends Plugin
|
||||
max += BONEMEAL_PER_DIARY;
|
||||
}
|
||||
}
|
||||
if (collected < max)
|
||||
{
|
||||
sendChatMessage(BONEMEAL_MESSAGE);
|
||||
}
|
||||
else if (dailyReset)
|
||||
if (dailyReset || collected < max)
|
||||
{
|
||||
sendChatMessage(BONEMEAL_MESSAGE);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.ItemContainerChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.maxhit.calculators.MagicMaxHitCalculator;
|
||||
import net.runelite.client.plugins.maxhit.calculators.MeleeMaxHitCalculator;
|
||||
import net.runelite.client.plugins.maxhit.calculators.RangeMaxHitCalculator;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Max Hit",
|
||||
description = "Max Hit Calculator",
|
||||
type = "PVM",
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class MaxHitPlugin extends Plugin
|
||||
{
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Subscribe
|
||||
public void onItemContainerChanged(final ItemContainerChanged event)
|
||||
{
|
||||
this.updateMaxHitWidget();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(final ConfigChanged event)
|
||||
{
|
||||
this.updateMaxHitWidget();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
this.updateMaxHitWidget();
|
||||
}
|
||||
|
||||
private void updateMaxHitWidget()
|
||||
{
|
||||
Widget equipmentStats = client.getWidget(WidgetInfo.EQUIPMENT_INVENTORY_ITEMS_CONTAINER);
|
||||
|
||||
ItemContainer equipmentContainer = client.getItemContainer(InventoryID.EQUIPMENT);
|
||||
Item[] equipedItems = new Item[14];
|
||||
|
||||
if (equipmentStats != null && !equipmentStats.isHidden())
|
||||
{
|
||||
if (equipmentContainer != null)
|
||||
{
|
||||
equipedItems = equipmentContainer.getItems();
|
||||
}
|
||||
|
||||
MeleeMaxHitCalculator meleeMaxHitCalculator = new MeleeMaxHitCalculator(this.client, equipedItems);
|
||||
RangeMaxHitCalculator rangeMaxHitCalculator = new RangeMaxHitCalculator(this.client, equipedItems);
|
||||
MagicMaxHitCalculator magicMaxHitCalculator = new MagicMaxHitCalculator(this.client, equipedItems);
|
||||
|
||||
MaxHit maxHit = new MaxHit(meleeMaxHitCalculator.getMaxHit(), rangeMaxHitCalculator.getMaxHit(), magicMaxHitCalculator.getMaxHit());
|
||||
this.setWidgetMaxHit(maxHit);
|
||||
}
|
||||
}
|
||||
|
||||
private void setWidgetMaxHit(MaxHit maxhit)
|
||||
{
|
||||
Widget equipYourCharacter = client.getWidget(WidgetInfo.EQUIP_YOUR_CHARACTER);
|
||||
String maxHitText = "Melee Max Hit: " + maxhit.getMaxMeleeHit();
|
||||
maxHitText += "<br>Range Max Hit: " + maxhit.getMaxRangeHit();
|
||||
maxHitText += "<br>Magic Max Hit: " + maxhit.getMaxMagicHit();
|
||||
|
||||
|
||||
equipYourCharacter.setText(maxHitText);
|
||||
}
|
||||
|
||||
private class MaxHit
|
||||
{
|
||||
private final double maxMeleeHit;
|
||||
private final double maxRangeHit;
|
||||
private final double maxMagicHit;
|
||||
|
||||
MaxHit(double maxMeleeHit, double maxRangeHit, double maxMagicHit)
|
||||
{
|
||||
this.maxMeleeHit = maxMeleeHit;
|
||||
this.maxRangeHit = maxRangeHit;
|
||||
this.maxMagicHit = maxMagicHit;
|
||||
}
|
||||
|
||||
double getMaxMeleeHit()
|
||||
{
|
||||
return maxMeleeHit;
|
||||
}
|
||||
|
||||
double getMaxRangeHit()
|
||||
{
|
||||
return maxRangeHit;
|
||||
}
|
||||
|
||||
double getMaxMagicHit()
|
||||
{
|
||||
return maxMagicHit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.attackstyle;
|
||||
|
||||
public enum AttackStyle
|
||||
{
|
||||
ACCURATE(0),
|
||||
AGGRESSIVE(3),
|
||||
DEFENSIVE(0),
|
||||
CONTROLLED(1),
|
||||
ACCURATERANGING(3),
|
||||
RANGING(0),
|
||||
LONGRANGE(0),
|
||||
CASTING(0),
|
||||
DEFENSIVE_CASTING(0),
|
||||
OTHER(0);
|
||||
|
||||
private final int maxHitBonus;
|
||||
|
||||
AttackStyle(int maxHitBonus)
|
||||
{
|
||||
this.maxHitBonus = maxHitBonus;
|
||||
}
|
||||
|
||||
public double getMaxHitBonus()
|
||||
{
|
||||
return this.maxHitBonus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.attackstyle;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static net.runelite.client.plugins.maxhit.attackstyle.AttackStyle.*;
|
||||
|
||||
public enum WeaponType
|
||||
{
|
||||
TYPE_0(ACCURATE, AGGRESSIVE, null, DEFENSIVE),
|
||||
TYPE_1(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE),
|
||||
TYPE_2(ACCURATE, AGGRESSIVE, null, DEFENSIVE),
|
||||
TYPE_3(ACCURATERANGING, RANGING, null, LONGRANGE),
|
||||
TYPE_4(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE),
|
||||
TYPE_5(ACCURATERANGING, RANGING, null, LONGRANGE),
|
||||
TYPE_6(AGGRESSIVE, RANGING, DEFENSIVE_CASTING, null),
|
||||
TYPE_7(ACCURATERANGING, RANGING, null, LONGRANGE),
|
||||
TYPE_8(OTHER, AGGRESSIVE, null, null),
|
||||
TYPE_9(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE),
|
||||
TYPE_10(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE),
|
||||
TYPE_11(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE),
|
||||
TYPE_12(CONTROLLED, AGGRESSIVE, null, DEFENSIVE),
|
||||
TYPE_13(ACCURATE, AGGRESSIVE, null, DEFENSIVE),
|
||||
TYPE_14(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE),
|
||||
TYPE_15(CONTROLLED, CONTROLLED, CONTROLLED, DEFENSIVE),
|
||||
TYPE_16(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE),
|
||||
TYPE_17(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE),
|
||||
TYPE_18(ACCURATE, AGGRESSIVE, null, DEFENSIVE, CASTING, DEFENSIVE_CASTING),
|
||||
TYPE_19(ACCURATERANGING, RANGING, null, LONGRANGE),
|
||||
TYPE_20(ACCURATE, CONTROLLED, null, DEFENSIVE),
|
||||
TYPE_21(ACCURATE, AGGRESSIVE, null, DEFENSIVE, CASTING, DEFENSIVE_CASTING),
|
||||
TYPE_22(ACCURATE, AGGRESSIVE, AGGRESSIVE, DEFENSIVE),
|
||||
TYPE_23(CASTING, CASTING, null, DEFENSIVE_CASTING),
|
||||
TYPE_24(ACCURATE, AGGRESSIVE, CONTROLLED, DEFENSIVE),
|
||||
TYPE_25(CONTROLLED, AGGRESSIVE, null, DEFENSIVE),
|
||||
TYPE_26(AGGRESSIVE, AGGRESSIVE, null, AGGRESSIVE),
|
||||
TYPE_27(ACCURATE, null, null, OTHER);
|
||||
|
||||
private static final Map<Integer, WeaponType> weaponTypes = new HashMap<>();
|
||||
|
||||
static
|
||||
{
|
||||
for (WeaponType weaponType : values())
|
||||
{
|
||||
weaponTypes.put(weaponType.ordinal(), weaponType);
|
||||
}
|
||||
}
|
||||
|
||||
private final AttackStyle[] attackStyles;
|
||||
|
||||
WeaponType(AttackStyle... attackStyles)
|
||||
{
|
||||
this.attackStyles = attackStyles;
|
||||
}
|
||||
|
||||
public static WeaponType getWeaponType(int id)
|
||||
{
|
||||
return weaponTypes.get(id);
|
||||
}
|
||||
|
||||
public AttackStyle[] getAttackStyles()
|
||||
{
|
||||
return attackStyles;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Item;
|
||||
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.plugins.maxhit.config.EquipmentBonusConfig;
|
||||
import net.runelite.client.plugins.maxhit.config.SpellBaseDamageConfig;
|
||||
|
||||
public class MagicMaxHitCalculator extends MaxHitCalculator
|
||||
{
|
||||
|
||||
public MagicMaxHitCalculator(Client client, Item[] equipedItems)
|
||||
{
|
||||
super(client, CombatMethod.MAGIC, equipedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSkillStrengthText(String equipmentText)
|
||||
{
|
||||
return equipmentText.replace("Magic damage: ", "").replace(".", "").replace("%", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
Widget equipmentSkillPower()
|
||||
{
|
||||
return this.client.getWidget(WidgetInfo.EQUIPMENT_MAGIC_DAMAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentSkillPower()
|
||||
{
|
||||
return this.client.getBoostedSkillLevel(Skill.MAGIC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Damage formula based on:
|
||||
* http://services.runescape.com/m=forum/forums.ws?317,318,712,65587452
|
||||
* Section 4.
|
||||
* */
|
||||
@Override
|
||||
public double calculate()
|
||||
{
|
||||
int spellBaseDamage = this.baseDamage;
|
||||
|
||||
if (spellBaseDamage == 0)
|
||||
{
|
||||
int autoCastSpellId = client.getVar(Varbits.AUTO_CAST_SPELL);
|
||||
if (autoCastSpellId == 0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
SpellBaseDamageConfig autoCastSpell = SpellBaseDamageConfig.findSpellById(autoCastSpellId);
|
||||
spellBaseDamage = autoCastSpell.getBaseDamage();
|
||||
}
|
||||
|
||||
// a.Find the base maximum damage a spell can deal.
|
||||
// See CustomFormulaConfig for spells based on magic lvl
|
||||
double maxHit = spellBaseDamage;
|
||||
|
||||
// b. Increase the base damage (Chaos Gauntlets)
|
||||
maxHit = this.applyEquipmentBonus(maxHit, EquipmentBonusConfig.BonusType.SPECIAL);
|
||||
|
||||
// c. The following bonuses stack by adding up. (List of bonus items)
|
||||
maxHit = this.applyEquipmentBonus(maxHit, EquipmentBonusConfig.BonusType.EQUIPMENT);
|
||||
|
||||
// d. Round down to the nearest integer.
|
||||
maxHit = Math.floor(maxHit);
|
||||
|
||||
// e. On a slayer task, multiply by 1.15 (imbued)
|
||||
maxHit = this.applyEquipmentBonus(maxHit, EquipmentBonusConfig.BonusType.SLAYER);
|
||||
|
||||
// f. Round down to the nearest integer.
|
||||
maxHit = Math.floor(maxHit);
|
||||
|
||||
// g. If a fire spell is used, multiply by 1.5 (Tome of fire)
|
||||
maxHit = this.applyEquipmentBonus(maxHit, EquipmentBonusConfig.BonusType.MAGIC_SPECIAL);
|
||||
|
||||
// h. Round down to the nearest integer.
|
||||
maxHit = Math.floor(maxHit);
|
||||
|
||||
// i, j. Castle Wars will not be included
|
||||
return maxHit;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.VarPlayer;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.client.plugins.maxhit.attackstyle.AttackStyle;
|
||||
import net.runelite.client.plugins.maxhit.attackstyle.WeaponType;
|
||||
import net.runelite.client.plugins.maxhit.config.CustomFormulaConfig;
|
||||
import net.runelite.client.plugins.maxhit.config.EquipmentBonusConfig;
|
||||
import net.runelite.client.plugins.maxhit.config.PrayerBonusConfig;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentHelper;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public abstract class MaxHitCalculator
|
||||
{
|
||||
|
||||
final Client client;
|
||||
private final CombatMethod combatMethod;
|
||||
private final Item[] equipedItems;
|
||||
int baseDamage = 0;
|
||||
|
||||
MaxHitCalculator(Client client, CombatMethod combatMethod, Item[] equipedItems)
|
||||
{
|
||||
this.client = client;
|
||||
this.combatMethod = combatMethod;
|
||||
this.equipedItems = equipedItems;
|
||||
}
|
||||
|
||||
protected abstract String getSkillStrengthText(String equipmentText);
|
||||
|
||||
abstract Widget equipmentSkillPower();
|
||||
|
||||
public abstract double getCurrentSkillPower();
|
||||
|
||||
AttackStyle getAttackStyle()
|
||||
{
|
||||
int equippedWeaponTypeId = client.getVar(Varbits.EQUIPPED_WEAPON_TYPE);
|
||||
int attackStyleId = client.getVar(VarPlayer.ATTACK_STYLE);
|
||||
|
||||
AttackStyle[] attackStyles = WeaponType.getWeaponType(equippedWeaponTypeId).getAttackStyles();
|
||||
|
||||
if (attackStyleId < attackStyles.length)
|
||||
{
|
||||
AttackStyle attackStyle = attackStyles[attackStyleId];
|
||||
if (attackStyle != null)
|
||||
{
|
||||
return attackStyle;
|
||||
}
|
||||
}
|
||||
|
||||
return AttackStyle.OTHER;
|
||||
}
|
||||
|
||||
double getPrayerBonus()
|
||||
{
|
||||
double bonus = 1;
|
||||
for (PrayerBonusConfig prayerBonus : PrayerBonusConfig.values())
|
||||
{
|
||||
boolean prayerActive = client.getVar(prayerBonus.getPrayerVarbit()) == 1;
|
||||
boolean sameCombatMethod = prayerBonus.getCombatMethod() == this.combatMethod;
|
||||
if (prayerActive && sameCombatMethod)
|
||||
{
|
||||
bonus += prayerBonus.getStrengthBonus();
|
||||
}
|
||||
}
|
||||
return bonus;
|
||||
}
|
||||
|
||||
double applyEquipmentBonus(double maxhit, EquipmentBonusConfig.BonusType bonusType)
|
||||
{
|
||||
double bonus = 1;
|
||||
ArrayList<Double> addList = new ArrayList<>();
|
||||
|
||||
ArrayList<EquipmentBonusConfig> equipmentBonuses = EquipmentBonusConfig.getBonusByType(bonusType);
|
||||
|
||||
for (EquipmentBonusConfig equipmentBonus : equipmentBonuses)
|
||||
{
|
||||
EquipmentItemset itemSet = equipmentBonus.getItemset();
|
||||
boolean wearsSet = EquipmentHelper.wearsItemSet(this.equipedItems, itemSet);
|
||||
if (wearsSet && equipmentBonus.meetsRequirements(this.client))
|
||||
{
|
||||
if (equipmentBonus.getOperation() == EquipmentBonusConfig.Operation.MULTIPLY)
|
||||
{
|
||||
bonus += equipmentBonus.getBonus(this.combatMethod);
|
||||
}
|
||||
else if (equipmentBonus.getOperation() == EquipmentBonusConfig.Operation.ADD)
|
||||
{
|
||||
addList.add(equipmentBonus.getBonus(this.combatMethod));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maxhit *= bonus;
|
||||
|
||||
maxhit = maxhit + addList.stream().reduce(0.0, Double::sum);
|
||||
|
||||
return maxhit;
|
||||
}
|
||||
|
||||
public double getMaxHit()
|
||||
{
|
||||
BiFunction<Client, MaxHitCalculator, Double> customFormula = this.getCustomFormula();
|
||||
if (customFormula != null)
|
||||
{
|
||||
return customFormula.apply(this.client, this);
|
||||
}
|
||||
|
||||
return this.calculate();
|
||||
}
|
||||
|
||||
private BiFunction<Client, MaxHitCalculator, Double> getCustomFormula()
|
||||
{
|
||||
for (CustomFormulaConfig customFormula : CustomFormulaConfig.values())
|
||||
{
|
||||
if (this.combatMethod != customFormula.getRequiredCombatMethod())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean meetsRequirements = customFormula.getRequirements().stream().allMatch(requirement -> requirement.meetsRequirements(this.client));
|
||||
|
||||
if (meetsRequirements)
|
||||
{
|
||||
return customFormula.getCustomFormula();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract double calculate();
|
||||
|
||||
public void setBaseDamage(int baseDamage)
|
||||
{
|
||||
this.baseDamage = baseDamage;
|
||||
}
|
||||
|
||||
double getSkillStrength()
|
||||
{
|
||||
return Double.parseDouble(this.getSkillStrengthText(this.equipmentSkillPower().getText()));
|
||||
}
|
||||
|
||||
public enum CombatMethod
|
||||
{
|
||||
MELEE,
|
||||
RANGE,
|
||||
MAGIC
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.plugins.maxhit.attackstyle.AttackStyle;
|
||||
import net.runelite.client.plugins.maxhit.config.EquipmentBonusConfig;
|
||||
|
||||
public class MeleeMaxHitCalculator extends MaxHitCalculator
|
||||
{
|
||||
|
||||
public MeleeMaxHitCalculator(Client client, Item[] equipedItems)
|
||||
{
|
||||
super(client, CombatMethod.MELEE, equipedItems);
|
||||
}
|
||||
|
||||
MeleeMaxHitCalculator(Client client, CombatMethod combatMethod, Item[] equipedItems)
|
||||
{
|
||||
super(client, combatMethod, equipedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSkillStrengthText(String equipmentText)
|
||||
{
|
||||
return equipmentText.replace("Melee strength: ", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget equipmentSkillPower()
|
||||
{
|
||||
return this.client.getWidget(WidgetInfo.EQUIPMENT_MELEE_STRENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentSkillPower()
|
||||
{
|
||||
return this.client.getBoostedSkillLevel(Skill.STRENGTH);
|
||||
}
|
||||
|
||||
private double getEffectiveLevel()
|
||||
{
|
||||
// a. Take the visible strength or ranged level from the skills interface.
|
||||
double skillPower = this.getCurrentSkillPower();
|
||||
|
||||
// b. Multiply the level by the prayer adjustment
|
||||
double effectiveLevel = skillPower * this.getPrayerBonus();
|
||||
|
||||
// c. Round down to the nearest integer.
|
||||
effectiveLevel = Math.floor(effectiveLevel);
|
||||
|
||||
// d. Add the stance bonus from the combat options interface.
|
||||
// Melee:
|
||||
// • Aggressive: +3
|
||||
// • Controlled: +1
|
||||
// Ranged:
|
||||
// * Accurate: +3
|
||||
AttackStyle attackStyle = this.getAttackStyle();
|
||||
effectiveLevel += attackStyle.getMaxHitBonus();
|
||||
|
||||
// e. Add up +8.
|
||||
effectiveLevel += 8;
|
||||
|
||||
// f. Multiply by the void bonus:
|
||||
// • Void melee: multiply by 1.10. Round down.
|
||||
// • Void ranged: multiply by 1.10. Round down.
|
||||
// • Elite void ranged: multiply by 1.125. Round down.
|
||||
effectiveLevel = this.applyEquipmentBonus(effectiveLevel, EquipmentBonusConfig.BonusType.VOID_KNIGHT);
|
||||
|
||||
// g. This is the effective (ranged) strength level. Let this equal 'A' in the formula in
|
||||
return effectiveLevel;
|
||||
}
|
||||
|
||||
// 3.3 Take the melee or ranged strength bonus from the equipment stats interface and let this equal 'B' in the formula in 3.1.
|
||||
private double getEquipmentBonus()
|
||||
{
|
||||
return this.getSkillStrength();
|
||||
}
|
||||
|
||||
/*
|
||||
* Damage formula based on:
|
||||
* http://services.runescape.com/m=forum/forums.ws?317,318,712,65587452
|
||||
* Section 3.1
|
||||
* */
|
||||
@Override
|
||||
public double calculate()
|
||||
{
|
||||
|
||||
// a. Max hit = 0.5 + A * (B+64) /640 (A is effective level, B is Equipment bonus)
|
||||
double maxHit = 0.5 + this.getEffectiveLevel() * (this.getEquipmentBonus() + 64) / 640;
|
||||
|
||||
// b. Round down the max hit to the nearest integer.
|
||||
maxHit = Math.floor(maxHit);
|
||||
|
||||
// 3.4 Special attacks (not actually taking weapon special attacks into account)
|
||||
// a. Multiply by the bonus of one of the following items (slayer)
|
||||
maxHit = this.applyEquipmentBonus(maxHit, EquipmentBonusConfig.BonusType.SLAYER);
|
||||
|
||||
// b. Round down the max hit to the nearest integer.
|
||||
maxHit = Math.floor(maxHit);
|
||||
|
||||
// c. Multiply by the bonus of one of the following items
|
||||
maxHit = this.applyEquipmentBonus(maxHit, EquipmentBonusConfig.BonusType.SPECIAL);
|
||||
|
||||
// d. Round down to the nearest integer.
|
||||
maxHit = Math.floor(maxHit);
|
||||
|
||||
return maxHit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
|
||||
public class RangeMaxHitCalculator extends MeleeMaxHitCalculator
|
||||
{
|
||||
|
||||
public RangeMaxHitCalculator(Client client, Item[] equipedItems)
|
||||
{
|
||||
super(client, CombatMethod.RANGE, equipedItems);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSkillStrengthText(String equipmentText)
|
||||
{
|
||||
return equipmentText.replace("Ranged strength: ", "").replace(".", "").replace("%", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Widget equipmentSkillPower()
|
||||
{
|
||||
return this.client.getWidget(WidgetInfo.EQUIPMENT_RANGED_STRENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentSkillPower()
|
||||
{
|
||||
return this.client.getBoostedSkillLevel(Skill.RANGED);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.config;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.EquipmentInventorySlot;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.plugins.maxhit.calculators.MaxHitCalculator;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentSlotItem;
|
||||
import net.runelite.client.plugins.maxhit.requirements.EquipmentItemRequirement;
|
||||
import net.runelite.client.plugins.maxhit.requirements.EquipmentItemSetRequirement;
|
||||
import net.runelite.client.plugins.maxhit.requirements.Requirement;
|
||||
import net.runelite.client.plugins.maxhit.requirements.SpellRequirement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public enum CustomFormulaConfig
|
||||
{
|
||||
|
||||
MAGIC_DART(
|
||||
MaxHitCalculator.CombatMethod.MAGIC,
|
||||
new ArrayList<>(Arrays.asList(
|
||||
new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList(
|
||||
ItemID.SLAYERS_STAFF,
|
||||
ItemID.SLAYERS_STAFF_E
|
||||
)))),
|
||||
new SpellRequirement(SpellBaseDamageConfig.MAGIC_DART)
|
||||
)),
|
||||
(client, calculator) ->
|
||||
{
|
||||
int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC);
|
||||
return Math.floor((magicLevel / 10.0) + 10.0);
|
||||
}
|
||||
),
|
||||
|
||||
TRIDENT_OF_SEAS(
|
||||
MaxHitCalculator.CombatMethod.MAGIC,
|
||||
new ArrayList<>(Collections.singletonList(
|
||||
new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList(
|
||||
ItemID.TRIDENT_OF_THE_SEAS_FULL,
|
||||
ItemID.TRIDENT_OF_THE_SEAS,
|
||||
ItemID.TRIDENT_OF_THE_SEAS_E
|
||||
))))
|
||||
)),
|
||||
(client, calculator) ->
|
||||
{
|
||||
int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC);
|
||||
|
||||
int baseDamage = (int) Math.floor(magicLevel / 3.0) - 5;
|
||||
calculator.setBaseDamage(baseDamage);
|
||||
|
||||
return calculator.calculate();
|
||||
}
|
||||
),
|
||||
|
||||
TRIDENT_OF_SWAMP(
|
||||
MaxHitCalculator.CombatMethod.MAGIC,
|
||||
new ArrayList<>(Collections.singletonList(
|
||||
new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList(
|
||||
ItemID.TRIDENT_OF_THE_SWAMP,
|
||||
ItemID.TRIDENT_OF_THE_SWAMP_E
|
||||
))))
|
||||
)),
|
||||
(client, calculator) ->
|
||||
{
|
||||
int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC);
|
||||
|
||||
int baseDamage = (int) Math.floor(magicLevel / 3.0) - 2;
|
||||
calculator.setBaseDamage(baseDamage);
|
||||
|
||||
return calculator.calculate();
|
||||
}
|
||||
),
|
||||
|
||||
SWAMP_LIZARD(
|
||||
MaxHitCalculator.CombatMethod.MAGIC,
|
||||
new ArrayList<>(Collections.singletonList(
|
||||
new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.SWAMP_LIZARD
|
||||
))))
|
||||
)),
|
||||
(client, calculator) ->
|
||||
{
|
||||
int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC);
|
||||
return Math.floor(0.5 + magicLevel * (64.0 + 56.0) / 640.0);
|
||||
}
|
||||
),
|
||||
|
||||
ORANGE_SALAMANDER(
|
||||
MaxHitCalculator.CombatMethod.MAGIC,
|
||||
new ArrayList<>(Collections.singletonList(
|
||||
new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ORANGE_SALAMANDER
|
||||
))))
|
||||
)),
|
||||
(client, calculator) ->
|
||||
{
|
||||
int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC);
|
||||
return Math.floor(0.5 + magicLevel * (64.0 + 59.0) / 640.0);
|
||||
}
|
||||
),
|
||||
|
||||
RED_SALAMANDER(
|
||||
MaxHitCalculator.CombatMethod.MAGIC,
|
||||
new ArrayList<>(Collections.singletonList(
|
||||
new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.RED_SALAMANDER
|
||||
))))
|
||||
)),
|
||||
(client, calculator) ->
|
||||
{
|
||||
int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC);
|
||||
return Math.floor(0.5 + magicLevel * (64.0 + 77.0) / 640.0);
|
||||
}
|
||||
),
|
||||
|
||||
BLACK_SALAMANDER(
|
||||
MaxHitCalculator.CombatMethod.MAGIC,
|
||||
new ArrayList<>(Collections.singletonList(
|
||||
new EquipmentItemRequirement(new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.BLACK_SALAMANDER
|
||||
))))
|
||||
)),
|
||||
(client, calculator) ->
|
||||
{
|
||||
int magicLevel = client.getBoostedSkillLevel(Skill.MAGIC);
|
||||
return Math.floor(0.5 + magicLevel * (64.0 + 92.0) / 640.0);
|
||||
}
|
||||
),
|
||||
|
||||
DHAROK(
|
||||
MaxHitCalculator.CombatMethod.MELEE,
|
||||
new ArrayList<>(Collections.singletonList(new EquipmentItemSetRequirement(new EquipmentItemset(Arrays.asList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.DHAROKS_HELM,
|
||||
ItemID.DHAROKS_HELM_100,
|
||||
ItemID.DHAROKS_HELM_75,
|
||||
ItemID.DHAROKS_HELM_50,
|
||||
ItemID.DHAROKS_HELM_25,
|
||||
ItemID.DHAROKS_HELM_0
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList(
|
||||
ItemID.DHAROKS_PLATEBODY,
|
||||
ItemID.DHAROKS_PLATEBODY_100,
|
||||
ItemID.DHAROKS_PLATEBODY_75,
|
||||
ItemID.DHAROKS_PLATEBODY_50,
|
||||
ItemID.DHAROKS_PLATEBODY_25,
|
||||
ItemID.DHAROKS_PLATEBODY_0
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Arrays.asList(
|
||||
ItemID.DHAROKS_PLATELEGS,
|
||||
ItemID.DHAROKS_PLATELEGS_100,
|
||||
ItemID.DHAROKS_PLATELEGS_75,
|
||||
ItemID.DHAROKS_PLATELEGS_50,
|
||||
ItemID.DHAROKS_PLATELEGS_25,
|
||||
ItemID.DHAROKS_PLATELEGS_0
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList(
|
||||
ItemID.DHAROKS_GREATAXE,
|
||||
ItemID.DHAROKS_GREATAXE_100,
|
||||
ItemID.DHAROKS_GREATAXE_75,
|
||||
ItemID.DHAROKS_GREATAXE_50,
|
||||
ItemID.DHAROKS_GREATAXE_25,
|
||||
ItemID.DHAROKS_GREATAXE_0
|
||||
)))
|
||||
))))),
|
||||
(client, calculator) ->
|
||||
{
|
||||
int currentHP = client.getBoostedSkillLevel(Skill.HITPOINTS);
|
||||
int maxHP = client.getRealSkillLevel(Skill.HITPOINTS);
|
||||
int lostHP = maxHP - currentHP;
|
||||
|
||||
double initialMaxHit = calculator.calculate();
|
||||
|
||||
double multiplier = (1.0 + ((lostHP / 100.0) * (maxHP / 100.0)));
|
||||
|
||||
return Math.floor(initialMaxHit * multiplier);
|
||||
}
|
||||
);
|
||||
|
||||
private final MaxHitCalculator.CombatMethod requiredCombatMethod;
|
||||
private final ArrayList<Requirement> requirements;
|
||||
private final BiFunction<Client, MaxHitCalculator, Double> customFormula;
|
||||
|
||||
CustomFormulaConfig(MaxHitCalculator.CombatMethod requiredCombatMethod, ArrayList<Requirement> requirements, BiFunction<Client, MaxHitCalculator, Double> customFormula)
|
||||
{
|
||||
this.requiredCombatMethod = requiredCombatMethod;
|
||||
this.requirements = requirements;
|
||||
this.customFormula = customFormula;
|
||||
}
|
||||
|
||||
public MaxHitCalculator.CombatMethod getRequiredCombatMethod()
|
||||
{
|
||||
return requiredCombatMethod;
|
||||
}
|
||||
|
||||
public BiFunction<Client, MaxHitCalculator, Double> getCustomFormula()
|
||||
{
|
||||
return customFormula;
|
||||
}
|
||||
|
||||
public ArrayList<Requirement> getRequirements()
|
||||
{
|
||||
return this.requirements;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.config;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.EquipmentInventorySlot;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.client.plugins.maxhit.calculators.MaxHitCalculator;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentCombatBonus;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentSlotItem;
|
||||
import net.runelite.client.plugins.maxhit.requirements.AutocastSpellRequirement;
|
||||
import net.runelite.client.plugins.maxhit.requirements.Requirement;
|
||||
import net.runelite.client.plugins.maxhit.requirements.SpellBookRequirement;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public enum EquipmentBonusConfig
|
||||
{
|
||||
|
||||
/*
|
||||
* Slayer bonus items
|
||||
*/
|
||||
BLACKMASK(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.BLACK_MASK_10,
|
||||
ItemID.BLACK_MASK_9,
|
||||
ItemID.BLACK_MASK_8,
|
||||
ItemID.BLACK_MASK_7,
|
||||
ItemID.BLACK_MASK_6,
|
||||
ItemID.BLACK_MASK_5,
|
||||
ItemID.BLACK_MASK_4,
|
||||
ItemID.BLACK_MASK_3,
|
||||
ItemID.BLACK_MASK_2,
|
||||
ItemID.BLACK_MASK_1,
|
||||
ItemID.BLACK_MASK
|
||||
)))
|
||||
)), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0, 0)),
|
||||
|
||||
SLAYERHELM(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.SLAYER_HELMET,
|
||||
ItemID.BLACK_SLAYER_HELMET,
|
||||
ItemID.GREEN_SLAYER_HELMET,
|
||||
ItemID.RED_SLAYER_HELMET,
|
||||
ItemID.PURPLE_SLAYER_HELMET,
|
||||
ItemID.TURQUOISE_SLAYER_HELMET,
|
||||
ItemID.HYDRA_SLAYER_HELMET
|
||||
)))
|
||||
)), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0, 0)),
|
||||
|
||||
BLACKMASKI(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.BLACK_MASK_10_I,
|
||||
ItemID.BLACK_MASK_9_I,
|
||||
ItemID.BLACK_MASK_8_I,
|
||||
ItemID.BLACK_MASK_7_I,
|
||||
ItemID.BLACK_MASK_6_I,
|
||||
ItemID.BLACK_MASK_5_I,
|
||||
ItemID.BLACK_MASK_4_I,
|
||||
ItemID.BLACK_MASK_3_I,
|
||||
ItemID.BLACK_MASK_2_I,
|
||||
ItemID.BLACK_MASK_1_I,
|
||||
ItemID.BLACK_MASK_I
|
||||
)))
|
||||
)), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0.15, 0.15)),
|
||||
|
||||
SLAYERHELMI(BonusType.SLAYER, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.SLAYER_HELMET_I,
|
||||
ItemID.BLACK_SLAYER_HELMET_I,
|
||||
ItemID.GREEN_SLAYER_HELMET_I,
|
||||
ItemID.RED_SLAYER_HELMET_I,
|
||||
ItemID.PURPLE_SLAYER_HELMET_I,
|
||||
ItemID.TURQUOISE_SLAYER_HELMET_I,
|
||||
ItemID.HYDRA_SLAYER_HELMET_I
|
||||
)))
|
||||
)), new EquipmentCombatBonus(((7.0 / 6.0) - 1), 0.15, 0.15)),
|
||||
|
||||
/*
|
||||
* Void bonus items
|
||||
* */
|
||||
MELEEVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.VOID_MELEE_HELM,
|
||||
ItemID.VOID_MELEE_HELM_11676
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList(
|
||||
ItemID.VOID_KNIGHT_TOP,
|
||||
ItemID.VOID_KNIGHT_TOP_10611
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.VOID_KNIGHT_ROBE
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.VOID_KNIGHT_GLOVES
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0.1, 0, 0)),
|
||||
|
||||
RANGERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.VOID_RANGER_HELM,
|
||||
ItemID.VOID_RANGER_HELM_11675
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Arrays.asList(
|
||||
ItemID.VOID_KNIGHT_TOP,
|
||||
ItemID.VOID_KNIGHT_TOP_10611
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.VOID_KNIGHT_ROBE
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.VOID_KNIGHT_GLOVES
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0.1, 0)),
|
||||
|
||||
|
||||
ELITEMELEERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.VOID_MELEE_HELM,
|
||||
ItemID.VOID_MELEE_HELM_11676
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ELITE_VOID_TOP
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ELITE_VOID_ROBE
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.VOID_KNIGHT_GLOVES
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0.125, 0, 0)),
|
||||
|
||||
|
||||
ELITERANGERVOID(BonusType.VOID_KNIGHT, new EquipmentItemset(Arrays.asList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.VOID_RANGER_HELM,
|
||||
ItemID.VOID_RANGER_HELM_11675
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ELITE_VOID_TOP
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ELITE_VOID_ROBE
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.VOID_KNIGHT_GLOVES
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0.125, 0)),
|
||||
|
||||
ELITEMAGICVOID(BonusType.EQUIPMENT, new EquipmentItemset(Arrays.asList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Arrays.asList(
|
||||
ItemID.VOID_MAGE_HELM,
|
||||
ItemID.VOID_MAGE_HELM_11674
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ELITE_VOID_TOP
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ELITE_VOID_ROBE
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.VOID_KNIGHT_GLOVES
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.025)),
|
||||
|
||||
/*
|
||||
* Special Melee Equipment
|
||||
* */
|
||||
OBISIDIAN(BonusType.SPECIAL, new EquipmentItemset(Arrays.asList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.OBSIDIAN_HELMET
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.OBSIDIAN_PLATEBODY
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.OBSIDIAN_PLATELEGS
|
||||
))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList(
|
||||
ItemID.TOKTZXILAK,
|
||||
ItemID.TOKTZXILEK,
|
||||
ItemID.TZHAARKETEM,
|
||||
ItemID.TZHAARKETOM,
|
||||
ItemID.TOKTZXILAK_20554
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0.1, 0, 0)),
|
||||
|
||||
BERSERKERNECKLACE(BonusType.SPECIAL, new EquipmentItemset(Arrays.asList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.AMULET, new ArrayList<>(Collections.singletonList(ItemID.BERSERKER_NECKLACE))),
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList(
|
||||
ItemID.TOKTZXILAK,
|
||||
ItemID.TOKTZXILEK,
|
||||
ItemID.TZHAARKETEM,
|
||||
ItemID.TZHAARKETOM,
|
||||
ItemID.TOKTZXILAK_20554
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0.2, 0, 0)),
|
||||
|
||||
|
||||
/*
|
||||
* Magic Equipment
|
||||
*/
|
||||
ANCESTRAL_HAT(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.HEAD, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ANCESTRAL_HAT
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.02)),
|
||||
|
||||
ANCESTRAL_ROBE_TOP(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.BODY, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ANCESTRAL_ROBE_TOP
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.02)),
|
||||
|
||||
ANCESTRAL_ROBE_BOTTOM(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.LEGS, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.ANCESTRAL_ROBE_BOTTOM
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.02)),
|
||||
|
||||
IMBUED_GOD_CAPE(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.CAPE, new ArrayList<>(Arrays.asList(
|
||||
ItemID.IMBUED_SARADOMIN_MAX_CAPE,
|
||||
ItemID.IMBUED_SARADOMIN_CAPE,
|
||||
ItemID.IMBUED_ZAMORAK_MAX_CAPE,
|
||||
ItemID.IMBUED_ZAMORAK_CAPE,
|
||||
ItemID.IMBUED_GUTHIX_MAX_CAPE,
|
||||
ItemID.IMBUED_GUTHIX_CAPE
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.02)),
|
||||
|
||||
KODAI_WAND(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.KODAI_WAND
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.15)),
|
||||
|
||||
OCCULT_NECKLACE(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.AMULET, new ArrayList<>(Arrays.asList(
|
||||
ItemID.OCCULT_NECKLACE,
|
||||
ItemID.OCCULT_NECKLACE_OR
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.10)),
|
||||
|
||||
STAFF_OF_THE_DEAD(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList(
|
||||
ItemID.STAFF_OF_THE_DEAD,
|
||||
ItemID.TOXIC_STAFF_OF_THE_DEAD,
|
||||
ItemID.STAFF_OF_LIGHT
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.15)),
|
||||
|
||||
TORMENTED_BRACELET(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.TORMENTED_BRACELET
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.05)),
|
||||
|
||||
SMOKE_STAFF(BonusType.EQUIPMENT, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.WEAPON, new ArrayList<>(Arrays.asList(
|
||||
ItemID.SMOKE_BATTLESTAFF,
|
||||
ItemID.MYSTIC_SMOKE_STAFF
|
||||
)))
|
||||
)), new EquipmentCombatBonus(0, 0, 0.10), Collections.singletonList(new SpellBookRequirement(SpellBaseDamageConfig.SpellBook.NORMAL))),
|
||||
|
||||
|
||||
/*
|
||||
* Special magic bonusses
|
||||
* */
|
||||
|
||||
CHAOS_GAUNTLETS(BonusType.SPECIAL, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.GLOVES, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.CHAOS_GAUNTLETS
|
||||
))))),
|
||||
new EquipmentCombatBonus(0, 0, 3),
|
||||
Collections.singletonList(
|
||||
new AutocastSpellRequirement(new ArrayList<>(Arrays.asList(
|
||||
SpellBaseDamageConfig.AIR_BOLT,
|
||||
SpellBaseDamageConfig.WATER_BOLT,
|
||||
SpellBaseDamageConfig.EARTH_BOLT,
|
||||
SpellBaseDamageConfig.FIRE_BOLT
|
||||
)))
|
||||
),
|
||||
Operation.ADD
|
||||
),
|
||||
|
||||
TOME_OF_FIRE(BonusType.MAGIC_SPECIAL, new EquipmentItemset(Collections.singletonList(
|
||||
new EquipmentSlotItem(EquipmentInventorySlot.SHIELD, new ArrayList<>(Collections.singletonList(
|
||||
ItemID.TOME_OF_FIRE
|
||||
))))),
|
||||
new EquipmentCombatBonus(0, 0, 0.5),
|
||||
Collections.singletonList(
|
||||
new AutocastSpellRequirement(new ArrayList<>(Arrays.asList(
|
||||
SpellBaseDamageConfig.FIRE_BLAST,
|
||||
SpellBaseDamageConfig.FIRE_BOLT,
|
||||
SpellBaseDamageConfig.FIRE_STRIKE,
|
||||
SpellBaseDamageConfig.FIRE_SURGE,
|
||||
SpellBaseDamageConfig.FIRE_WAVE
|
||||
)))
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
private static final Map<BonusType, ArrayList<EquipmentBonusConfig>> bonusTypes = new HashMap<>();
|
||||
|
||||
static
|
||||
{
|
||||
for (EquipmentBonusConfig equipmentBonus : values())
|
||||
{
|
||||
BonusType bonusType = equipmentBonus.bonusType;
|
||||
if (!bonusTypes.containsKey(bonusType))
|
||||
{
|
||||
bonusTypes.put(bonusType, new ArrayList<>());
|
||||
}
|
||||
ArrayList<EquipmentBonusConfig> list = bonusTypes.get(bonusType);
|
||||
list.add(equipmentBonus);
|
||||
bonusTypes.put(bonusType, list);
|
||||
}
|
||||
}
|
||||
|
||||
private final EquipmentItemset itemset;
|
||||
private BonusType bonusType;
|
||||
private EquipmentCombatBonus equipmentCombatBonus;
|
||||
private List<Requirement> requirements = new ArrayList<>();
|
||||
private Operation operation = Operation.MULTIPLY;
|
||||
EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus)
|
||||
{
|
||||
this.bonusType = bonusType;
|
||||
this.itemset = itemset;
|
||||
this.equipmentCombatBonus = equipmentCombatBonus;
|
||||
}
|
||||
EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus, List<Requirement> requirements)
|
||||
{
|
||||
this.bonusType = bonusType;
|
||||
this.itemset = itemset;
|
||||
this.equipmentCombatBonus = equipmentCombatBonus;
|
||||
this.requirements = requirements;
|
||||
}
|
||||
|
||||
EquipmentBonusConfig(BonusType bonusType, EquipmentItemset itemset, EquipmentCombatBonus equipmentCombatBonus, List<Requirement> requirements, Operation operation)
|
||||
{
|
||||
this.bonusType = bonusType;
|
||||
this.itemset = itemset;
|
||||
this.equipmentCombatBonus = equipmentCombatBonus;
|
||||
this.requirements = requirements;
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
public static ArrayList<EquipmentBonusConfig> getBonusByType(BonusType bonusType)
|
||||
{
|
||||
if (!bonusTypes.containsKey(bonusType))
|
||||
{
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return bonusTypes.get(bonusType);
|
||||
}
|
||||
|
||||
public EquipmentItemset getItemset()
|
||||
{
|
||||
return itemset;
|
||||
}
|
||||
|
||||
public Operation getOperation()
|
||||
{
|
||||
return operation;
|
||||
}
|
||||
|
||||
public double getBonus(MaxHitCalculator.CombatMethod combatMethod)
|
||||
{
|
||||
return this.equipmentCombatBonus.getCombatBonus(combatMethod);
|
||||
}
|
||||
|
||||
public boolean meetsRequirements(Client client)
|
||||
{
|
||||
return requirements.stream().allMatch(requirement -> requirement.meetsRequirements(client));
|
||||
}
|
||||
|
||||
public enum BonusType
|
||||
{
|
||||
EQUIPMENT,
|
||||
SLAYER,
|
||||
VOID_KNIGHT,
|
||||
SPECIAL,
|
||||
MAGIC_SPECIAL
|
||||
}
|
||||
|
||||
public enum Operation
|
||||
{
|
||||
ADD,
|
||||
MULTIPLY
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.config;
|
||||
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.client.plugins.maxhit.calculators.MaxHitCalculator;
|
||||
|
||||
public enum PrayerBonusConfig
|
||||
{
|
||||
BURST_OF_STRENGTH(MaxHitCalculator.CombatMethod.MELEE, Varbits.PRAYER_BURST_OF_STRENGTH, 0.05),
|
||||
SUPERHUMAN_STRENGTH(MaxHitCalculator.CombatMethod.MELEE, Varbits.PRAYER_SUPERHUMAN_STRENGTH, 0.1),
|
||||
ULTIMATE_STRENGTH(MaxHitCalculator.CombatMethod.MELEE, Varbits.PRAYER_ULTIMATE_STRENGTH, 0.15),
|
||||
CHIVALRY(MaxHitCalculator.CombatMethod.MELEE, Varbits.PRAYER_CHIVALRY, 0.18),
|
||||
PIETY(MaxHitCalculator.CombatMethod.MELEE, Varbits.PRAYER_PIETY, 0.23),
|
||||
|
||||
SHARP_EYE(MaxHitCalculator.CombatMethod.RANGE, Varbits.PRAYER_SHARP_EYE, 0.05),
|
||||
HAWK_EYE(MaxHitCalculator.CombatMethod.RANGE, Varbits.PRAYER_HAWK_EYE, 0.1),
|
||||
EAGLE_EYE(MaxHitCalculator.CombatMethod.RANGE, Varbits.PRAYER_EAGLE_EYE, 0.15),
|
||||
RIGOUR(MaxHitCalculator.CombatMethod.RANGE, Varbits.PRAYER_RIGOUR, 0.23);
|
||||
|
||||
private final MaxHitCalculator.CombatMethod combatMethod;
|
||||
private final Varbits prayerVarbit;
|
||||
private final double strengthBonus;
|
||||
|
||||
PrayerBonusConfig(MaxHitCalculator.CombatMethod combatMethod, Varbits prayerVarbit, double strengthBonus)
|
||||
{
|
||||
this.combatMethod = combatMethod;
|
||||
this.prayerVarbit = prayerVarbit;
|
||||
this.strengthBonus = strengthBonus;
|
||||
}
|
||||
|
||||
public MaxHitCalculator.CombatMethod getCombatMethod()
|
||||
{
|
||||
return combatMethod;
|
||||
}
|
||||
|
||||
public Varbits getPrayerVarbit()
|
||||
{
|
||||
return prayerVarbit;
|
||||
}
|
||||
|
||||
public double getStrengthBonus()
|
||||
{
|
||||
return strengthBonus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public enum SpellBaseDamageConfig
|
||||
{
|
||||
|
||||
/*
|
||||
* Normal Spellbook
|
||||
* */
|
||||
AIR_STRIKE(SpellBook.NORMAL, 1, 2),
|
||||
WATER_STRIKE(SpellBook.NORMAL, 2, 4),
|
||||
EARTH_STRIKE(SpellBook.NORMAL, 3, 6),
|
||||
FIRE_STRIKE(SpellBook.NORMAL, 4, 8),
|
||||
|
||||
AIR_BOLT(SpellBook.NORMAL, 5, 9),
|
||||
WATER_BOLT(SpellBook.NORMAL, 6, 10),
|
||||
EARTH_BOLT(SpellBook.NORMAL, 7, 11),
|
||||
FIRE_BOLT(SpellBook.NORMAL, 8, 12),
|
||||
|
||||
WIND_BLAST(SpellBook.NORMAL, 9, 13),
|
||||
WATER_BLAST(SpellBook.NORMAL, 10, 14),
|
||||
EARTH_BLAST(SpellBook.NORMAL, 11, 15),
|
||||
FIRE_BLAST(SpellBook.NORMAL, 12, 16),
|
||||
|
||||
AIR_WAVE(SpellBook.NORMAL, 13, 17),
|
||||
WATER_WAVE(SpellBook.NORMAL, 14, 18),
|
||||
EARTH_WAVE(SpellBook.NORMAL, 15, 19),
|
||||
FIRE_WAVE(SpellBook.NORMAL, 16, 20),
|
||||
|
||||
AIR_SURGE(SpellBook.NORMAL, 48, 21),
|
||||
WATER_SURGE(SpellBook.NORMAL, 49, 22),
|
||||
EARTH_SURGE(SpellBook.NORMAL, 50, 23),
|
||||
FIRE_SURGE(SpellBook.NORMAL, 51, 24),
|
||||
|
||||
/*
|
||||
* Ancient Spellbook
|
||||
* */
|
||||
SMOKE_RUSH(SpellBook.ANCIENT, 31, 14),
|
||||
SHADOW_RUSH(SpellBook.ANCIENT, 32, 15),
|
||||
BLOOD_RUSH(SpellBook.ANCIENT, 33, 16),
|
||||
ICE_RUSH(SpellBook.ANCIENT, 34, 17),
|
||||
|
||||
SMOKE_BURST(SpellBook.ANCIENT, 35, 18),
|
||||
SHADOW_BURST(SpellBook.ANCIENT, 36, 19),
|
||||
BLOOD_BURST(SpellBook.ANCIENT, 37, 21),
|
||||
ICE_BURST(SpellBook.ANCIENT, 38, 22),
|
||||
|
||||
SMOKE_BLITZ(SpellBook.ANCIENT, 39, 23),
|
||||
SHADOW_BLITZ(SpellBook.ANCIENT, 40, 24),
|
||||
BLOOD_BLITZ(SpellBook.ANCIENT, 41, 25),
|
||||
ICE_BLITZ(SpellBook.ANCIENT, 42, 26),
|
||||
|
||||
SMOKE_BARRAGE(SpellBook.ANCIENT, 43, 27),
|
||||
SHADOW_BARRAGE(SpellBook.ANCIENT, 44, 28),
|
||||
BLOOD_BARRAGE(SpellBook.ANCIENT, 55, 29),
|
||||
ICE_BARRAGE(SpellBook.ANCIENT, 46, 30),
|
||||
|
||||
/*
|
||||
* Other spells
|
||||
* */
|
||||
CRUMBLE_UNDEAD(SpellBook.OTHER, 17, 15),
|
||||
IBAN_BLAST(SpellBook.OTHER, 47, 25),
|
||||
FLAMES_OF_ZAMAROK(SpellBook.OTHER, 20, 20),
|
||||
CLAWS_OF_GUTHIX(SpellBook.OTHER, 19, 20),
|
||||
SARADOMIN_STRIKE(SpellBook.OTHER, 52, 20),
|
||||
|
||||
/*
|
||||
* Custom Formula spells
|
||||
* */
|
||||
MAGIC_DART(SpellBook.OTHER, 18, 0);
|
||||
|
||||
private final SpellBook spellBook;
|
||||
private final int spellID;
|
||||
private final int baseDamage;
|
||||
|
||||
SpellBaseDamageConfig(SpellBook spellBook, int spellID, int baseDamage)
|
||||
{
|
||||
this.spellBook = spellBook;
|
||||
this.spellID = spellID;
|
||||
this.baseDamage = baseDamage;
|
||||
}
|
||||
|
||||
public static SpellBaseDamageConfig findSpellById(int spellID)
|
||||
{
|
||||
return Arrays.stream(values()).filter(spell -> spell.getSpellID() == spellID).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public int getSpellID()
|
||||
{
|
||||
return spellID;
|
||||
}
|
||||
|
||||
public int getBaseDamage()
|
||||
{
|
||||
return baseDamage;
|
||||
}
|
||||
|
||||
public SpellBook getSpellBook()
|
||||
{
|
||||
return spellBook;
|
||||
}
|
||||
|
||||
public enum SpellBook
|
||||
{
|
||||
NORMAL,
|
||||
ANCIENT,
|
||||
OTHER
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.equipment;
|
||||
|
||||
import net.runelite.client.plugins.maxhit.calculators.MaxHitCalculator;
|
||||
|
||||
public class EquipmentCombatBonus
|
||||
{
|
||||
|
||||
private final double meleeBonus;
|
||||
private final double rangeBonus;
|
||||
private final double magicBonus;
|
||||
|
||||
public EquipmentCombatBonus(double meleeBonus, double rangeBonus, double magicBonus)
|
||||
{
|
||||
this.meleeBonus = meleeBonus;
|
||||
this.rangeBonus = rangeBonus;
|
||||
this.magicBonus = magicBonus;
|
||||
}
|
||||
|
||||
public double getCombatBonus(MaxHitCalculator.CombatMethod combatMethod)
|
||||
{
|
||||
switch (combatMethod)
|
||||
{
|
||||
default:
|
||||
case MELEE:
|
||||
return this.meleeBonus;
|
||||
case RANGE:
|
||||
return this.rangeBonus;
|
||||
case MAGIC:
|
||||
return this.magicBonus;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.equipment;
|
||||
|
||||
import net.runelite.api.EquipmentInventorySlot;
|
||||
import net.runelite.api.Item;
|
||||
|
||||
public class EquipmentHelper
|
||||
{
|
||||
|
||||
public static boolean wearsItemSet(Item[] equipedItems, EquipmentItemset itemSet)
|
||||
{
|
||||
return itemSet.getItems().stream().allMatch(item -> wearsItem(equipedItems, item));
|
||||
}
|
||||
|
||||
private static boolean wearsItem(Item[] equipedItems, EquipmentInventorySlot slot, int itemId)
|
||||
{
|
||||
Item item = equipedItems[slot.getSlotIdx()];
|
||||
if (item == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return item.getId() == itemId;
|
||||
}
|
||||
|
||||
public static boolean wearsItem(Item[] equipedItems, EquipmentSlotItem equipmentSlotItem)
|
||||
{
|
||||
return equipmentSlotItem.getItems().stream().anyMatch(itemId ->
|
||||
wearsItem(equipedItems, equipmentSlotItem.getEquipmentSlot(), itemId)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.equipment;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class EquipmentItemset
|
||||
{
|
||||
private final List<EquipmentSlotItem> items;
|
||||
|
||||
public EquipmentItemset(List<EquipmentSlotItem> items)
|
||||
{
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public List<EquipmentSlotItem> getItems()
|
||||
{
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.equipment;
|
||||
|
||||
import net.runelite.api.EquipmentInventorySlot;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class EquipmentSlotItem
|
||||
{
|
||||
private final EquipmentInventorySlot equipmentSlot;
|
||||
private final ArrayList<Integer> itemIds;
|
||||
|
||||
public EquipmentSlotItem(EquipmentInventorySlot equipmentSlot, ArrayList<Integer> itemIds)
|
||||
{
|
||||
this.equipmentSlot = equipmentSlot;
|
||||
this.itemIds = itemIds;
|
||||
}
|
||||
|
||||
public ArrayList<Integer> getItems()
|
||||
{
|
||||
return this.itemIds;
|
||||
}
|
||||
|
||||
public EquipmentInventorySlot getEquipmentSlot()
|
||||
{
|
||||
return this.equipmentSlot;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.requirements;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.client.plugins.maxhit.config.SpellBaseDamageConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class AutocastSpellRequirement implements Requirement
|
||||
{
|
||||
|
||||
private final ArrayList<SpellBaseDamageConfig> autocastSpells;
|
||||
|
||||
public AutocastSpellRequirement(ArrayList<SpellBaseDamageConfig> autocastSpells)
|
||||
{
|
||||
this.autocastSpells = autocastSpells;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsRequirements(Client client)
|
||||
{
|
||||
int autoCastSpellId = client.getVar(Varbits.AUTO_CAST_SPELL);
|
||||
|
||||
if (autoCastSpellId == 0)
|
||||
{
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return this.autocastSpells.stream().anyMatch(spell -> spell.getSpellID() == autoCastSpellId);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.requirements;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentHelper;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentSlotItem;
|
||||
|
||||
public class EquipmentItemRequirement implements Requirement
|
||||
{
|
||||
private final EquipmentSlotItem item;
|
||||
|
||||
public EquipmentItemRequirement(EquipmentSlotItem item)
|
||||
{
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsRequirements(Client client)
|
||||
{
|
||||
ItemContainer equipmentContainer = client.getItemContainer(InventoryID.EQUIPMENT);
|
||||
if (equipmentContainer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Item[] equipedItems = equipmentContainer.getItems();
|
||||
return EquipmentHelper.wearsItem(equipedItems, this.item);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.requirements;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentHelper;
|
||||
import net.runelite.client.plugins.maxhit.equipment.EquipmentItemset;
|
||||
|
||||
public class EquipmentItemSetRequirement implements Requirement
|
||||
{
|
||||
private final EquipmentItemset itemSet;
|
||||
|
||||
public EquipmentItemSetRequirement(EquipmentItemset itemSet)
|
||||
{
|
||||
this.itemSet = itemSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsRequirements(Client client)
|
||||
{
|
||||
ItemContainer equipmentContainer = client.getItemContainer(InventoryID.EQUIPMENT);
|
||||
if (equipmentContainer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
Item[] equipedItems = equipmentContainer.getItems();
|
||||
|
||||
return EquipmentHelper.wearsItemSet(equipedItems, this.itemSet);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.requirements;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
|
||||
public interface Requirement
|
||||
{
|
||||
boolean meetsRequirements(Client client);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.requirements;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.client.plugins.maxhit.config.SpellBaseDamageConfig;
|
||||
|
||||
public class SpellBookRequirement implements Requirement
|
||||
{
|
||||
private final SpellBaseDamageConfig.SpellBook spellBook;
|
||||
|
||||
public SpellBookRequirement(SpellBaseDamageConfig.SpellBook spellBook)
|
||||
{
|
||||
this.spellBook = spellBook;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsRequirements(Client client)
|
||||
{
|
||||
int autoCastSpellId = client.getVar(Varbits.AUTO_CAST_SPELL);
|
||||
if (autoCastSpellId == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SpellBaseDamageConfig autoCastSpell = SpellBaseDamageConfig.findSpellById(autoCastSpellId);
|
||||
return autoCastSpell.getSpellBook() == this.spellBook;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.requirements;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.client.plugins.maxhit.config.SpellBaseDamageConfig;
|
||||
|
||||
public class SpellRequirement implements Requirement
|
||||
{
|
||||
private final SpellBaseDamageConfig spellBaseDamageConfig;
|
||||
|
||||
public SpellRequirement(SpellBaseDamageConfig spellBaseDamageConfig)
|
||||
{
|
||||
this.spellBaseDamageConfig = spellBaseDamageConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean meetsRequirements(Client client)
|
||||
{
|
||||
int autoCastSpellId = client.getVar(Varbits.AUTO_CAST_SPELL);
|
||||
if (autoCastSpellId == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return autoCastSpellId == this.spellBaseDamageConfig.getSpellID();
|
||||
}
|
||||
}
|
||||
@@ -282,4 +282,14 @@ public interface MenuEntrySwapperConfig extends Config
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "swapRogueschests",
|
||||
name = "Rogueschests",
|
||||
description = "Swap Rogueschests from open to Search for traps"
|
||||
)
|
||||
default boolean swapRogueschests()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -544,6 +544,10 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
{
|
||||
swap("pick-lots", option, target, true);
|
||||
}
|
||||
else if (config.swapRogueschests() && target.contains("chest"))
|
||||
{
|
||||
swap("search for traps", option, target, true);
|
||||
}
|
||||
else if (config.shiftClickCustomization() && shiftModifier && !option.equals("use"))
|
||||
{
|
||||
Integer customOption = getSwapConfig(eventId);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,97 +25,220 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.pestcontrol;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.BLUE;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.PURPLE;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.RED;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.YELLOW;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.GameTick;
|
||||
|
||||
@Slf4j
|
||||
class Game
|
||||
public class Game
|
||||
{
|
||||
private Client client;
|
||||
|
||||
private PestControlPlugin plugin;
|
||||
|
||||
@Getter
|
||||
private Portal bluePortal = new Portal(PortalColor.BLUE, WidgetPortal.BLUE);
|
||||
|
||||
@Getter
|
||||
private Portal purplePortal = new Portal(PortalColor.PURPLE, WidgetPortal.PURPLE);
|
||||
|
||||
@Getter
|
||||
private Portal yellowPortal = new Portal(PortalColor.YELLOW, WidgetPortal.YELLOW);
|
||||
|
||||
@Getter
|
||||
private Portal redPortal = new Portal(PortalColor.RED, WidgetPortal.RED);
|
||||
|
||||
@Getter
|
||||
private int shieldsDropped = 0;
|
||||
|
||||
// Game starts with all possible rotations
|
||||
private Rotation[] possibleRotations = Rotation.values();
|
||||
// Number of shields dropped
|
||||
private int shieldsDropped;
|
||||
private PortalRotation[] possibleRotations = PortalRotation.values();
|
||||
|
||||
@Getter
|
||||
private final PortalContext purple = new PortalContext(PURPLE);
|
||||
@Getter
|
||||
private final PortalContext blue = new PortalContext(BLUE);
|
||||
@Getter
|
||||
private final PortalContext yellow = new PortalContext(YELLOW);
|
||||
@Getter
|
||||
private final PortalContext red = new PortalContext(RED);
|
||||
private boolean portalLocationsSet = false;
|
||||
|
||||
void fall(String color)
|
||||
|
||||
private Instant startTime = Instant.now();
|
||||
|
||||
public Game(Client client, PestControlPlugin plugin)
|
||||
{
|
||||
switch (color.toLowerCase())
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void onGameTick(GameTick gameTickEvent)
|
||||
{
|
||||
if (!portalLocationsSet)
|
||||
{
|
||||
loadPortalLocations();
|
||||
}
|
||||
|
||||
WidgetOverlay widgetOverlay = plugin.getWidgetOverlay();
|
||||
|
||||
if (!purplePortal.isDead() && widgetOverlay.getPortalHitpoints(PortalColor.PURPLE) == 0)
|
||||
{
|
||||
killPortal(purplePortal);
|
||||
}
|
||||
|
||||
if (!yellowPortal.isDead() && widgetOverlay.getPortalHitpoints(PortalColor.YELLOW) == 0)
|
||||
{
|
||||
killPortal(yellowPortal);
|
||||
}
|
||||
|
||||
if (!redPortal.isDead() && widgetOverlay.getPortalHitpoints(PortalColor.RED) == 0)
|
||||
{
|
||||
killPortal(redPortal);
|
||||
}
|
||||
|
||||
if (!bluePortal.isDead() && widgetOverlay.getPortalHitpoints(PortalColor.BLUE) == 0)
|
||||
{
|
||||
killPortal(bluePortal);
|
||||
}
|
||||
}
|
||||
|
||||
public void lowerPortalShield(String portalColor)
|
||||
{
|
||||
switch (portalColor.toLowerCase())
|
||||
{
|
||||
case "purple":
|
||||
fall(purple);
|
||||
lowerPortalShield(purplePortal);
|
||||
break;
|
||||
case "red":
|
||||
fall(red);
|
||||
lowerPortalShield(redPortal);
|
||||
break;
|
||||
case "yellow":
|
||||
fall(yellow);
|
||||
lowerPortalShield(yellowPortal);
|
||||
break;
|
||||
case "blue":
|
||||
fall(blue);
|
||||
lowerPortalShield(bluePortal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void fall(PortalContext portal)
|
||||
private void lowerPortalShield(Portal portal)
|
||||
{
|
||||
if (!portal.isShielded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Shield dropped for {}", portal.getPortal());
|
||||
log.debug("Shield dropped for {}", portal.getColor());
|
||||
|
||||
portal.setPortalState(PortalState.ACTIVE);
|
||||
|
||||
portal.setShielded(false);
|
||||
int shieldDrop = shieldsDropped++;
|
||||
|
||||
// Remove impossible rotations
|
||||
List<Rotation> rotations = new ArrayList<>();
|
||||
List<PortalRotation> rotations = new ArrayList<>();
|
||||
|
||||
for (Rotation rotation : possibleRotations)
|
||||
for (PortalRotation rotation : possibleRotations)
|
||||
{
|
||||
if (rotation.getPortal(shieldDrop) == portal.getPortal())
|
||||
if (rotation.getPortal(this, shieldDrop) == portal)
|
||||
{
|
||||
rotations.add(rotation);
|
||||
}
|
||||
}
|
||||
|
||||
possibleRotations = rotations.toArray(new Rotation[rotations.size()]);
|
||||
possibleRotations = rotations.toArray(new PortalRotation[rotations.size()]);
|
||||
}
|
||||
|
||||
void die(PortalContext portal)
|
||||
public void killPortal(Portal portal)
|
||||
{
|
||||
if (portal.isDead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Portal {} died", portal.getPortal());
|
||||
log.debug("Portal {} died", portal.getColor());
|
||||
|
||||
portal.setDead(true);
|
||||
portal.setPortalState(PortalState.DEAD);
|
||||
}
|
||||
|
||||
Collection<Portal> getNextPortals()
|
||||
private boolean loadPortalLocations()
|
||||
{
|
||||
NPC squire = null;
|
||||
|
||||
for (NPC npc : client.getNpcs())
|
||||
{
|
||||
if (PestControlNpc.isIngameSquireId(npc.getId()))
|
||||
{
|
||||
squire = npc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (squire != null)
|
||||
{
|
||||
log.debug("In-game Squire found: {}", squire);
|
||||
setPortalLocations(squire.getWorldLocation());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setPortalLocations(WorldPoint squireLocation)
|
||||
{
|
||||
int x = squireLocation.getX();
|
||||
int y = squireLocation.getY();
|
||||
|
||||
purplePortal.setLocation(new WorldPoint(x - 26, y - 15, 0));
|
||||
bluePortal.setLocation(new WorldPoint(x + 26, y - 18, 0));
|
||||
yellowPortal.setLocation(new WorldPoint(x + 15, y - 36, 0));
|
||||
redPortal.setLocation(new WorldPoint(x - 9, y - 37, 0));
|
||||
|
||||
portalLocationsSet = true;
|
||||
}
|
||||
|
||||
public List<Portal> getPortals()
|
||||
{
|
||||
List<Portal> portalList = new ArrayList<Portal>();
|
||||
|
||||
portalList.add(getPurplePortal());
|
||||
portalList.add(getBluePortal());
|
||||
portalList.add(getYellowPortal());
|
||||
portalList.add(getRedPortal());
|
||||
|
||||
return portalList;
|
||||
}
|
||||
|
||||
public Portal getPortal(PortalColor portalColor)
|
||||
{
|
||||
if (bluePortal.getColor() == portalColor)
|
||||
{
|
||||
return bluePortal;
|
||||
}
|
||||
if (redPortal.getColor() == portalColor)
|
||||
{
|
||||
return redPortal;
|
||||
}
|
||||
if (purplePortal.getColor() == portalColor)
|
||||
{
|
||||
return purplePortal;
|
||||
}
|
||||
if (yellowPortal.getColor() == portalColor)
|
||||
{
|
||||
return yellowPortal;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Collection<Portal> getNextPortals()
|
||||
{
|
||||
List<Portal> portals = new ArrayList<>();
|
||||
|
||||
for (Rotation rotation : possibleRotations)
|
||||
for (PortalRotation rotation : possibleRotations)
|
||||
{
|
||||
Portal portal = rotation.getPortal(shieldsDropped);
|
||||
Portal portal = rotation.getPortal(this, shieldsDropped);
|
||||
|
||||
if (portal != null && !portals.contains(portal))
|
||||
{
|
||||
@@ -124,4 +248,40 @@ class Game
|
||||
|
||||
return portals;
|
||||
}
|
||||
|
||||
public Collection<Portal> getActivePortals()
|
||||
{
|
||||
List<Portal> portals = new ArrayList<>();
|
||||
|
||||
for (Portal portal : getPortals())
|
||||
{
|
||||
if (portal.isActive())
|
||||
{
|
||||
portals.add(portal);
|
||||
}
|
||||
}
|
||||
|
||||
return portals;
|
||||
}
|
||||
|
||||
public Duration getTimeTillNextPortal()
|
||||
{
|
||||
Instant nextShieldDrop;
|
||||
|
||||
if (shieldsDropped == 4)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (shieldsDropped == 0)
|
||||
{
|
||||
nextShieldDrop = Instant.ofEpochSecond(startTime.getEpochSecond() + 17);
|
||||
}
|
||||
else
|
||||
{
|
||||
nextShieldDrop = Instant.ofEpochSecond(startTime.getEpochSecond() + 17 + (30 * shieldsDropped));
|
||||
}
|
||||
|
||||
return Duration.between(Instant.now(), nextShieldDrop);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.tooltip.Tooltip;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
@Slf4j
|
||||
public class GangplankOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final PestControlConfig config;
|
||||
private final PestControlPlugin plugin;
|
||||
private final TooltipManager tooltipManager;
|
||||
|
||||
@Inject
|
||||
GangplankOverlay(Client client, PestControlConfig config, PestControlPlugin plugin, TooltipManager toolTipManager)
|
||||
{
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
this.tooltipManager = toolTipManager;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.isOnPestControlMainIsland())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Player localPlayer = client.getLocalPlayer();
|
||||
|
||||
if (localPlayer == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int combatLevel = localPlayer.getCombatLevel();
|
||||
|
||||
Color noviceCbColor = (combatLevel >= 40) ? Color.GREEN : Color.RED;
|
||||
Color intermediateCbColor = (combatLevel >= 70) ? Color.GREEN : Color.RED;
|
||||
Color veteranCbColor = (combatLevel >= 100) ? Color.GREEN : Color.RED;
|
||||
|
||||
Tile noviceGangplankTile = plugin.getNoviceGangplankTile();
|
||||
Tile intermediateGangplankTile = plugin.getIntermediateGangplankTile();
|
||||
Tile veteranGangplankTile = plugin.getVeteranGangplankTile();
|
||||
|
||||
Point mousePosition = client.getMouseCanvasPosition();
|
||||
String tooltipString = null;
|
||||
|
||||
if (noviceGangplankTile != null)
|
||||
{
|
||||
Polygon polygon = noviceGangplankTile.getGameObjects()[0].getConvexHull();
|
||||
if (polygon != null)
|
||||
{
|
||||
graphics.setColor(noviceCbColor);
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.drawPolygon(polygon);
|
||||
graphics.setColor(setColorAlpha(noviceCbColor, 45));
|
||||
graphics.fill(polygon);
|
||||
|
||||
if (polygon.contains(mousePosition.getX(), mousePosition.getY()))
|
||||
{
|
||||
tooltipString = ColorUtil.wrapWithColorTag("Combat 40+", noviceCbColor) + " (3 points)";
|
||||
graphics.setColor(setColorAlpha(noviceCbColor, 65));
|
||||
graphics.fill(polygon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (intermediateGangplankTile != null)
|
||||
{
|
||||
Polygon polygon = intermediateGangplankTile.getGameObjects()[0].getConvexHull();
|
||||
if (polygon != null)
|
||||
{
|
||||
graphics.setColor(intermediateCbColor);
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.drawPolygon(polygon);
|
||||
graphics.setColor(setColorAlpha(intermediateCbColor, 45));
|
||||
graphics.fill(polygon);
|
||||
|
||||
if (polygon.contains(mousePosition.getX(), mousePosition.getY()))
|
||||
{
|
||||
tooltipString = ColorUtil.wrapWithColorTag("Combat 70+", intermediateCbColor) + " (4 points)";
|
||||
graphics.setColor(setColorAlpha(intermediateCbColor, 65));
|
||||
graphics.fill(polygon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (veteranGangplankTile != null)
|
||||
{
|
||||
Polygon polygon = veteranGangplankTile.getGameObjects()[0].getConvexHull();
|
||||
if (polygon != null)
|
||||
{
|
||||
graphics.setColor(veteranCbColor);
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.drawPolygon(polygon);
|
||||
graphics.setColor(setColorAlpha(veteranCbColor, 45));
|
||||
graphics.fill(polygon);
|
||||
|
||||
if (polygon.contains(mousePosition.getX(), mousePosition.getY()))
|
||||
{
|
||||
tooltipString = ColorUtil.wrapWithColorTag("Combat 100+", veteranCbColor) + " (5 points)";
|
||||
graphics.setColor(setColorAlpha(veteranCbColor, 65));
|
||||
graphics.fill(polygon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tooltipString != null)
|
||||
{
|
||||
tooltipManager.add(new Tooltip(tooltipString));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Color setColorAlpha(Color color, int alpha)
|
||||
{
|
||||
return new Color(
|
||||
color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(),
|
||||
alpha
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
|
||||
public class HintArrowOverlay extends Overlay
|
||||
{
|
||||
private final PestControlConfig config;
|
||||
private final PestControlPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
HintArrowOverlay(PestControlConfig config, PestControlPlugin plugin, Client client)
|
||||
{
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (plugin.getGame() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
List<NPC> visibleActivePortals = new ArrayList<>();
|
||||
List<NPC> visibleShieldedPortals = new ArrayList<>();
|
||||
|
||||
for (NPC npc : client.getNpcs())
|
||||
{
|
||||
if (PestControlNpc.isActivePortalId(npc.getId()))
|
||||
{
|
||||
visibleActivePortals.add(npc);
|
||||
}
|
||||
}
|
||||
|
||||
if (!visibleActivePortals.isEmpty())
|
||||
{
|
||||
NPC closestPortalNpc = getClosestNpc(visibleActivePortals);
|
||||
|
||||
if (closestPortalNpc != null)
|
||||
{
|
||||
NPC currentHintArrowTarget = client.getHintArrowNpc();
|
||||
|
||||
if (currentHintArrowTarget == null || currentHintArrowTarget != closestPortalNpc)
|
||||
{
|
||||
client.setHintArrow(closestPortalNpc);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Portal closestActivePortal = getClosestPortal(PortalState.ACTIVE);
|
||||
|
||||
if (closestActivePortal != null)
|
||||
{
|
||||
WorldPoint currentHintArrowLocation = client.getHintArrowPoint();
|
||||
WorldPoint closestActivePortalLocation = closestActivePortal.getLocation();
|
||||
|
||||
if (currentHintArrowLocation == null || currentHintArrowLocation != closestActivePortalLocation)
|
||||
{
|
||||
client.setHintArrow(closestActivePortalLocation);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Collection<Portal> nextPortalList = plugin.getGame().getNextPortals();
|
||||
|
||||
if (nextPortalList.size() == 1)
|
||||
{
|
||||
client.setHintArrow(nextPortalList.iterator().next().getLocation());
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private NPC getClosestNpc(List<NPC> npcList)
|
||||
{
|
||||
WorldPoint currentLocation = client.getLocalPlayer().getWorldLocation();
|
||||
|
||||
NPC closestNpc = null;
|
||||
int currentShortestDistance = 1337;
|
||||
int distanceToNpc;
|
||||
|
||||
for (NPC npc : npcList)
|
||||
{
|
||||
if (closestNpc != null)
|
||||
{
|
||||
distanceToNpc = npc.getWorldLocation().distanceTo(currentLocation);
|
||||
|
||||
if (distanceToNpc < currentShortestDistance)
|
||||
{
|
||||
closestNpc = npc;
|
||||
currentShortestDistance = distanceToNpc;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
closestNpc = npc;
|
||||
}
|
||||
}
|
||||
|
||||
return closestNpc;
|
||||
}
|
||||
|
||||
private Portal getClosestPortal(PortalState portalState)
|
||||
{
|
||||
WorldPoint currentLocation = client.getLocalPlayer().getWorldLocation();
|
||||
|
||||
Portal closestPortal = null;
|
||||
int currentShortestDistance = 1337;
|
||||
int distanceToWorldPoint;
|
||||
|
||||
for (Portal portal : plugin.getGame().getPortals())
|
||||
{
|
||||
if (portal.getPortalState() != portalState)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
distanceToWorldPoint = portal.getLocation().distanceTo(currentLocation);
|
||||
|
||||
if (distanceToWorldPoint < currentShortestDistance)
|
||||
{
|
||||
closestPortal = portal;
|
||||
currentShortestDistance = distanceToWorldPoint;
|
||||
}
|
||||
}
|
||||
|
||||
return closestPortal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import java.awt.Color;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.client.plugins.pestcontrol.config.NpcHighlightStyle;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
public class NpcHighlightContext
|
||||
{
|
||||
private NpcHighlightStyle npcRenderStyle;
|
||||
private Color color;
|
||||
private boolean showNpcName = false;
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.util.HashMap;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.client.plugins.pestcontrol.config.NpcHighlightStyle;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
@Slf4j
|
||||
public class NpcHighlightOverlay extends Overlay
|
||||
{
|
||||
private final PestControlConfig config;
|
||||
private final PestControlPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
NpcHighlightOverlay(PestControlConfig config, PestControlPlugin plugin, Client client)
|
||||
{
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (plugin.getGame() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
HashMap highlightedNpcList = plugin.getHighlightedNpcList();
|
||||
|
||||
for (NPC npc : client.getNpcs())
|
||||
{
|
||||
if (!highlightedNpcList.containsKey(npc.getId()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
NpcHighlightContext npcHighlightContext = plugin.getHighlightedNpcList().get(npc.getId());
|
||||
|
||||
String name = npcHighlightContext.isShowNpcName() ? npc.getName() : null;
|
||||
Color color = npcHighlightContext.getColor();
|
||||
NpcHighlightStyle highlightStyle = npcHighlightContext.getNpcRenderStyle();
|
||||
|
||||
switch (highlightStyle)
|
||||
{
|
||||
case HULL:
|
||||
{
|
||||
renderHullOverlay(graphics, npc, color);
|
||||
break;
|
||||
}
|
||||
case TILE:
|
||||
{
|
||||
renderTileOverlay(graphics, npc, color);
|
||||
break;
|
||||
}
|
||||
case BOTH:
|
||||
{
|
||||
renderHullOverlay(graphics, npc, color);
|
||||
renderTileOverlay(graphics, npc, color);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (name != null)
|
||||
{
|
||||
renderTextOverlay(graphics, npc, name, color);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderTileOverlay(Graphics2D graphics, NPC npc, Color color)
|
||||
{
|
||||
Polygon polygon;
|
||||
Color fillColor;
|
||||
|
||||
// Double the polygon size if it's a Brawler
|
||||
if (PestControlNpc.isBrawlerId(npc.getId()))
|
||||
{
|
||||
polygon = Perspective.getCanvasTileAreaPoly(client, npc.getLocalLocation(), 2);
|
||||
fillColor = new Color(color.getRed(), color.getGreen(), color.getBlue(), 35);
|
||||
}
|
||||
else
|
||||
{
|
||||
polygon = npc.getCanvasTilePoly();
|
||||
fillColor = new Color(0, 0, 0, 50);
|
||||
}
|
||||
|
||||
if (polygon != null)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.drawPolygon(polygon);
|
||||
graphics.setColor(fillColor);
|
||||
graphics.fillPolygon(polygon);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderHullOverlay(Graphics2D graphics, NPC npc, Color color)
|
||||
{
|
||||
Polygon objectClickbox = npc.getConvexHull();
|
||||
if (objectClickbox != null)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.draw(objectClickbox);
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), 20));
|
||||
graphics.fill(objectClickbox);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderTextOverlay(Graphics2D graphics, NPC npc, String text, Color color)
|
||||
{
|
||||
Point textLocation = npc.getCanvasTextLocation(graphics, text, npc.getLogicalHeight() + 40);
|
||||
if (textLocation != null)
|
||||
{
|
||||
OverlayUtil.renderTextLocation(graphics, textLocation, text, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.plugins.pestcontrol.config.HighlightPortalOption;
|
||||
import net.runelite.client.plugins.pestcontrol.config.NpcHighlightStyle;
|
||||
|
||||
@ConfigGroup("pestcontrol")
|
||||
public interface PestControlConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "showHintArrow",
|
||||
name = "Show hint arrows",
|
||||
description = "Show hint arrows to the portals that can be attacked.",
|
||||
position = 1
|
||||
)
|
||||
default boolean showHintArrow()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showPortalWeakness",
|
||||
name = "Show portal weakness",
|
||||
description = "Show the combat style weakness of the portals. For melee the attack styles are shown: Stab/Crush/Slash",
|
||||
position = 2
|
||||
)
|
||||
default boolean showPortalWeakness()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "highlightGangplanks",
|
||||
name = "Highlight gangplanks",
|
||||
description = "Highlight the boarding gangplanks and show the required combat level.",
|
||||
position = 3
|
||||
)
|
||||
default boolean highlightGangplanks()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "highlightPortals",
|
||||
name = "Highlight portals",
|
||||
description = "Highlight all, active or shielded portals.",
|
||||
position = 4
|
||||
)
|
||||
default HighlightPortalOption portalHighlight()
|
||||
{
|
||||
return HighlightPortalOption.ACTIVE;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "activePortalColor",
|
||||
name = "Active portal color",
|
||||
description = "Color of the portals that can be attacked.",
|
||||
position = 5
|
||||
)
|
||||
default Color activePortalColor()
|
||||
{
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "shieldedPortalColor",
|
||||
name = "Shielded portal color",
|
||||
description = "Color of the portals that are shielded.",
|
||||
position = 6
|
||||
)
|
||||
default Color shieldedPortalColor()
|
||||
{
|
||||
return Color.BLUE;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "highlightSpinners",
|
||||
name = "Highlight Spinners",
|
||||
description = "Highlights Spinners. Highlighting them is recommended as Spinners heal the portals.",
|
||||
position = 7
|
||||
)
|
||||
default NpcHighlightStyle highlightSpinners()
|
||||
{
|
||||
return NpcHighlightStyle.BOTH;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "spinnerColor",
|
||||
name = "Spinner color",
|
||||
description = "Color of highlighted Spinners.",
|
||||
position = 8
|
||||
)
|
||||
default Color spinnerColor()
|
||||
{
|
||||
return Color.CYAN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "highlightBrawlers",
|
||||
name = "Highlight Brawlers",
|
||||
description = "Highlights Brawlers.",
|
||||
position = 9
|
||||
)
|
||||
default NpcHighlightStyle highlightBrawlers()
|
||||
{
|
||||
return NpcHighlightStyle.TILE;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "brawlerColor",
|
||||
name = "Brawler color",
|
||||
description = "Color of highlighted Brawlers.",
|
||||
position = 10
|
||||
)
|
||||
default Color brawlerColor()
|
||||
{
|
||||
return Color.ORANGE;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "highlightRepairables",
|
||||
name = "Highlight repairables",
|
||||
description = "Highlight repairable barricades and gates.",
|
||||
position = 11
|
||||
)
|
||||
default boolean highlightRepairables()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "repairableColor",
|
||||
name = "Repairable color",
|
||||
description = "Color of highlighted repairables.",
|
||||
position = 12
|
||||
)
|
||||
/*default Color repairableColor()
|
||||
{
|
||||
return new Color(193, 141, 255);
|
||||
}*/
|
||||
default Color repairableColor()
|
||||
{
|
||||
return Color.YELLOW;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showPoints",
|
||||
name = "Show points indicator",
|
||||
description = "Always display your points when on the island or in the minigame.",
|
||||
position = 13
|
||||
)
|
||||
default boolean showPoints()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showTimeTillNextPortal",
|
||||
name = "Show time till next portal",
|
||||
description = "Show a timer that counts down till the next portal is attackable.",
|
||||
position = 14
|
||||
)
|
||||
default boolean showTimeTillNextPortal()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.NpcID;
|
||||
|
||||
@Getter
|
||||
public class PestControlNpc
|
||||
{
|
||||
@Getter
|
||||
private static final Set<Integer> splatterIdSet = ImmutableSet.of(
|
||||
NpcID.SPLATTER,
|
||||
NpcID.SPLATTER_1690,
|
||||
NpcID.SPLATTER_1691,
|
||||
NpcID.SPLATTER_1692,
|
||||
NpcID.SPLATTER_1693
|
||||
);
|
||||
|
||||
@Getter
|
||||
public static final Set<Integer> shifterIdSet = ImmutableSet.of(
|
||||
NpcID.SHIFTER,
|
||||
NpcID.SHIFTER_1695,
|
||||
NpcID.SHIFTER_1696,
|
||||
NpcID.SHIFTER_1697,
|
||||
NpcID.SHIFTER_1698,
|
||||
NpcID.SHIFTER_1699,
|
||||
NpcID.SHIFTER_1700,
|
||||
NpcID.SHIFTER_1701,
|
||||
NpcID.SHIFTER_1702,
|
||||
NpcID.SHIFTER_1703
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> spinnerIdSet = ImmutableSet.of(
|
||||
NpcID.SPINNER,
|
||||
NpcID.SPINNER_1710,
|
||||
NpcID.SPINNER_1711,
|
||||
NpcID.SPINNER_1712,
|
||||
NpcID.SPINNER_1713
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> torcherIdSet = ImmutableSet.of(
|
||||
NpcID.TORCHER,
|
||||
NpcID.TORCHER_1715,
|
||||
NpcID.TORCHER_1716,
|
||||
NpcID.TORCHER_1717,
|
||||
NpcID.TORCHER_1718,
|
||||
NpcID.TORCHER_1719,
|
||||
NpcID.TORCHER_1720,
|
||||
NpcID.TORCHER_1721,
|
||||
NpcID.TORCHER_1722,
|
||||
NpcID.TORCHER_1723
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> defilerIdSet = ImmutableSet.of(
|
||||
NpcID.DEFILER,
|
||||
NpcID.DEFILER_1725,
|
||||
NpcID.DEFILER_1726,
|
||||
NpcID.DEFILER_1727,
|
||||
NpcID.DEFILER_1728,
|
||||
NpcID.DEFILER_1729,
|
||||
NpcID.DEFILER_1730,
|
||||
NpcID.DEFILER_1731,
|
||||
NpcID.DEFILER_1732,
|
||||
NpcID.DEFILER_1733
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> brawlerIdSet = ImmutableSet.of(
|
||||
NpcID.BRAWLER,
|
||||
NpcID.BRAWLER_1735,
|
||||
NpcID.BRAWLER_1736,
|
||||
NpcID.BRAWLER_1737,
|
||||
NpcID.BRAWLER_1738
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> ravagerIdSet = ImmutableSet.of(
|
||||
NpcID.RAVAGER,
|
||||
NpcID.RAVAGER_1705,
|
||||
NpcID.RAVAGER_1706,
|
||||
NpcID.RAVAGER_1707,
|
||||
NpcID.RAVAGER_1708
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> activePortalIdSet = ImmutableSet.of(
|
||||
NpcID.PORTAL_1747, // Novice Purple Active
|
||||
NpcID.PORTAL_1748, // Novice Blue Active
|
||||
NpcID.PORTAL_1749, // Novice Yellow Active
|
||||
NpcID.PORTAL_1750, // Novice Red Active
|
||||
NpcID.PORTAL, // Intermediate Purple Active
|
||||
NpcID.PORTAL_1740, // Intermediate Blue Active
|
||||
NpcID.PORTAL_1741, // Intermediate Yellow Active
|
||||
NpcID.PORTAL_1742 // Intermediate Red Active
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> shieldedPortalIdSet = ImmutableSet.of(
|
||||
NpcID.PORTAL_1751, // Novice Purple Shielded
|
||||
NpcID.PORTAL_1752, // Novice Blue Shielded
|
||||
NpcID.PORTAL_1753, // Novice Yellow Shielded
|
||||
NpcID.PORTAL_1754, // Novice Red Shielded
|
||||
NpcID.PORTAL_1743, // Intermediate Purple Shielded
|
||||
NpcID.PORTAL_1744, // Intermediate Blue Shielded
|
||||
NpcID.PORTAL_1745, // Intermediate Yellow Shielded
|
||||
NpcID.PORTAL_1746 // Intermediate Red Shielded
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> purplePortalIdSet = ImmutableSet.of(
|
||||
NpcID.PORTAL_1747, // Novice Purple Active
|
||||
NpcID.PORTAL_1751, // Novice Purple Shielded
|
||||
NpcID.PORTAL, // Intermediate Purple Active
|
||||
NpcID.PORTAL_1743 // Intermediate Purple Shielded
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> bluePortalIdSet = ImmutableSet.of(
|
||||
NpcID.PORTAL_1748, // Novice Blue Active
|
||||
NpcID.PORTAL_1752, // Novice Blue Shielded
|
||||
NpcID.PORTAL_1740, // Intermediate Blue Active
|
||||
NpcID.PORTAL_1744 // Intermediate Blue Shielded
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> yellowPortalIdSet = ImmutableSet.of(
|
||||
NpcID.PORTAL_1749, // Novice Yellow Active
|
||||
NpcID.PORTAL_1753, // Novice Yellow Shielded
|
||||
NpcID.PORTAL_1741, // Intermediate Yellow Active
|
||||
NpcID.PORTAL_1745 // Intermediate Yellow Shielded
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> redPortalIdSet = ImmutableSet.of(
|
||||
NpcID.PORTAL_1750, // Novice Red Active
|
||||
NpcID.PORTAL_1754, // Novice Red Shielded
|
||||
NpcID.PORTAL_1742, // Intermediate Red Active
|
||||
NpcID.PORTAL_1746 // Intermediate Red Shielded
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> ingameVoidKnightIdSet = ImmutableSet.of(
|
||||
NpcID.VOID_KNIGHT_2950,
|
||||
NpcID.VOID_KNIGHT_2951,
|
||||
NpcID.VOID_KNIGHT_2952,
|
||||
NpcID.VOID_KNIGHT_2953
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Integer ingameSquireId = NpcID.SQUIRE_2949;
|
||||
|
||||
public static boolean isSplatterId(int npcId)
|
||||
{
|
||||
return splatterIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isShifterId(int npcId)
|
||||
{
|
||||
return shifterIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isSpinnerId(int npcId)
|
||||
{
|
||||
return brawlerIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isTorcherId(int npcId)
|
||||
{
|
||||
return torcherIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isDefilerId(int npcId)
|
||||
{
|
||||
return defilerIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isBrawlerId(int npcId)
|
||||
{
|
||||
return brawlerIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isRavagerId(int npcId)
|
||||
{
|
||||
return ravagerIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isIngameVoidKnightId(int npcId)
|
||||
{
|
||||
return ingameVoidKnightIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isIngameSquireId(int npcId)
|
||||
{
|
||||
return ingameSquireId == npcId;
|
||||
}
|
||||
|
||||
public static boolean isPortalId(int npcId)
|
||||
{
|
||||
return (isActivePortalId(npcId) || isShieldedPortalId(npcId));
|
||||
}
|
||||
|
||||
public static boolean isActivePortalId(int npcId)
|
||||
{
|
||||
return activePortalIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isShieldedPortalId(int npcId)
|
||||
{
|
||||
return shieldedPortalIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isPurplePortalId(int npcId)
|
||||
{
|
||||
return purplePortalIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isBluePortalId(int npcId)
|
||||
{
|
||||
return bluePortalIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isYellowPortalId(int npcId)
|
||||
{
|
||||
return yellowPortalIdSet.contains(npcId);
|
||||
}
|
||||
|
||||
public static boolean isRedPortalId(int npcId)
|
||||
{
|
||||
return redPortalIdSet.contains(npcId);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Kronos <https://github.com/KronosDesign>
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,29 +25,47 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.pestcontrol;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.TileObject;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameObjectChanged;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.GroundObjectChanged;
|
||||
import net.runelite.api.events.GroundObjectDespawned;
|
||||
import net.runelite.api.events.GroundObjectSpawned;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.pestcontrol.config.HighlightPortalOption;
|
||||
import net.runelite.client.plugins.pestcontrol.config.NpcHighlightStyle;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "Pest Control",
|
||||
description = "Show helpful information for the Pest Control minigame",
|
||||
@@ -54,77 +73,598 @@ import net.runelite.client.ui.overlay.OverlayManager;
|
||||
)
|
||||
public class PestControlPlugin extends Plugin
|
||||
{
|
||||
private static final Set<Integer> SPINNER_IDS = ImmutableSet.of(
|
||||
NpcID.SPINNER,
|
||||
NpcID.SPINNER_1710,
|
||||
NpcID.SPINNER_1711,
|
||||
NpcID.SPINNER_1712,
|
||||
NpcID.SPINNER_1713
|
||||
);
|
||||
private final int NOVICE_GANGPLANK = 14315; // Combat 40+ (3 points)
|
||||
private final int INTERMEDIATE_GANGPLANK = 25631; // Combat 70+ (4 points)
|
||||
private final int VETERAN_GANGPLANK = 25632; // Combat 100+ (5 points)
|
||||
|
||||
private final Pattern SHIELD_DROP = Pattern.compile("The ([a-z]+), [^ ]+ portal shield has dropped!", Pattern.CASE_INSENSITIVE);
|
||||
private final Pattern SHIELD_DROP_PATTERN = Pattern.compile("The ([a-z]+), [^ ]+ portal shield has dropped!");
|
||||
private final Pattern EXCHANGE_WINDOW_POINTS_PATTERN = Pattern.compile("Points: <col=ffffff>([0-9]+)</col>");
|
||||
private final Pattern BOAT_POINTS_PATTERN = Pattern.compile("Pest Points: ([0-9]+)");
|
||||
private final Pattern AWARDED_PATTERN = Pattern.compile("We've awarded you ([0-9]+) Void Knight Commendation points.");
|
||||
private final Pattern PURCHASE_PATTERN = Pattern.compile("Remaining Void Knight Commendation Points: ([0-9]+)");
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<NPC> spinners = new ArrayList<>();
|
||||
@Inject
|
||||
@Getter
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private PestControlOverlay overlay;
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Inject
|
||||
@Getter
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
@Getter
|
||||
private PestControlConfig config;
|
||||
|
||||
@Inject
|
||||
@Getter
|
||||
private WidgetOverlay widgetOverlay;
|
||||
|
||||
@Inject
|
||||
private HintArrowOverlay hintArrowOverlay;
|
||||
|
||||
@Inject
|
||||
private NpcHighlightOverlay npcHighlightOverlay;
|
||||
|
||||
@Inject
|
||||
private RepairOverlay repairOverlay;
|
||||
|
||||
@Inject
|
||||
private GangplankOverlay gangplankOverlay;
|
||||
|
||||
@Inject
|
||||
private TimerOverlay timerOverlay;
|
||||
|
||||
@Inject
|
||||
private PortalWeaknessOverlay portalWeaknessOverlay;
|
||||
|
||||
@Getter
|
||||
private Game game;
|
||||
|
||||
@Getter
|
||||
private HashMap<Integer, NpcHighlightContext> highlightedNpcList = new HashMap<Integer, NpcHighlightContext>();
|
||||
|
||||
@Getter
|
||||
private List<TileObject> highlightedRepairList = new ArrayList<TileObject>();
|
||||
|
||||
@Getter
|
||||
private Tile noviceGangplankTile;
|
||||
|
||||
@Getter
|
||||
private Tile intermediateGangplankTile;
|
||||
|
||||
@Getter
|
||||
private Tile veteranGangplankTile;
|
||||
|
||||
@Getter
|
||||
private Integer commendationPoints;
|
||||
|
||||
private String userConfigKey;
|
||||
|
||||
private boolean checkForPointWidgets;
|
||||
|
||||
private boolean pointsRewarded = false;
|
||||
|
||||
private PointsInfoboxCounter pointsInfoboxCounter;
|
||||
|
||||
|
||||
@Provides
|
||||
PestControlConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(PestControlConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
loadPlugin();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
spinners.clear();
|
||||
unloadPlugin();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged configEvent)
|
||||
{
|
||||
if (configEvent.getGroup().equals("pestcontrol"))
|
||||
{
|
||||
unloadPlugin();
|
||||
loadPlugin();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadLocalUserPoints()
|
||||
{
|
||||
if (userConfigKey != null)
|
||||
{
|
||||
String configKey = "points." + userConfigKey;
|
||||
String pointString = configManager.getConfiguration("pestcontrol", configKey);
|
||||
if (pointString != null)
|
||||
{
|
||||
commendationPoints = Integer.parseInt(pointString);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void loadPlugin()
|
||||
{
|
||||
if (loadLocalUserPoints())
|
||||
{
|
||||
handlePointsInfoboxCounter();
|
||||
}
|
||||
|
||||
overlayManager.add(widgetOverlay);
|
||||
|
||||
if (config.highlightSpinners() != NpcHighlightStyle.OFF)
|
||||
{
|
||||
for (Integer npcId : PestControlNpc.getSpinnerIdSet())
|
||||
{
|
||||
highlightedNpcList.put(npcId, new NpcHighlightContext(
|
||||
config.highlightSpinners(),
|
||||
config.spinnerColor(),
|
||||
true
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (config.highlightBrawlers() != NpcHighlightStyle.OFF)
|
||||
{
|
||||
for (Integer npcId : PestControlNpc.getBrawlerIdSet())
|
||||
{
|
||||
highlightedNpcList.put(npcId, new NpcHighlightContext(
|
||||
config.highlightBrawlers(),
|
||||
config.brawlerColor(),
|
||||
false
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (config.portalHighlight() != HighlightPortalOption.OFF)
|
||||
{
|
||||
if (config.portalHighlight() == HighlightPortalOption.ACTIVE ||
|
||||
config.portalHighlight() == HighlightPortalOption.ALL)
|
||||
{
|
||||
for (Integer portalNpcId : PestControlNpc.getActivePortalIdSet())
|
||||
{
|
||||
highlightedNpcList.put(portalNpcId, new NpcHighlightContext(
|
||||
NpcHighlightStyle.HULL,
|
||||
config.activePortalColor(),
|
||||
false
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (config.portalHighlight() == HighlightPortalOption.SHIELDED ||
|
||||
config.portalHighlight() == HighlightPortalOption.ALL)
|
||||
{
|
||||
for (Integer portalNpcId : PestControlNpc.getShieldedPortalIdSet())
|
||||
{
|
||||
highlightedNpcList.put(portalNpcId, new NpcHighlightContext(
|
||||
NpcHighlightStyle.HULL,
|
||||
config.shieldedPortalColor(),
|
||||
false
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!highlightedNpcList.isEmpty())
|
||||
{
|
||||
overlayManager.add(npcHighlightOverlay);
|
||||
}
|
||||
|
||||
if (config.highlightRepairables())
|
||||
{
|
||||
overlayManager.add(repairOverlay);
|
||||
}
|
||||
|
||||
if (config.showHintArrow())
|
||||
{
|
||||
overlayManager.add(hintArrowOverlay);
|
||||
|
||||
if (game != null && client.hasHintArrow())
|
||||
{
|
||||
client.clearHintArrow();
|
||||
}
|
||||
}
|
||||
|
||||
if (config.highlightGangplanks())
|
||||
{
|
||||
overlayManager.add(gangplankOverlay);
|
||||
}
|
||||
|
||||
if (config.showTimeTillNextPortal())
|
||||
{
|
||||
overlayManager.add(timerOverlay);
|
||||
}
|
||||
|
||||
if (config.showPortalWeakness())
|
||||
{
|
||||
overlayManager.add(portalWeaknessOverlay);
|
||||
}
|
||||
}
|
||||
|
||||
private void unloadPlugin()
|
||||
{
|
||||
overlayManager.remove(widgetOverlay);
|
||||
overlayManager.remove(npcHighlightOverlay);
|
||||
overlayManager.remove(repairOverlay);
|
||||
overlayManager.remove(gangplankOverlay);
|
||||
overlayManager.remove(hintArrowOverlay);
|
||||
overlayManager.remove(timerOverlay);
|
||||
overlayManager.remove(portalWeaknessOverlay);
|
||||
|
||||
infoBoxManager.removeInfoBox(pointsInfoboxCounter);
|
||||
pointsInfoboxCounter = null;
|
||||
|
||||
highlightedNpcList.clear();
|
||||
|
||||
if (game != null && config.showHintArrow() && client.hasHintArrow())
|
||||
{
|
||||
client.clearHintArrow();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
GameState gameState = event.getGameState();
|
||||
if (gameState == GameState.CONNECTION_LOST || gameState == GameState.LOGIN_SCREEN || gameState == GameState.HOPPING)
|
||||
// LOGGED_IN also triggers when teleporting to the island
|
||||
if (event.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
spinners.clear();
|
||||
handlePointsInfoboxCounter();
|
||||
}
|
||||
}
|
||||
|
||||
public void handlePointsInfoboxCounter()
|
||||
{
|
||||
if (!config.showPoints())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isOnPestControlMainIsland() && !isInPestControlInstance())
|
||||
{
|
||||
infoBoxManager.removeInfoBox(pointsInfoboxCounter);
|
||||
pointsInfoboxCounter = null;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (commendationPoints == null)
|
||||
{
|
||||
if (pointsInfoboxCounter != null)
|
||||
{
|
||||
infoBoxManager.removeInfoBox(pointsInfoboxCounter);
|
||||
pointsInfoboxCounter = null;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (pointsInfoboxCounter != null)
|
||||
{
|
||||
pointsInfoboxCounter.setCount(commendationPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferedImage image = itemManager.getImage(ItemID.VOID_SEAL1);
|
||||
pointsInfoboxCounter = new PointsInfoboxCounter(image, this, commendationPoints);
|
||||
pointsInfoboxCounter.setTooltip("Void Knight Commendation Points");
|
||||
infoBoxManager.addInfoBox(pointsInfoboxCounter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void getPointsFromWidgets()
|
||||
{
|
||||
|
||||
// Get points from dialog after the game
|
||||
Widget npcDialog = client.getWidget(WidgetInfo.DIALOG_NPC_TEXT);
|
||||
if (npcDialog != null)
|
||||
{
|
||||
String npcText = Text.sanitizeMultilineText(npcDialog.getText());
|
||||
Matcher matcher = AWARDED_PATTERN.matcher(npcText);
|
||||
|
||||
if (matcher.find())
|
||||
{
|
||||
int newPoints = Integer.parseInt(matcher.group(1));
|
||||
|
||||
if (commendationPoints != null)
|
||||
{
|
||||
newPoints += commendationPoints;
|
||||
}
|
||||
|
||||
setCommendationPoints(newPoints);
|
||||
log.debug("PEST CONTROL [POINTS REWARDED] UPDATE: {}", commendationPoints);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get points from dialog after purchase
|
||||
Widget pestControlDialog = client.getWidget(WidgetInfo.PEST_CONTROL_DIALOG_TEXT);
|
||||
if (pestControlDialog != null)
|
||||
{
|
||||
String pestControlDialogText = Text.sanitizeMultilineText(pestControlDialog.getText());
|
||||
Matcher matcher = PURCHASE_PATTERN.matcher(pestControlDialogText);
|
||||
|
||||
if (matcher.find())
|
||||
{
|
||||
setCommendationPoints(Integer.parseInt(matcher.group(1)));
|
||||
log.debug("PEST CONTROL [DIALOG] POINTS UPDATE: {}", commendationPoints);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get points from exchange window
|
||||
Widget exchangeWindowPointsWidget = client.getWidget(WidgetInfo.PEST_CONTROL_EXCHANGE_WINDOW_POINTS);
|
||||
if (exchangeWindowPointsWidget != null)
|
||||
{
|
||||
String pointsString = exchangeWindowPointsWidget.getText();
|
||||
|
||||
Matcher matcher = EXCHANGE_WINDOW_POINTS_PATTERN.matcher(pointsString);
|
||||
if (matcher.lookingAt())
|
||||
{
|
||||
setCommendationPoints(Integer.parseInt(matcher.group(1)));
|
||||
log.debug("PEST CONTROL [EXCHANGE WINDOW] POINTS UPDATE: {}", commendationPoints);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get points in boat
|
||||
// NOTE: The boat info widget is still active right after the game
|
||||
// We should therefor only check for point updates if there are no dialogs
|
||||
Widget boatPointsWidget = client.getWidget(WidgetInfo.PEST_CONTROL_BOAT_INFO_POINTS);
|
||||
if (boatPointsWidget != null && npcDialog == null && pestControlDialog == null)
|
||||
{
|
||||
String pointsString = boatPointsWidget.getText();
|
||||
Matcher matcher = BOAT_POINTS_PATTERN.matcher(pointsString);
|
||||
|
||||
if (matcher.lookingAt())
|
||||
{
|
||||
log.debug(matcher.toString());
|
||||
log.debug("MATCHER GROUP 1: {}", matcher.group(1));
|
||||
setCommendationPoints(Integer.parseInt(matcher.group(1)));
|
||||
log.debug("PEST CONTROL [BOAT] POINTS UPDATE: {}", commendationPoints);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCommendationPoints(int newPoints)
|
||||
{
|
||||
if (userConfigKey == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (commendationPoints == null || commendationPoints != newPoints)
|
||||
{
|
||||
commendationPoints = newPoints;
|
||||
|
||||
configManager.setConfiguration(
|
||||
"pestcontrol",
|
||||
"points." + userConfigKey,
|
||||
String.valueOf(commendationPoints)
|
||||
);
|
||||
}
|
||||
|
||||
handlePointsInfoboxCounter();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick gameTickEvent)
|
||||
{
|
||||
// Check for widgets on main island
|
||||
if (game == null && isOnPestControlMainIsland())
|
||||
{
|
||||
// This must be synchronized for some reason
|
||||
synchronized (this)
|
||||
{
|
||||
if (checkForPointWidgets)
|
||||
{
|
||||
checkForPointWidgets = false;
|
||||
getPointsFromWidgets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the points of the user
|
||||
if (userConfigKey == null)
|
||||
{
|
||||
String username = client.getUsername();
|
||||
|
||||
if (username == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
userConfigKey = String.valueOf(username.hashCode());
|
||||
|
||||
log.debug("USER CONFIG SCOPE: {}", userConfigKey);
|
||||
|
||||
if (loadLocalUserPoints())
|
||||
{
|
||||
handlePointsInfoboxCounter();
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the game has started
|
||||
if (game == null && isInPestControlInstance())
|
||||
{
|
||||
log.debug("Pest control game has started");
|
||||
game = new Game(client, this);
|
||||
pointsRewarded = false;
|
||||
}
|
||||
|
||||
// Check if we are in a game
|
||||
if (game == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we left the game
|
||||
if (!isInPestControlInstance())
|
||||
{
|
||||
if (game != null)
|
||||
{
|
||||
log.debug("Pest control game has ended");
|
||||
game = null;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
game.onGameTick(gameTickEvent);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage chatMessage)
|
||||
{
|
||||
if (overlay.getGame() != null && chatMessage.getType() == ChatMessageType.GAMEMESSAGE)
|
||||
if (game != null && chatMessage.getType() == ChatMessageType.GAMEMESSAGE)
|
||||
{
|
||||
Matcher matcher = SHIELD_DROP.matcher(chatMessage.getMessage());
|
||||
Matcher matcher = SHIELD_DROP_PATTERN.matcher(chatMessage.getMessage());
|
||||
if (matcher.lookingAt())
|
||||
{
|
||||
overlay.getGame().fall(matcher.group(1));
|
||||
game.lowerPortalShield(matcher.group(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
public void onWidgetLoaded(WidgetLoaded event)
|
||||
{
|
||||
final NPC npc = event.getNpc();
|
||||
if (SPINNER_IDS.contains(npc.getId()))
|
||||
if (game != null)
|
||||
{
|
||||
spinners.add(npc);
|
||||
log.debug(event.toString());
|
||||
}
|
||||
|
||||
if (isOnPestControlMainIsland() && game == null)
|
||||
{
|
||||
checkForPointWidgets = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void unlistTileObject(TileObject tileObject)
|
||||
{
|
||||
int tileObjectId = tileObject.getId();
|
||||
|
||||
if (PestControlRepairObject.isRepairableBarricadeId(tileObjectId) ||
|
||||
PestControlRepairObject.isRepairableGateId(tileObjectId))
|
||||
{
|
||||
highlightedRepairList.remove(tileObject);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (tileObjectId)
|
||||
{
|
||||
case NOVICE_GANGPLANK:
|
||||
{
|
||||
noviceGangplankTile = null;
|
||||
break;
|
||||
}
|
||||
case INTERMEDIATE_GANGPLANK:
|
||||
{
|
||||
intermediateGangplankTile = null;
|
||||
break;
|
||||
}
|
||||
case VETERAN_GANGPLANK:
|
||||
{
|
||||
veteranGangplankTile = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTileObject(Tile tile, TileObject tileObject)
|
||||
{
|
||||
int tileObjectId = tileObject.getId();
|
||||
|
||||
if (PestControlRepairObject.isRepairableBarricadeId(tileObjectId) ||
|
||||
PestControlRepairObject.isRepairableGateId(tileObjectId))
|
||||
{
|
||||
highlightedRepairList.add(tileObject);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (tileObjectId)
|
||||
{
|
||||
case NOVICE_GANGPLANK:
|
||||
{
|
||||
noviceGangplankTile = tile;
|
||||
break;
|
||||
}
|
||||
case INTERMEDIATE_GANGPLANK:
|
||||
{
|
||||
intermediateGangplankTile = tile;
|
||||
break;
|
||||
}
|
||||
case VETERAN_GANGPLANK:
|
||||
{
|
||||
veteranGangplankTile = tile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcDespawned(NpcDespawned event)
|
||||
public void onGameObjectSpawned(GameObjectSpawned event)
|
||||
{
|
||||
spinners.remove(event.getNpc());
|
||||
handleTileObject(event.getTile(), event.getGameObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectChanged(GameObjectChanged event)
|
||||
{
|
||||
unlistTileObject(event.getPrevious());
|
||||
handleTileObject(event.getTile(), event.getGameObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectDespawned(GameObjectDespawned event)
|
||||
{
|
||||
unlistTileObject(event.getGameObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGroundObjectSpawned(GroundObjectSpawned event)
|
||||
{
|
||||
handleTileObject(event.getTile(), event.getGroundObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGroundObjectChanged(GroundObjectChanged event)
|
||||
{
|
||||
unlistTileObject(event.getPrevious());
|
||||
handleTileObject(event.getTile(), event.getGroundObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGroundObjectDespawned(GroundObjectDespawned event)
|
||||
{
|
||||
unlistTileObject(event.getGroundObject());
|
||||
}
|
||||
|
||||
public boolean isInPestControlInstance()
|
||||
{
|
||||
return client.getWidget(WidgetInfo.PEST_CONTROL_BLUE_SHIELD) != null;
|
||||
}
|
||||
|
||||
public boolean isOnPestControlMainIsland()
|
||||
{
|
||||
return client.getLocalPlayer().getWorldLocation().getRegionID() == 10537;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ObjectID;
|
||||
|
||||
@Getter
|
||||
public class PestControlRepairObject
|
||||
{
|
||||
@Getter
|
||||
private static final Set<Integer> repairableBarricades = ImmutableSet.of(
|
||||
//ObjectID.BARRICADE_14224,
|
||||
ObjectID.BARRICADE_14227,
|
||||
ObjectID.BARRICADE_14228,
|
||||
ObjectID.BARRICADE_14229,
|
||||
ObjectID.BARRICADE_14230,
|
||||
ObjectID.BARRICADE_14231,
|
||||
ObjectID.BARRICADE_14232
|
||||
);
|
||||
|
||||
@Getter
|
||||
private static final Set<Integer> repairableGates = ImmutableSet.of(
|
||||
ObjectID.GATE_14238,
|
||||
ObjectID.GATE_14239,
|
||||
ObjectID.GATE_14240,
|
||||
ObjectID.GATE_14241,
|
||||
ObjectID.GATE_14242,
|
||||
ObjectID.GATE_14243,
|
||||
ObjectID.GATE_14244,
|
||||
ObjectID.GATE_14245,
|
||||
ObjectID.GATE_14246,
|
||||
ObjectID.GATE_14247,
|
||||
ObjectID.GATE_14248
|
||||
);
|
||||
|
||||
public static boolean isRepairableBarricadeId(int objectId)
|
||||
{
|
||||
return repairableBarricades.contains(objectId);
|
||||
}
|
||||
|
||||
public static boolean isRepairableGateId(int objectId)
|
||||
{
|
||||
return repairableGates.contains(objectId);
|
||||
}
|
||||
|
||||
public static boolean isRepairableId(int objectId)
|
||||
{
|
||||
return isRepairableBarricadeId(objectId) || isRepairableGateId(objectId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.client.ui.overlay.infobox.Counter;
|
||||
|
||||
public class PointsInfoboxCounter extends Counter
|
||||
{
|
||||
private final PestControlPlugin plugin;
|
||||
|
||||
PointsInfoboxCounter(BufferedImage image, PestControlPlugin plugin, int count)
|
||||
{
|
||||
super(image, plugin, count);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -23,22 +24,39 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.pestcontrol;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
enum Portal
|
||||
@Setter
|
||||
class Portal
|
||||
{
|
||||
PURPLE(WidgetInfo.PEST_CONTROL_PURPLE_SHIELD, WidgetInfo.PEST_CONTROL_PURPLE_HEALTH, WidgetInfo.PEST_CONTROL_PURPLE_ICON),
|
||||
BLUE(WidgetInfo.PEST_CONTROL_BLUE_SHIELD, WidgetInfo.PEST_CONTROL_BLUE_HEALTH, WidgetInfo.PEST_CONTROL_BLUE_ICON),
|
||||
YELLOW(WidgetInfo.PEST_CONTROL_YELLOW_SHIELD, WidgetInfo.PEST_CONTROL_YELLOW_HEALTH, WidgetInfo.PEST_CONTROL_YELLOW_ICON),
|
||||
RED(WidgetInfo.PEST_CONTROL_RED_SHIELD, WidgetInfo.PEST_CONTROL_RED_HEALTH, WidgetInfo.PEST_CONTROL_RED_ICON);
|
||||
private PortalColor color;
|
||||
private WidgetPortal widget;
|
||||
private WorldPoint location;
|
||||
|
||||
private final WidgetInfo shield;
|
||||
private final WidgetInfo hitpoints;
|
||||
private final WidgetInfo icon;
|
||||
private PortalState portalState = PortalState.SHIELDED;
|
||||
|
||||
public Portal(PortalColor color, WidgetPortal widget)
|
||||
{
|
||||
this.color = color;
|
||||
this.widget = widget;
|
||||
}
|
||||
|
||||
public boolean isShielded()
|
||||
{
|
||||
return portalState == PortalState.SHIELDED;
|
||||
}
|
||||
|
||||
public boolean isDead()
|
||||
{
|
||||
return portalState == PortalState.DEAD;
|
||||
}
|
||||
|
||||
public boolean isActive()
|
||||
{
|
||||
return (!isShielded() && !isDead());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -25,15 +25,12 @@
|
||||
package net.runelite.client.plugins.pestcontrol;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
class PortalContext
|
||||
public enum PortalColor
|
||||
{
|
||||
private final Portal portal;
|
||||
private boolean isShielded = true;
|
||||
private boolean isDead;
|
||||
BLUE,
|
||||
PURPLE,
|
||||
YELLOW,
|
||||
RED
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,12 +25,12 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.pestcontrol;
|
||||
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.BLUE;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.PURPLE;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.RED;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.YELLOW;
|
||||
import static net.runelite.client.plugins.pestcontrol.PortalColor.BLUE;
|
||||
import static net.runelite.client.plugins.pestcontrol.PortalColor.PURPLE;
|
||||
import static net.runelite.client.plugins.pestcontrol.PortalColor.RED;
|
||||
import static net.runelite.client.plugins.pestcontrol.PortalColor.YELLOW;
|
||||
|
||||
enum Rotation
|
||||
enum PortalRotation
|
||||
{
|
||||
PBYR(PURPLE, BLUE, YELLOW, RED),
|
||||
PYBR(PURPLE, YELLOW, BLUE, RED),
|
||||
@@ -38,23 +39,23 @@ enum Rotation
|
||||
YRPB(YELLOW, RED, PURPLE, BLUE),
|
||||
YPRB(YELLOW, PURPLE, RED, BLUE);
|
||||
|
||||
private final Portal[] portals;
|
||||
private final PortalColor[] portals;
|
||||
|
||||
Rotation(Portal first, Portal second, Portal third, Portal fourth)
|
||||
PortalRotation(PortalColor first, PortalColor second, PortalColor third, PortalColor fourth)
|
||||
{
|
||||
portals = new Portal[]
|
||||
{
|
||||
first, second, third, fourth
|
||||
};
|
||||
portals = new PortalColor[]
|
||||
{
|
||||
first, second, third, fourth
|
||||
};
|
||||
}
|
||||
|
||||
public Portal getPortal(int index)
|
||||
public Portal getPortal(Game game, int index)
|
||||
{
|
||||
if (index < 0 || index >= portals.length)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return portals[index];
|
||||
return game.getPortal(portals[index]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
public enum PortalState
|
||||
{
|
||||
ACTIVE,
|
||||
SHIELDED,
|
||||
DEAD
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.SkillIconManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
@Slf4j
|
||||
public class PortalWeaknessOverlay extends Overlay
|
||||
{
|
||||
private int zOffset = 100;
|
||||
|
||||
private final PestControlConfig config;
|
||||
private final PestControlPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
private BufferedImage magicImage;
|
||||
private BufferedImage rangedImage;
|
||||
private BufferedImage stabImage;
|
||||
private BufferedImage slashImage;
|
||||
private BufferedImage crushImage;
|
||||
|
||||
@Inject
|
||||
PortalWeaknessOverlay(
|
||||
PestControlConfig config,
|
||||
PestControlPlugin plugin,
|
||||
Client client,
|
||||
ItemManager itemManager,
|
||||
SkillIconManager skillIconManager
|
||||
)
|
||||
{
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
|
||||
this.magicImage = skillIconManager.getSkillImage(Skill.MAGIC);
|
||||
this.rangedImage = skillIconManager.getSkillImage(Skill.RANGED);
|
||||
|
||||
this.stabImage = itemManager.getImage(ItemID.WHITE_DAGGER);
|
||||
this.slashImage = itemManager.getImage(ItemID.WHITE_SCIMITAR);
|
||||
this.crushImage = itemManager.getImage(ItemID.WHITE_WARHAMMER);
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.UNDER_WIDGETS);
|
||||
}
|
||||
|
||||
private Point getPortalPoint(Portal portal)
|
||||
{
|
||||
WorldPoint portalLocation = portal.getLocation();
|
||||
LocalPoint localLocation = LocalPoint.fromWorld(client, portalLocation);
|
||||
|
||||
if (localLocation == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// We can use any image here as it's only needed to calculate the position
|
||||
Point imageLocation = Perspective.getCanvasImageLocation(client, localLocation, magicImage, zOffset);
|
||||
|
||||
if (imageLocation != null)
|
||||
{
|
||||
return imageLocation;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderPortalWeakness(Graphics2D graphics, Portal portal, BufferedImage image)
|
||||
{
|
||||
Point portalPoint = getPortalPoint(portal);
|
||||
|
||||
if (portalPoint != null)
|
||||
{
|
||||
Composite originalComposite = graphics.getComposite();
|
||||
Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
|
||||
graphics.setComposite(translucentComposite);
|
||||
|
||||
OverlayUtil.renderImageLocation(graphics, portalPoint, image);
|
||||
|
||||
graphics.setComposite(originalComposite);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderDoublePortalWeakness(
|
||||
Graphics2D graphics,
|
||||
Portal portal,
|
||||
BufferedImage imageLeft,
|
||||
BufferedImage imageRight
|
||||
)
|
||||
{
|
||||
Point portalPoint = getPortalPoint(portal);
|
||||
|
||||
if (portalPoint != null)
|
||||
{
|
||||
Point portalLeft = new Point(
|
||||
portalPoint.getX() - (imageLeft.getWidth() / 2) - 5,
|
||||
portalPoint.getY()
|
||||
);
|
||||
|
||||
Point portalRight = new Point(
|
||||
portalPoint.getX() + (imageRight.getWidth() / 2) + 5,
|
||||
portalPoint.getY()
|
||||
);
|
||||
|
||||
Composite originalComposite = graphics.getComposite();
|
||||
Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f);
|
||||
graphics.setComposite(translucentComposite);
|
||||
|
||||
OverlayUtil.renderImageLocation(graphics, portalLeft, imageLeft);
|
||||
OverlayUtil.renderImageLocation(graphics, portalPoint, imageRight);
|
||||
|
||||
graphics.setComposite(originalComposite);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
Game game = plugin.getGame();
|
||||
|
||||
if (game == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Portal portal : game.getPortals())
|
||||
{
|
||||
if (!portal.isDead())
|
||||
{
|
||||
switch (portal.getColor())
|
||||
{
|
||||
case BLUE:
|
||||
{
|
||||
renderPortalWeakness(graphics, portal, magicImage);
|
||||
break;
|
||||
}
|
||||
case YELLOW:
|
||||
{
|
||||
renderDoublePortalWeakness(graphics, portal, stabImage, slashImage);
|
||||
break;
|
||||
}
|
||||
case RED:
|
||||
{
|
||||
renderPortalWeakness(graphics, portal, crushImage);
|
||||
break;
|
||||
}
|
||||
case PURPLE:
|
||||
{
|
||||
renderPortalWeakness(graphics, portal, rangedImage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Area;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Constants;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GroundObject;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Scene;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.WallObject;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
|
||||
public class RepairOverlay extends Overlay
|
||||
{
|
||||
private final PestControlConfig config;
|
||||
private final PestControlPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
private static final int MAX_DISTANCE = 2400;
|
||||
|
||||
@Inject
|
||||
RepairOverlay(PestControlConfig config, PestControlPlugin plugin, Client client)
|
||||
{
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (plugin.getGame() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Point mousePosition = client.getMouseCanvasPosition();
|
||||
Scene scene = client.getScene();
|
||||
Color color = config.repairableColor();
|
||||
Tile[][][] tiles = scene.getTiles();
|
||||
int z = client.getPlane();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Player player = client.getLocalPlayer();
|
||||
if (player == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Render GameObjects
|
||||
GameObject[] gameObjects = tile.getGameObjects();
|
||||
if (gameObjects != null)
|
||||
{
|
||||
for (GameObject gameObject : gameObjects)
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PestControlRepairObject.isRepairableId(gameObject.getId()))
|
||||
{
|
||||
|
||||
if (player.getLocalLocation().distanceTo(gameObject.getLocalLocation()) <= MAX_DISTANCE)
|
||||
{
|
||||
renderObjectOverlay(graphics, gameObject.getClickbox(), color, mousePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render GameObject
|
||||
GroundObject groundObject = tile.getGroundObject();
|
||||
if (groundObject != null)
|
||||
{
|
||||
if (groundObject == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PestControlRepairObject.isRepairableId(groundObject.getId()))
|
||||
{
|
||||
|
||||
if (player.getLocalLocation().distanceTo(groundObject.getLocalLocation()) <= MAX_DISTANCE)
|
||||
{
|
||||
renderObjectOverlay(graphics, groundObject.getClickbox(), color, mousePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render WallObject
|
||||
WallObject wallObject = tile.getWallObject();
|
||||
if (wallObject != null)
|
||||
{
|
||||
if (wallObject == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PestControlRepairObject.isRepairableId(wallObject.getId()))
|
||||
{
|
||||
|
||||
if (player.getLocalLocation().distanceTo(wallObject.getLocalLocation()) <= MAX_DISTANCE)
|
||||
{
|
||||
renderObjectOverlay(graphics, wallObject.getClickbox(), color, mousePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*if(plugin.getGame() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Point mousePosition = client.getMouseCanvasPosition();
|
||||
|
||||
List<TileObject> repairList = plugin.getHighlightedRepairList();
|
||||
|
||||
for(TileObject tileObject: repairList)
|
||||
{
|
||||
//tileObject.getWorldLocation().distanceTo(client.getLocalPlayer().getWorldLocation());
|
||||
|
||||
Polygon polygon = tileObject.getCanvasTilePoly();
|
||||
|
||||
if(polygon != null)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.drawPolygon(polygon);
|
||||
graphics.setColor(setColorAlpha(color, 40));
|
||||
graphics.fill(polygon);
|
||||
|
||||
if(polygon.contains(mousePosition.getX(), mousePosition.getY()))
|
||||
{
|
||||
graphics.setColor(setColorAlpha(color, 65));
|
||||
graphics.fill(polygon);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderObjectOverlay(Graphics2D graphics, Area area, Color color, Point mousePosition)
|
||||
{
|
||||
if (area == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
graphics.setColor(color);
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.draw(area);
|
||||
graphics.setColor(setColorAlpha(color, 50));
|
||||
graphics.fill(area);
|
||||
|
||||
if (area.contains(mousePosition.getX(), mousePosition.getY()))
|
||||
{
|
||||
graphics.setColor(setColorAlpha(color, 60));
|
||||
graphics.fill(area);
|
||||
}
|
||||
}
|
||||
|
||||
private Color setColorAlpha(Color color, int alpha)
|
||||
{
|
||||
return new Color(
|
||||
color.getRed(),
|
||||
color.getGreen(),
|
||||
color.getBlue(),
|
||||
alpha
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.time.Duration;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
public class TimerOverlay extends Overlay
|
||||
{
|
||||
private final PestControlConfig config;
|
||||
private final PestControlPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
TimerOverlay(PestControlConfig config, PestControlPlugin plugin, Client client)
|
||||
{
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (plugin.getGame() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Widget timeWidget = client.getWidget(WidgetInfo.PEST_CONTROL_INFO_TIME);
|
||||
|
||||
if (timeWidget == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int x = timeWidget.getCanvasLocation().getX() + 38;
|
||||
int y = timeWidget.getCanvasLocation().getY() + 11;
|
||||
|
||||
Duration timeTillNextPortal = plugin.getGame().getTimeTillNextPortal();
|
||||
|
||||
if (timeTillNextPortal != null)
|
||||
{
|
||||
String firstOrNext = (plugin.getGame().getShieldsDropped() == 0) ? "first" : "next";
|
||||
String string = String.format("- %s portal: %ds", firstOrNext, timeTillNextPortal.getSeconds());
|
||||
|
||||
OverlayUtil.renderTextLocation(graphics, new Point(x, y), string, new Color(204, 204, 204));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Kronos <https://github.com/KronosDesign>
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,151 +32,107 @@ import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.BLUE;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.PURPLE;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.RED;
|
||||
import static net.runelite.client.plugins.pestcontrol.Portal.YELLOW;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
@Slf4j
|
||||
public class PestControlOverlay extends Overlay
|
||||
public class WidgetOverlay extends Overlay
|
||||
{
|
||||
private final PestControlPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
// Pest control game
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Game game;
|
||||
private final PestControlPlugin plugin;
|
||||
|
||||
@Inject
|
||||
public PestControlOverlay(PestControlPlugin plugin, Client client)
|
||||
public WidgetOverlay(Client client, PestControlPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
|
||||
public Integer getPortalHitpoints(PortalColor color)
|
||||
{
|
||||
if (plugin.getGame() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
WidgetInfo healthWidgetInfo = null;
|
||||
|
||||
switch (color)
|
||||
{
|
||||
case RED:
|
||||
{
|
||||
healthWidgetInfo = WidgetPortal.RED.getHitpoints();
|
||||
break;
|
||||
}
|
||||
case BLUE:
|
||||
{
|
||||
healthWidgetInfo = WidgetPortal.BLUE.getHitpoints();
|
||||
break;
|
||||
}
|
||||
case PURPLE:
|
||||
{
|
||||
healthWidgetInfo = WidgetPortal.PURPLE.getHitpoints();
|
||||
break;
|
||||
}
|
||||
case YELLOW:
|
||||
{
|
||||
healthWidgetInfo = WidgetPortal.YELLOW.getHitpoints();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (healthWidgetInfo == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Widget healthWidget = client.getWidget(healthWidgetInfo);
|
||||
|
||||
if (healthWidget == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return Integer.parseInt(healthWidget.getText().trim());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
// See if we are in a game or not
|
||||
if (client.getWidget(WidgetInfo.PEST_CONTROL_BLUE_SHIELD) == null)
|
||||
if (plugin.getGame() == null)
|
||||
{
|
||||
if (game != null)
|
||||
{
|
||||
log.debug("Pest control game has ended");
|
||||
game = null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (game == null)
|
||||
{
|
||||
log.debug("Pest control game has started");
|
||||
game = new Game();
|
||||
}
|
||||
|
||||
renderSpinners(graphics);
|
||||
renderPortalWidgets(graphics);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderSpinners(Graphics2D graphics)
|
||||
{
|
||||
for (NPC npc : plugin.getSpinners())
|
||||
{
|
||||
OverlayUtil.renderActorOverlay(graphics, npc, npc.getName(), Color.CYAN);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPortalWidgets(Graphics2D graphics)
|
||||
{
|
||||
PortalContext purple = game.getPurple();
|
||||
PortalContext blue = game.getBlue();
|
||||
PortalContext yellow = game.getYellow();
|
||||
PortalContext red = game.getRed();
|
||||
|
||||
Widget purpleHealth = client.getWidget(PURPLE.getHitpoints());
|
||||
Widget blueHealth = client.getWidget(BLUE.getHitpoints());
|
||||
Widget yellowHealth = client.getWidget(YELLOW.getHitpoints());
|
||||
Widget redHealth = client.getWidget(RED.getHitpoints());
|
||||
|
||||
// Check for dead portals
|
||||
if (isZero(purpleHealth))
|
||||
{
|
||||
game.die(purple);
|
||||
}
|
||||
if (isZero(blueHealth))
|
||||
{
|
||||
game.die(blue);
|
||||
}
|
||||
if (isZero(yellowHealth))
|
||||
{
|
||||
game.die(yellow);
|
||||
}
|
||||
if (isZero(redHealth))
|
||||
{
|
||||
game.die(red);
|
||||
}
|
||||
|
||||
// display "ATK" overlay on recorded portals without shields
|
||||
renderAttack(graphics, purple);
|
||||
renderAttack(graphics, blue);
|
||||
renderAttack(graphics, yellow);
|
||||
renderAttack(graphics, red);
|
||||
|
||||
// display "NEXT" overlay on predicted portals
|
||||
for (Portal portal : game.getNextPortals())
|
||||
for (Portal portal : plugin.getGame().getNextPortals())
|
||||
{
|
||||
renderWidgetOverlay(graphics, portal, "NEXT", Color.ORANGE);
|
||||
}
|
||||
|
||||
renderProgressWidget(graphics);
|
||||
}
|
||||
|
||||
private void renderProgressWidget(Graphics2D graphics)
|
||||
{
|
||||
Widget bar = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_BAR).getChild(0);
|
||||
Rectangle2D bounds = bar.getBounds().getBounds2D();
|
||||
|
||||
Widget prgs = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_PROGRESS).getChild(0);
|
||||
int perc = (int) ((prgs.getBounds().getWidth() / bounds.getWidth()) * 100);
|
||||
|
||||
Color color = Color.GREEN;
|
||||
if (perc < 25)
|
||||
for (Portal portal : plugin.getGame().getActivePortals())
|
||||
{
|
||||
color = Color.RED;
|
||||
renderWidgetOverlay(graphics, portal, "ATT", Color.RED);
|
||||
}
|
||||
|
||||
String text = String.valueOf(perc) + "%";
|
||||
renderProgressWidget(graphics);
|
||||
|
||||
FontMetrics fm = graphics.getFontMetrics();
|
||||
Rectangle2D textBounds = fm.getStringBounds(text, graphics);
|
||||
int x = (int) (bounds.getX() - textBounds.getWidth());
|
||||
int y = (int) (bounds.getY() + fm.getHeight() - 2);
|
||||
|
||||
graphics.setColor(Color.BLACK);
|
||||
graphics.drawString(text, x + 1, y + 1);
|
||||
graphics.setColor(color);
|
||||
graphics.drawString(text, x, y);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderWidgetOverlay(Graphics2D graphics, Portal portal, String text, Color color)
|
||||
{
|
||||
Widget shield = client.getWidget(portal.getShield());
|
||||
Widget icon = client.getWidget(portal.getIcon());
|
||||
Widget hp = client.getWidget(portal.getHitpoints());
|
||||
Widget shield = client.getWidget(portal.getWidget().getShield());
|
||||
Widget icon = client.getWidget(portal.getWidget().getIcon());
|
||||
Widget hp = client.getWidget(portal.getWidget().getHitpoints());
|
||||
|
||||
Widget bar = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_BAR).getChild(0);
|
||||
|
||||
@@ -199,6 +156,45 @@ public class PestControlOverlay extends Overlay
|
||||
graphics.drawString(text, x, y + 4);
|
||||
}
|
||||
|
||||
private void renderProgressWidget(Graphics2D graphics)
|
||||
{
|
||||
String text;
|
||||
int percentage;
|
||||
|
||||
Widget bar = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_BAR).getChild(0);
|
||||
Rectangle2D bounds = bar.getBounds().getBounds2D();
|
||||
|
||||
Widget prgs = client.getWidget(WidgetInfo.PEST_CONTROL_ACTIVITY_PROGRESS).getChild(0);
|
||||
|
||||
// At 0% the inner widget changes and your progress will not increase anymore
|
||||
if ((int) (prgs.getBounds().getX()) - bounds.getX() != 2)
|
||||
{
|
||||
percentage = 0;
|
||||
text = "FAILED";
|
||||
}
|
||||
else
|
||||
{
|
||||
percentage = (int) ((prgs.getBounds().getWidth() / bounds.getWidth()) * 100);
|
||||
text = String.valueOf(percentage) + "%";
|
||||
}
|
||||
|
||||
Color color = Color.GREEN;
|
||||
if (percentage < 25)
|
||||
{
|
||||
color = Color.RED;
|
||||
}
|
||||
|
||||
FontMetrics fm = graphics.getFontMetrics();
|
||||
Rectangle2D textBounds = fm.getStringBounds(text, graphics);
|
||||
int x = (int) (bounds.getX() - textBounds.getWidth() - 4);
|
||||
int y = (int) (bounds.getY() + fm.getHeight() - 2);
|
||||
|
||||
graphics.setColor(Color.BLACK);
|
||||
graphics.drawString(text, x + 1, y + 1);
|
||||
graphics.setColor(color);
|
||||
graphics.drawString(text, x, y);
|
||||
}
|
||||
|
||||
private static Rectangle2D union(Rectangle2D src1, Rectangle2D src2)
|
||||
{
|
||||
double x1 = Math.min(src1.getMinX(), src2.getMinX());
|
||||
@@ -211,19 +207,4 @@ public class PestControlOverlay extends Overlay
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void renderAttack(Graphics2D graphics, PortalContext portal)
|
||||
{
|
||||
if (portal.isShielded() || portal.isDead())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
renderWidgetOverlay(graphics, portal.getPortal(), "ATK", Color.RED);
|
||||
}
|
||||
|
||||
private static boolean isZero(Widget widget)
|
||||
{
|
||||
return widget.getText().trim().equals("0");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.pestcontrol;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@ToString
|
||||
enum WidgetPortal
|
||||
{
|
||||
PURPLE(WidgetInfo.PEST_CONTROL_PURPLE_SHIELD, WidgetInfo.PEST_CONTROL_PURPLE_HEALTH, WidgetInfo.PEST_CONTROL_PURPLE_ICON),
|
||||
BLUE(WidgetInfo.PEST_CONTROL_BLUE_SHIELD, WidgetInfo.PEST_CONTROL_BLUE_HEALTH, WidgetInfo.PEST_CONTROL_BLUE_ICON),
|
||||
YELLOW(WidgetInfo.PEST_CONTROL_YELLOW_SHIELD, WidgetInfo.PEST_CONTROL_YELLOW_HEALTH, WidgetInfo.PEST_CONTROL_YELLOW_ICON),
|
||||
RED(WidgetInfo.PEST_CONTROL_RED_SHIELD, WidgetInfo.PEST_CONTROL_RED_HEALTH, WidgetInfo.PEST_CONTROL_RED_ICON);
|
||||
|
||||
private final WidgetInfo shield;
|
||||
private final WidgetInfo hitpoints;
|
||||
private final WidgetInfo icon;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum HighlightPortalOption
|
||||
{
|
||||
OFF("Off"),
|
||||
ACTIVE("Active"),
|
||||
SHIELDED("Shielded"),
|
||||
ALL("All");
|
||||
|
||||
private final String option;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return option;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.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.pestcontrol.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum NpcHighlightStyle
|
||||
{
|
||||
OFF("Off"),
|
||||
TILE("Tile"),
|
||||
HULL("Hull"),
|
||||
BOTH("Hull + Tile");
|
||||
|
||||
private final String style;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return style;
|
||||
}
|
||||
}
|
||||
@@ -59,6 +59,9 @@ import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.events.WidgetHiddenChanged;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.chat.ChatColorType;
|
||||
import net.runelite.client.chat.ChatMessageBuilder;
|
||||
@@ -126,6 +129,9 @@ public class RaidsPlugin extends Plugin
|
||||
@Inject
|
||||
private RaidsOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private RaidsPointsOverlay pointsOverlay;
|
||||
|
||||
@Inject
|
||||
private LayoutSolver layoutSolver;
|
||||
|
||||
@@ -177,6 +183,7 @@ public class RaidsPlugin extends Plugin
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(pointsOverlay);
|
||||
updateLists();
|
||||
clientThread.invokeLater(() -> checkRaidPresence(true));
|
||||
}
|
||||
@@ -185,10 +192,17 @@ public class RaidsPlugin extends Plugin
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(pointsOverlay);
|
||||
infoBoxManager.removeInfoBox(timer);
|
||||
inRaidChambers = false;
|
||||
raid = null;
|
||||
timer = null;
|
||||
|
||||
final Widget widget = client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX);
|
||||
if (widget != null)
|
||||
{
|
||||
widget.setHidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -209,6 +223,22 @@ public class RaidsPlugin extends Plugin
|
||||
clientThread.invokeLater(() -> checkRaidPresence(true));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetHiddenChanged(WidgetHiddenChanged event)
|
||||
{
|
||||
if (!inRaidChambers || event.isHidden())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widget widget = event.getWidget();
|
||||
|
||||
if (widget == client.getWidget(WidgetInfo.RAIDS_POINTS_INFOBOX))
|
||||
{
|
||||
widget.setHidden(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Kamiel
|
||||
* 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.raids;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
|
||||
import net.runelite.api.Varbits;
|
||||
import static net.runelite.client.plugins.raids.RaidsPlugin.POINTS_FORMAT;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
|
||||
public class RaidsPointsOverlay extends Overlay
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private RaidsPlugin plugin;
|
||||
|
||||
private final PanelComponent panel = new PanelComponent();
|
||||
|
||||
private static final NumberFormat UNIQUE_FORMAT = NumberFormat.getPercentInstance(Locale.ENGLISH);
|
||||
static
|
||||
{
|
||||
UNIQUE_FORMAT.setMaximumFractionDigits(2);
|
||||
UNIQUE_FORMAT.setMinimumFractionDigits(2);
|
||||
}
|
||||
|
||||
@Inject
|
||||
private RaidsPointsOverlay(RaidsPlugin plugin)
|
||||
{
|
||||
super(plugin);
|
||||
setPosition(OverlayPosition.TOP_RIGHT);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Raids overlay"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.isInRaidChambers())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int totalPoints = client.getVar(Varbits.TOTAL_POINTS);
|
||||
int personalPoints = client.getVar(Varbits.PERSONAL_POINTS);
|
||||
int partySize = client.getVar(Varbits.RAID_PARTY_SIZE);
|
||||
double uniqueChance = totalPoints / 867500f;
|
||||
|
||||
panel.getChildren().clear();
|
||||
panel.getChildren().add(LineComponent.builder()
|
||||
.left("Total:")
|
||||
.right(POINTS_FORMAT.format(totalPoints))
|
||||
.build());
|
||||
|
||||
panel.getChildren().add(LineComponent.builder()
|
||||
.left(client.getLocalPlayer().getName() + ":")
|
||||
.right(POINTS_FORMAT.format(personalPoints))
|
||||
.build());
|
||||
|
||||
|
||||
if (partySize > 1)
|
||||
{
|
||||
panel.getChildren().add(LineComponent.builder()
|
||||
.left("Party size:")
|
||||
.right(String.valueOf(partySize))
|
||||
.build());
|
||||
}
|
||||
|
||||
panel.getChildren().add(LineComponent.builder()
|
||||
.left("Unique:")
|
||||
.right(UNIQUE_FORMAT.format(uniqueChance))
|
||||
.build());
|
||||
|
||||
if (partySize > 1)
|
||||
{
|
||||
double personalChance = uniqueChance * (personalPoints / totalPoints);
|
||||
|
||||
panel.getChildren().add(LineComponent.builder()
|
||||
.left("Personal:")
|
||||
.right(UNIQUE_FORMAT.format(personalChance))
|
||||
.build());
|
||||
}
|
||||
|
||||
return panel.render(graphics);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 179 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.testing.fieldbinder.Bind;
|
||||
import com.google.inject.testing.fieldbinder.BoundFieldModule;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.plugins.maxhit.calculators.testconfig.MagicMaxHitConfig;
|
||||
import net.runelite.client.plugins.maxhit.calculators.testconfig.MaxHitConfig;
|
||||
import net.runelite.client.plugins.maxhit.calculators.testconfig.MeleeMaxHitConfig;
|
||||
import net.runelite.client.plugins.maxhit.calculators.testconfig.RangeMaxHitConfig;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MaxHitCalculatorTest
|
||||
{
|
||||
@Mock
|
||||
@Bind
|
||||
protected Client client;
|
||||
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void calculate()
|
||||
{
|
||||
testMaxHitConfig(MeleeMaxHitConfig.values());
|
||||
testMaxHitConfig(RangeMaxHitConfig.values());
|
||||
testMaxHitConfig(MagicMaxHitConfig.values());
|
||||
}
|
||||
|
||||
private void testMaxHitConfig(MaxHitConfig[] maxHitConfigs)
|
||||
{
|
||||
for (MaxHitConfig maxHitConfig : maxHitConfigs)
|
||||
{
|
||||
maxHitConfig.test(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators.testconfig;
|
||||
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.client.plugins.maxhit.calculators.MagicMaxHitCalculator;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public enum MagicMaxHitConfig implements MaxHitConfig
|
||||
{
|
||||
|
||||
TRIDENT_SLAYER(new int[] {75, 83, 99}, 0, new Item[]
|
||||
{
|
||||
mockItem(ItemID.SLAYER_HELMET_I),
|
||||
mockItem(ItemID.SARADOMIN_CAPE),
|
||||
mockItem(ItemID.OCCULT_NECKLACE),
|
||||
mockItem(ItemID.TRIDENT_OF_THE_SEAS),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.BROODOO_SHIELD),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_GLOVES),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, new int[] {25, 27, 34}),
|
||||
|
||||
TRIDENT_OF_SEAS(new int[] {75, 83, 99}, 0, new Item[]
|
||||
{
|
||||
mockItem(ItemID.MYSTIC_HAT),
|
||||
mockItem(ItemID.SARADOMIN_CAPE),
|
||||
mockItem(ItemID.AMULET_OF_GLORY),
|
||||
mockItem(ItemID.TRIDENT_OF_THE_SEAS),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.BROODOO_SHIELD),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_GLOVES),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, new int[] {20, 22, 28}),
|
||||
|
||||
TRIDENT_OF_SWAMP(new int[] {75, 83, 99}, 0, new Item[]
|
||||
{
|
||||
mockItem(ItemID.MYSTIC_HAT),
|
||||
mockItem(ItemID.SARADOMIN_CAPE),
|
||||
mockItem(ItemID.AMULET_OF_GLORY),
|
||||
mockItem(ItemID.TRIDENT_OF_THE_SWAMP),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.BROODOO_SHIELD),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_GLOVES),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, new int[] {23, 25, 31}),
|
||||
|
||||
MAGIC_DART(new int[] {75, 83, 99}, 18, new Item[]
|
||||
{
|
||||
mockItem(ItemID.MYSTIC_HAT),
|
||||
mockItem(ItemID.SARADOMIN_CAPE),
|
||||
mockItem(ItemID.AMULET_OF_GLORY),
|
||||
mockItem(ItemID.SLAYERS_STAFF),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.BROODOO_SHIELD),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_GLOVES),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, new int[] {17, 18, 19}),
|
||||
|
||||
|
||||
FIRE_BOLT(75, 8, new Item[]
|
||||
{
|
||||
mockItem(ItemID.SLAYER_HELMET_I),
|
||||
mockItem(ItemID.IMBUED_SARADOMIN_CAPE),
|
||||
mockItem(ItemID.OCCULT_NECKLACE),
|
||||
mockItem(ItemID.STAFF_OF_THE_DEAD),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.TOME_OF_FIRE),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.CHAOS_GAUNTLETS),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, 31),
|
||||
|
||||
|
||||
WIND_BLAST(75, 9, new Item[]
|
||||
{
|
||||
mockItem(ItemID.MYSTIC_HAT),
|
||||
mockItem(ItemID.SARADOMIN_CAPE),
|
||||
mockItem(ItemID.AMULET_OF_GLORY),
|
||||
mockItem(ItemID.STAFF_OF_AIR),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.BROODOO_SHIELD),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_GLOVES),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, 13),
|
||||
|
||||
|
||||
EARTH_WAVE(75, 15, new Item[]
|
||||
{
|
||||
mockItem(ItemID.MYSTIC_HAT),
|
||||
mockItem(ItemID.SARADOMIN_CAPE),
|
||||
mockItem(ItemID.OCCULT_NECKLACE),
|
||||
mockItem(ItemID.STAFF_OF_EARTH),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.TOME_OF_FIRE),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_GLOVES),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, 20),
|
||||
|
||||
FLAMES_OF_ZAMORAK(75, 20, new Item[]
|
||||
{
|
||||
mockItem(ItemID.MYSTIC_HAT),
|
||||
mockItem(ItemID.SARADOMIN_CAPE),
|
||||
mockItem(ItemID.AMULET_OF_GLORY),
|
||||
mockItem(ItemID.STAFF_OF_THE_DEAD),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.BROODOO_SHIELD),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_GLOVES),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, 23),
|
||||
|
||||
SARADOMIN_STRIKE(75, 52, new Item[]
|
||||
{
|
||||
mockItem(ItemID.MYSTIC_HAT),
|
||||
mockItem(ItemID.SARADOMIN_CAPE),
|
||||
mockItem(ItemID.AMULET_OF_GLORY),
|
||||
mockItem(ItemID.STAFF_OF_LIGHT),
|
||||
mockItem(ItemID.MYSTIC_ROBE_TOP),
|
||||
mockItem(ItemID.BROODOO_SHIELD),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_ROBE_BOTTOM),
|
||||
null,
|
||||
mockItem(ItemID.MYSTIC_GLOVES),
|
||||
mockItem(ItemID.WIZARD_BOOTS),
|
||||
mockItem(ItemID.RING_OF_WEALTH)
|
||||
}, 23),
|
||||
|
||||
|
||||
;
|
||||
|
||||
|
||||
private final int[] magicLevels;
|
||||
private final int spellId;
|
||||
private final Item[] equipedItems;
|
||||
private final int[] expectedMaxHits;
|
||||
|
||||
MagicMaxHitConfig(int magicLevel, int spellId, Item[] equipedItems, int expectedMaxHit)
|
||||
{
|
||||
this.magicLevels = new int[] {magicLevel};
|
||||
this.spellId = spellId;
|
||||
this.equipedItems = equipedItems;
|
||||
this.expectedMaxHits = new int[] {expectedMaxHit};
|
||||
}
|
||||
|
||||
MagicMaxHitConfig(int[] magicLevels, int spellId, Item[] equipedItems, int[] expectedMaxHits)
|
||||
{
|
||||
this.magicLevels = magicLevels;
|
||||
this.spellId = spellId;
|
||||
this.equipedItems = equipedItems;
|
||||
this.expectedMaxHits = expectedMaxHits;
|
||||
}
|
||||
|
||||
|
||||
private static Item mockItem(int itemId)
|
||||
{
|
||||
Item item = mock(Item.class);
|
||||
when(item.getId()).thenReturn(itemId);
|
||||
return item;
|
||||
}
|
||||
|
||||
public void test(Client client)
|
||||
{
|
||||
int[] magicLevels = this.magicLevels;
|
||||
for (int i = 0, magicLevelsLength = magicLevels.length; i < magicLevelsLength; i++)
|
||||
{
|
||||
int magicLevel = magicLevels[i];
|
||||
int expectedMaxHit = this.expectedMaxHits[i];
|
||||
|
||||
// Mock equipment container
|
||||
ItemContainer equipmentContainer = mock(ItemContainer.class);
|
||||
when(equipmentContainer.getItems())
|
||||
.thenReturn(this.equipedItems);
|
||||
when(client.getItemContainer(InventoryID.EQUIPMENT)).thenReturn(equipmentContainer);
|
||||
|
||||
// Mock Varbits
|
||||
when(client.getBoostedSkillLevel(Skill.MAGIC)).thenReturn(magicLevel);
|
||||
when(client.getVar(Varbits.AUTO_CAST_SPELL)).thenReturn(this.spellId);
|
||||
|
||||
// Test
|
||||
MagicMaxHitCalculator maxHitCalculator = new MagicMaxHitCalculator(client, this.equipedItems);
|
||||
assertEquals(this.toString(), expectedMaxHit, maxHitCalculator.getMaxHit(), 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators.testconfig;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
|
||||
public interface MaxHitConfig
|
||||
{
|
||||
void test(Client client);
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators.testconfig;
|
||||
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.plugins.maxhit.attackstyle.WeaponType;
|
||||
import net.runelite.client.plugins.maxhit.calculators.MeleeMaxHitCalculator;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public enum MeleeMaxHitConfig implements MaxHitConfig
|
||||
{
|
||||
|
||||
DRAGON_SCIMITAR(new int[] {75, 83, 99}, 66, WeaponType.TYPE_9, 1, new Item[]
|
||||
{
|
||||
mockItem(ItemID.IRON_FULL_HELM),
|
||||
mockItem(ItemID.BLACK_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.DRAGON_SCIMITAR),
|
||||
mockItem(ItemID.IRON_PLATEBODY),
|
||||
mockItem(ItemID.IRON_KITESHIELD),
|
||||
null,
|
||||
mockItem(ItemID.IRON_PLATELEGS),
|
||||
null,
|
||||
mockItem(ItemID.LEATHER_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING)
|
||||
}, new int[] {17, 19, 22}),
|
||||
|
||||
DRAGON_SCIMITAR_DEFENDER(new int[] {75, 83, 99}, 76, WeaponType.TYPE_9, 1, new Item[]
|
||||
{
|
||||
mockItem(ItemID.IRON_FULL_HELM),
|
||||
mockItem(ItemID.BLACK_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.DRAGON_SCIMITAR),
|
||||
mockItem(ItemID.IRON_PLATEBODY),
|
||||
mockItem(ItemID.DRAGON_DEFENDER),
|
||||
null,
|
||||
mockItem(ItemID.IRON_PLATELEGS),
|
||||
null,
|
||||
mockItem(ItemID.LEATHER_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING)
|
||||
}, new int[] {19, 21, 24}),
|
||||
|
||||
DRAGON_SCIMITAR_COMPLETE(new int[] {75, 83, 99}, 108, WeaponType.TYPE_9, 1, new Item[]
|
||||
{
|
||||
mockItem(ItemID.SLAYER_HELMET),
|
||||
mockItem(ItemID.FIRE_CAPE),
|
||||
mockItem(ItemID.AMULET_OF_FURY),
|
||||
mockItem(ItemID.DRAGON_SCIMITAR),
|
||||
mockItem(ItemID.FIGHTER_TORSO),
|
||||
mockItem(ItemID.DRAGON_DEFENDER),
|
||||
null,
|
||||
mockItem(ItemID.IRON_PLATELEGS),
|
||||
null,
|
||||
mockItem(ItemID.BARROWS_GLOVES),
|
||||
mockItem(ItemID.DRAGON_BOOTS),
|
||||
mockItem(ItemID.BERSERKER_RING)
|
||||
}, new int[] {26, 29, 35}),
|
||||
|
||||
OBSIDIAN_SET(new int[] {75, 83, 99}, 61, WeaponType.TYPE_17, 2, new Item[]
|
||||
{
|
||||
mockItem(ItemID.OBSIDIAN_HELMET),
|
||||
mockItem(ItemID.OBSIDIAN_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.TOKTZXILAK),
|
||||
mockItem(ItemID.OBSIDIAN_PLATEBODY),
|
||||
mockItem(ItemID.TOKTZKETXIL),
|
||||
null,
|
||||
mockItem(ItemID.OBSIDIAN_PLATELEGS),
|
||||
null,
|
||||
mockItem(ItemID.LEATHER_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING)
|
||||
}, new int[] {18, 19, 23}),
|
||||
|
||||
DHAROK_SET(new int[] {75, 75, 75, 83, 83, 83, 99, 99, 99}, 105, WeaponType.TYPE_1, 1,
|
||||
new int[][] {{99, 99}, {1, 99}, {32, 75}, {99, 99}, {1, 99}, {32, 75}, {99, 99}, {1, 99}, {32, 75}},
|
||||
new Item[]
|
||||
{
|
||||
mockItem(ItemID.DHAROKS_HELM_100),
|
||||
mockItem(ItemID.BLACK_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.DHAROKS_GREATAXE_100),
|
||||
mockItem(ItemID.DHAROKS_PLATEBODY_100),
|
||||
null,
|
||||
null,
|
||||
mockItem(ItemID.DHAROKS_PLATELEGS_100),
|
||||
null,
|
||||
mockItem(ItemID.LEATHER_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING)
|
||||
}, new int[] {23, 45, 30, 25, 49, 33, 29, 57, 38}),
|
||||
|
||||
VOID_SET(new int[] {75, 83, 99}, 66, WeaponType.TYPE_9, 1, new Item[]
|
||||
{
|
||||
mockItem(ItemID.VOID_MELEE_HELM),
|
||||
mockItem(ItemID.BLACK_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.DRAGON_SCIMITAR),
|
||||
mockItem(ItemID.VOID_KNIGHT_TOP),
|
||||
mockItem(ItemID.IRON_KITESHIELD),
|
||||
null,
|
||||
mockItem(ItemID.VOID_KNIGHT_ROBE),
|
||||
null,
|
||||
mockItem(ItemID.VOID_KNIGHT_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING)
|
||||
}, new int[] {19, 21, 25}),
|
||||
;
|
||||
|
||||
|
||||
private final int[] strengthLevels;
|
||||
private final WeaponType weaponType;
|
||||
private final int attackStyleId;
|
||||
private final Item[] equipedItems;
|
||||
private final int[] expectedMaxHits;
|
||||
private final int[][] hitpoints;
|
||||
private final int meleeEquipmentStrength;
|
||||
|
||||
MeleeMaxHitConfig(int[] strengthLevels, int meleeEquipmentStrength, WeaponType weaponType, int attackStyleId, int[][] hitpoints, Item[] equipedItems, int[] expectedMaxHits)
|
||||
{
|
||||
this.strengthLevels = strengthLevels;
|
||||
this.meleeEquipmentStrength = meleeEquipmentStrength;
|
||||
this.weaponType = weaponType;
|
||||
this.attackStyleId = attackStyleId;
|
||||
this.hitpoints = hitpoints;
|
||||
this.equipedItems = equipedItems;
|
||||
this.expectedMaxHits = expectedMaxHits;
|
||||
}
|
||||
|
||||
MeleeMaxHitConfig(int[] strengthLevels, int meleeEquipmentStrength, WeaponType weaponType, int attackStyleId, Item[] equipedItems, int[] expectedMaxHits)
|
||||
{
|
||||
this.strengthLevels = strengthLevels;
|
||||
this.hitpoints = new int[strengthLevels.length][2];
|
||||
this.meleeEquipmentStrength = meleeEquipmentStrength;
|
||||
this.weaponType = weaponType;
|
||||
this.attackStyleId = attackStyleId;
|
||||
this.equipedItems = equipedItems;
|
||||
this.expectedMaxHits = expectedMaxHits;
|
||||
}
|
||||
|
||||
|
||||
private static Item mockItem(int itemId)
|
||||
{
|
||||
Item item = mock(Item.class);
|
||||
when(item.getId()).thenReturn(itemId);
|
||||
return item;
|
||||
}
|
||||
|
||||
public void test(Client client)
|
||||
{
|
||||
int[] strengthLevels = this.strengthLevels;
|
||||
for (int i = 0, strengthLevelsLength = strengthLevels.length; i < strengthLevelsLength; i++)
|
||||
{
|
||||
int strengthLevel = strengthLevels[i];
|
||||
int[] hitpoints = this.hitpoints[i];
|
||||
int expectedMaxHit = this.expectedMaxHits[i];
|
||||
|
||||
// Mock equipment container
|
||||
ItemContainer equipmentContainer = mock(ItemContainer.class);
|
||||
when(equipmentContainer.getItems())
|
||||
.thenReturn(this.equipedItems);
|
||||
when(client.getItemContainer(InventoryID.EQUIPMENT)).thenReturn(equipmentContainer);
|
||||
|
||||
// Mock equipment strength
|
||||
Widget equipmentWidget = mock(Widget.class);
|
||||
when(client.getWidget(WidgetInfo.EQUIPMENT_MELEE_STRENGTH)).thenReturn(equipmentWidget);
|
||||
when(equipmentWidget.getText()).thenReturn("Melee strength: " + this.meleeEquipmentStrength);
|
||||
|
||||
// Mock Varbits
|
||||
when(client.getVar(Varbits.EQUIPPED_WEAPON_TYPE)).thenReturn(this.weaponType.ordinal());
|
||||
when(client.getVar(VarPlayer.ATTACK_STYLE)).thenReturn(this.attackStyleId);
|
||||
|
||||
// Mock strength
|
||||
when(client.getBoostedSkillLevel(Skill.STRENGTH)).thenReturn(strengthLevel);
|
||||
|
||||
// Mock hitpoints
|
||||
when(client.getBoostedSkillLevel(Skill.HITPOINTS)).thenReturn(hitpoints[0]);
|
||||
when(client.getRealSkillLevel(Skill.HITPOINTS)).thenReturn(hitpoints[1]);
|
||||
|
||||
// Test
|
||||
MeleeMaxHitCalculator maxHitCalculator = new MeleeMaxHitCalculator(client, this.equipedItems);
|
||||
assertEquals(this.toString(), expectedMaxHit, maxHitCalculator.getMaxHit(), 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Bartvollebregt <https://github.com/Bartvollebregt>
|
||||
* 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.maxhit.calculators.testconfig;
|
||||
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.plugins.maxhit.attackstyle.WeaponType;
|
||||
import net.runelite.client.plugins.maxhit.calculators.RangeMaxHitCalculator;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public enum RangeMaxHitConfig implements MaxHitConfig
|
||||
{
|
||||
|
||||
MAGIC_SHORTBOW(new int[] {75, 83, 99}, 49, WeaponType.TYPE_3, 1, new Item[]
|
||||
{
|
||||
mockItem(ItemID.IRON_FULL_HELM),
|
||||
mockItem(ItemID.BLACK_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.MAGIC_SHORTBOW),
|
||||
mockItem(ItemID.IRON_PLATEBODY),
|
||||
null,
|
||||
null,
|
||||
mockItem(ItemID.IRON_PLATELEGS),
|
||||
null,
|
||||
mockItem(ItemID.LEATHER_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING),
|
||||
mockItem(ItemID.RUNE_ARROW)
|
||||
}, new int[] {15, 16, 19}),
|
||||
|
||||
RUNE_CROSSBOW(new int[] {75, 83, 99}, 115, WeaponType.TYPE_5, 0, new Item[]
|
||||
{
|
||||
mockItem(ItemID.IRON_FULL_HELM),
|
||||
mockItem(ItemID.BLACK_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.RUNE_CROSSBOW),
|
||||
mockItem(ItemID.IRON_PLATEBODY),
|
||||
null,
|
||||
null,
|
||||
mockItem(ItemID.IRON_PLATELEGS),
|
||||
null,
|
||||
mockItem(ItemID.LEATHER_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING),
|
||||
mockItem(ItemID.RUNITE_BOLTS)
|
||||
}, new int[] {24, 26, 31}),
|
||||
|
||||
BLOwPIPE(new int[] {75, 83, 99}, 50, WeaponType.TYPE_19, 1, new Item[]
|
||||
{
|
||||
mockItem(ItemID.IRON_FULL_HELM),
|
||||
mockItem(ItemID.BLACK_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.TOXIC_BLOWPIPE),
|
||||
mockItem(ItemID.IRON_PLATEBODY),
|
||||
null,
|
||||
null,
|
||||
mockItem(ItemID.IRON_PLATELEGS),
|
||||
null,
|
||||
mockItem(ItemID.LEATHER_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING)
|
||||
}, new int[] {15, 16, 19}),
|
||||
|
||||
VOID_SET(new int[] {75, 83, 99}, 115, WeaponType.TYPE_5, 1, new Item[]
|
||||
{
|
||||
mockItem(ItemID.VOID_RANGER_HELM),
|
||||
mockItem(ItemID.BLACK_CAPE),
|
||||
mockItem(ItemID.GOLD_NECKLACE),
|
||||
mockItem(ItemID.RUNE_CROSSBOW),
|
||||
mockItem(ItemID.VOID_KNIGHT_TOP),
|
||||
mockItem(ItemID.IRON_KITESHIELD),
|
||||
null,
|
||||
mockItem(ItemID.VOID_KNIGHT_ROBE),
|
||||
null,
|
||||
mockItem(ItemID.VOID_KNIGHT_GLOVES),
|
||||
mockItem(ItemID.LEATHER_BOOTS),
|
||||
mockItem(ItemID.GOLD_RING)
|
||||
}, new int[] {26, 28, 33}),
|
||||
|
||||
;
|
||||
|
||||
private final int[] rangeLevels;
|
||||
private final WeaponType weaponType;
|
||||
private final int attackStyleId;
|
||||
private final Item[] equipedItems;
|
||||
private final int[] expectedMaxHits;
|
||||
private final int ammoEquipmentStrength;
|
||||
|
||||
RangeMaxHitConfig(int[] rangeLevels, int ammoEquipmentStrength, WeaponType weaponType, int attackStyleId, Item[] equipedItems, int[] expectedMaxHits)
|
||||
{
|
||||
this.rangeLevels = rangeLevels;
|
||||
this.ammoEquipmentStrength = ammoEquipmentStrength;
|
||||
this.weaponType = weaponType;
|
||||
this.attackStyleId = attackStyleId;
|
||||
this.equipedItems = equipedItems;
|
||||
this.expectedMaxHits = expectedMaxHits;
|
||||
}
|
||||
|
||||
|
||||
private static Item mockItem(int itemId)
|
||||
{
|
||||
Item item = mock(Item.class);
|
||||
when(item.getId()).thenReturn(itemId);
|
||||
return item;
|
||||
}
|
||||
|
||||
public void test(Client client)
|
||||
{
|
||||
int[] rangeLevels = this.rangeLevels;
|
||||
for (int i = 0, rangeLevelsLength = rangeLevels.length; i < rangeLevelsLength; i++)
|
||||
{
|
||||
int rangeLevel = rangeLevels[i];
|
||||
int expectedMaxHit = this.expectedMaxHits[i];
|
||||
|
||||
// Mock equipment container
|
||||
ItemContainer equipmentContainer = mock(ItemContainer.class);
|
||||
when(equipmentContainer.getItems())
|
||||
.thenReturn(this.equipedItems);
|
||||
when(client.getItemContainer(InventoryID.EQUIPMENT)).thenReturn(equipmentContainer);
|
||||
|
||||
// Mock equipment strength
|
||||
Widget equipmentWidget = mock(Widget.class);
|
||||
when(client.getWidget(WidgetInfo.EQUIPMENT_RANGED_STRENGTH)).thenReturn(equipmentWidget);
|
||||
when(equipmentWidget.getText()).thenReturn("Ranged strength: " + this.ammoEquipmentStrength);
|
||||
|
||||
// Mock Varbits
|
||||
when(client.getVar(Varbits.EQUIPPED_WEAPON_TYPE)).thenReturn(this.weaponType.ordinal());
|
||||
when(client.getVar(VarPlayer.ATTACK_STYLE)).thenReturn(this.attackStyleId);
|
||||
|
||||
// Mock strength
|
||||
when(client.getBoostedSkillLevel(Skill.RANGED)).thenReturn(rangeLevel);
|
||||
|
||||
// Test
|
||||
RangeMaxHitCalculator maxHitCalculator = new RangeMaxHitCalculator(client, this.equipedItems);
|
||||
assertEquals(this.toString(), expectedMaxHit, maxHitCalculator.getMaxHit(), 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user