Merge pull request #18 from Kyleeld/master

additonal changes + plugins
This commit is contained in:
James
2019-04-20 15:42:18 -07:00
committed by GitHub
23 changed files with 2547 additions and 1 deletions

View File

@@ -57,6 +57,10 @@ public enum InventoryID
* Chambers of Xeric chest inventory.
*/
CHAMBERS_OF_XERIC_CHEST(581),
/**
* Looting Bag inventory
*/
LOOTING_BAG(516),
/**
* Theater of Blood reward chest inventory (Raids 2)
*/
@@ -78,4 +82,4 @@ public enum InventoryID
{
return id;
}
}
}

View File

@@ -16,6 +16,7 @@ import net.runelite.client.plugins.PluginDescriptor;
name = "fKeyRemapping",
description = "Used for interface hotkeys",
tags = {"hotkey", "remapping"},
type = "utility",
enabledByDefault = true
)
public class fKeyRemappingPlugin extends Plugin

View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2018 AWPH-I
* 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.lootingbagviewer;
import net.runelite.api.Client;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemContainer;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import javax.inject.Inject;
import java.awt.*;
import java.awt.image.BufferedImage;
class LootingBagViewerOverlay extends Overlay
{
private static final int INVENTORY_SIZE = 28;
private static final int PLACEHOLDER_WIDTH = 36;
private static final int PLACEHOLDER_HEIGHT = 32;
private static final ImageComponent PLACEHOLDER_IMAGE = new ImageComponent(new BufferedImage(PLACEHOLDER_WIDTH, PLACEHOLDER_HEIGHT, BufferedImage.TYPE_4BYTE_ABGR));
private final Client client;
private final ItemManager itemManager;
private final PanelComponent panelComponent = new PanelComponent();
private ItemContainer itemContainer;
private Item[] items;
@Inject
private LootingBagViewerOverlay(Client client, ItemManager itemManager)
{
setPosition(OverlayPosition.BOTTOM_RIGHT);
panelComponent.setWrapping(4);
panelComponent.setGap(new Point(6, 4));
panelComponent.setOrientation(PanelComponent.Orientation.HORIZONTAL);
this.itemManager = itemManager;
this.client = client;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (itemContainer == null)
{
if(client.getItemContainer(InventoryID.LOOTING_BAG) != null) {
itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG);
items = itemContainer.getItems();
}
return null;
}
else if(itemContainer != null && client.getItemContainer(InventoryID.LOOTING_BAG) != null)
{
itemContainer = client.getItemContainer(InventoryID.LOOTING_BAG);
Item[] tempItems = itemContainer.getItems();
for(int i = 0; i < items.length; i++)
{
if(!items[i].equals(tempItems[i]))
{
items = tempItems;
}
}
}
panelComponent.getChildren().clear();
for (int i = 0; i < INVENTORY_SIZE; i++)
{
if (i < items.length)
{
final Item item = items[i];
if (item.getQuantity() > 0)
{
final BufferedImage image = getImage(item);
if (image != null)
{
panelComponent.getChildren().add(new ImageComponent(image));
continue;
}
}
}
// put a placeholder image so each item is aligned properly and the panel is not resized
panelComponent.getChildren().add(PLACEHOLDER_IMAGE);
}
return panelComponent.render(graphics);
}
private BufferedImage getImage(Item item)
{
return itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1);
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (c) 2018 AWPH-I
* 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.lootingbagviewer;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import javax.inject.Inject;
@PluginDescriptor(
name = "PvP Looting Bag Viewer",
description = "Add an overlay showing the contents of your looting bag",
tags = {"alternate", "items", "overlay", "second"},
type = "utility",
enabledByDefault = false
)
public class LootingBagViewerPlugin extends Plugin
{
@Inject
private net.runelite.client.plugins.lootingbagviewer.LootingBagViewerOverlay overlay;
@Inject
private OverlayManager overlayManager;
@Override
public void startUp()
{
overlayManager.add(overlay);
}
@Override
public void shutDown()
{
overlayManager.remove(overlay);
}
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright (c) 2018, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving.BatSolver;
import java.util.Map;
import java.util.HashSet;
import java.util.HashMap;
import java.util.TreeSet;
import java.util.List;
import java.util.ArrayList;
import static net.runelite.client.plugins.raidsthieving.BatSolver.SolutionSet.SOLUTION_SETS;
public class BatSolver
{
private Map<Integer, Integer> numberOfSolutionsWithPoison;
private final SolutionSet solution;
private final HashSet<Integer> grubsChests;
public BatSolver(ThievingRoomType roomType)
{
solution = new SolutionSet(roomType);
grubsChests = new HashSet<>();
}
public void addEmptyChest(int chestId)
{
// When a new empty chest is found, add it to the current solution set
solution.addEmptyChest(chestId);
calculateChanceOfPoison();
}
public void addGrubsChest(int chestId)
{
// When a chest with grubs is found, keep track of it to invalidate solutions
grubsChests.add(chestId);
calculateChanceOfPoison();
}
public TreeSet<Integer> matchSolutions()
{
TreeSet<Integer> possibleEmptyChests = new TreeSet<>();
for (SolutionSet knownSolution : SolutionSet.SOLUTION_SETS)
{
if (knownSolution.getType() == solution.getType() && matchSolution(knownSolution))
{
possibleEmptyChests.addAll(knownSolution.getEmptyChests());
}
}
return possibleEmptyChests;
}
private boolean matchSolution(SolutionSet testSolution)
{
for (Integer grubsChest : grubsChests)
{
if (testSolution.containsChest(grubsChest))
{
// If one of the chests is known to have grubs, it cannot be a solution
return false;
}
}
boolean matchesAll = true;
boolean everMatched = false;
for (int i : solution.getEmptyChests())
{
if (!testSolution.containsChest(i))
{
matchesAll = false;
}
else
{
everMatched = true;
}
}
return matchesAll && everMatched;
}
public ThievingRoomType getType()
{
return solution.getType();
}
public void calculateChanceOfPoison()
{
if (getType() == null)
{
numberOfSolutionsWithPoison = null;
return;
}
numberOfSolutionsWithPoison = new HashMap<>();
for (SolutionSet sol : getPosssibleSolutions())
{
if (getType() == sol.getType() && (solution.getEmptyChests().size() == 0 || matchSolution(sol)))
{
for (Integer i : sol.getEmptyChests())
{
if (numberOfSolutionsWithPoison.containsKey(i))
{
numberOfSolutionsWithPoison.put(i, numberOfSolutionsWithPoison.get(i) + 1);
}
else
{
numberOfSolutionsWithPoison.put(i, 1);
}
}
}
}
}
private List<SolutionSet> getPosssibleSolutions()
{
List<SolutionSet> possibleSolutions = new ArrayList<>();
for (SolutionSet soln : SOLUTION_SETS)
{
// Check if we've found grubs in one of the chests, invalidating it as an solution
boolean foundMatch = false;
for (int i : grubsChests)
{
if (soln.containsChest(i))
{
foundMatch = true;
}
}
if (!foundMatch)
{
possibleSolutions.add(soln);
}
}
return possibleSolutions;
}
public double relativeLikelihoodPoison(int chestId)
{
// Returns a double between 0 and 1 of how likely the chest has poison based on the number of possible solutions
// Uses a Sigmoid like function to give good contrast in drawn opacity,
// perhaps could be changed to something more accurate quantitavely.
if (numberOfSolutionsWithPoison == null)
{
calculateChanceOfPoison();
}
if (numberOfSolutionsWithPoison == null)
{
return 1.0;
}
int mostFrequentPoison = 0;
for (Map.Entry<Integer, Integer> entry : numberOfSolutionsWithPoison.entrySet())
{
if (entry.getValue() > mostFrequentPoison)
{
mostFrequentPoison = entry.getValue();
}
}
int timesFound = 0;
if (numberOfSolutionsWithPoison.containsKey(chestId))
{
timesFound = numberOfSolutionsWithPoison.get(chestId);
}
double chestChance = (double) (timesFound) / (double) (mostFrequentPoison);
return 1. / (1 + Math.exp(5 - 10 * chestChance));
}
public int getNumberOfEmptyChests()
{
return solution.getEmptyChests().size();
}
}

View File

@@ -0,0 +1,261 @@
/*
* Copyright (c) 2018, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving.BatSolver;
import net.runelite.client.plugins.raidsthieving.InstancePoint;
import net.runelite.client.plugins.raidsthieving.ThievingChest;
import java.util.HashMap;
import java.util.Map;
public class ChestIdentifier
{
public ChestIdentifier(ThievingRoomType roomType)
{
chestIds = new HashMap<>();
switch (roomType)
{
case LEFT_TURN:
chestIds.put(new InstancePoint(3283, 5379), 1);
chestIds.put(new InstancePoint(3285, 5380), 2);
chestIds.put(new InstancePoint(3279, 5381), 3);
chestIds.put(new InstancePoint(3287, 5382), 4);
chestIds.put(new InstancePoint(3281, 5382), 5);
chestIds.put(new InstancePoint(3284, 5383), 6);
chestIds.put(new InstancePoint(3283, 5384), 7);
chestIds.put(new InstancePoint(3286, 5384), 8);
chestIds.put(new InstancePoint(3288, 5384), 9);
chestIds.put(new InstancePoint(3277, 5385), 10);
chestIds.put(new InstancePoint(3280, 5385), 11);
chestIds.put(new InstancePoint(3285, 5386), 12);
chestIds.put(new InstancePoint(3290, 5386), 13);
chestIds.put(new InstancePoint(3275, 5387), 14);
chestIds.put(new InstancePoint(3287, 5387), 15);
chestIds.put(new InstancePoint(3288, 5387), 16);
chestIds.put(new InstancePoint(3281, 5388), 17);
chestIds.put(new InstancePoint(3291, 5388), 18);
chestIds.put(new InstancePoint(3280, 5389), 19);
chestIds.put(new InstancePoint(3285, 5389), 20);
chestIds.put(new InstancePoint(3289, 5389), 21);
chestIds.put(new InstancePoint(3283, 5390), 22);
chestIds.put(new InstancePoint(3285, 5390), 23);
chestIds.put(new InstancePoint(3288, 5390), 24);
chestIds.put(new InstancePoint(3290, 5390), 25);
chestIds.put(new InstancePoint(3282, 5391), 26);
chestIds.put(new InstancePoint(3289, 5391), 27);
chestIds.put(new InstancePoint(3292, 5391), 28);
chestIds.put(new InstancePoint(3279, 5392), 29);
chestIds.put(new InstancePoint(3276, 5393), 30);
chestIds.put(new InstancePoint(3279, 5393), 31);
chestIds.put(new InstancePoint(3284, 5393), 32);
chestIds.put(new InstancePoint(3285, 5393), 33);
chestIds.put(new InstancePoint(3291, 5393), 34);
chestIds.put(new InstancePoint(3275, 5394), 35);
chestIds.put(new InstancePoint(3277, 5394), 36);
chestIds.put(new InstancePoint(3288, 5394), 37);
chestIds.put(new InstancePoint(3276, 5395), 38);
chestIds.put(new InstancePoint(3281, 5395), 39);
chestIds.put(new InstancePoint(3285, 5395), 40);
chestIds.put(new InstancePoint(3287, 5395), 41);
chestIds.put(new InstancePoint(3289, 5395), 42);
chestIds.put(new InstancePoint(3274, 5396), 43);
chestIds.put(new InstancePoint(3283, 5396), 44);
chestIds.put(new InstancePoint(3285, 5396), 45);
chestIds.put(new InstancePoint(3288, 5396), 46);
chestIds.put(new InstancePoint(3272, 5397), 47);
chestIds.put(new InstancePoint(3280, 5397), 48);
chestIds.put(new InstancePoint(3277, 5398), 49);
chestIds.put(new InstancePoint(3281, 5398), 50);
chestIds.put(new InstancePoint(3284, 5398), 51);
chestIds.put(new InstancePoint(3276, 5399), 52);
chestIds.put(new InstancePoint(3278, 5399), 53);
chestIds.put(new InstancePoint(3283, 5399), 54);
chestIds.put(new InstancePoint(3285, 5399), 55);
chestIds.put(new InstancePoint(3277, 5400), 56);
chestIds.put(new InstancePoint(3284, 5400), 57);
chestIds.put(new InstancePoint(3288, 5400), 58);
chestIds.put(new InstancePoint(3281, 5401), 59);
chestIds.put(new InstancePoint(3286, 5401), 60);
chestIds.put(new InstancePoint(3279, 5402), 61);
chestIds.put(new InstancePoint(3285, 5402), 62);
chestIds.put(new InstancePoint(3280, 5403), 63);
chestIds.put(new InstancePoint(3283, 5403), 64);
break;
case RIGHT_TURN:
chestIds.put(new InstancePoint(3338, 5405), 1);
chestIds.put(new InstancePoint(3334, 5405), 2);
chestIds.put(new InstancePoint(3342, 5404), 3);
chestIds.put(new InstancePoint(3340, 5404), 4);
chestIds.put(new InstancePoint(3345, 5403), 5);
chestIds.put(new InstancePoint(3334, 5403), 6);
chestIds.put(new InstancePoint(3330, 5403), 7);
chestIds.put(new InstancePoint(3343, 5402), 8);
chestIds.put(new InstancePoint(3342, 5402), 9);
chestIds.put(new InstancePoint(3339, 5402), 10);
chestIds.put(new InstancePoint(3338, 5402), 11);
chestIds.put(new InstancePoint(3336, 5402), 12);
chestIds.put(new InstancePoint(3347, 5401), 13);
chestIds.put(new InstancePoint(3330, 5401), 14);
chestIds.put(new InstancePoint(3345, 5400), 15);
chestIds.put(new InstancePoint(3341, 5400), 16);
chestIds.put(new InstancePoint(3337, 5400), 17);
chestIds.put(new InstancePoint(3334, 5400), 18);
chestIds.put(new InstancePoint(3345, 5399), 19);
chestIds.put(new InstancePoint(3343, 5399), 20);
chestIds.put(new InstancePoint(3340, 5399), 21);
chestIds.put(new InstancePoint(3335, 5399), 22);
chestIds.put(new InstancePoint(3331, 5399), 23);
chestIds.put(new InstancePoint(3338, 5398), 24);
chestIds.put(new InstancePoint(3337, 5398), 25);
chestIds.put(new InstancePoint(3345, 5397), 26);
chestIds.put(new InstancePoint(3341, 5397), 27);
chestIds.put(new InstancePoint(3334, 5397), 28);
chestIds.put(new InstancePoint(3331, 5397), 29);
chestIds.put(new InstancePoint(3346, 5396), 30);
chestIds.put(new InstancePoint(3343, 5396), 31);
chestIds.put(new InstancePoint(3339, 5396), 32);
chestIds.put(new InstancePoint(3335, 5396), 33);
chestIds.put(new InstancePoint(3333, 5396), 34);
chestIds.put(new InstancePoint(3340, 5395), 35);
chestIds.put(new InstancePoint(3337, 5395), 36);
chestIds.put(new InstancePoint(3334, 5395), 37);
chestIds.put(new InstancePoint(3345, 5394), 38);
chestIds.put(new InstancePoint(3342, 5394), 39);
chestIds.put(new InstancePoint(3332, 5394), 40);
chestIds.put(new InstancePoint(3343, 5393), 41);
chestIds.put(new InstancePoint(3341, 5393), 42);
chestIds.put(new InstancePoint(3338, 5393), 43);
chestIds.put(new InstancePoint(3335, 5393), 44);
chestIds.put(new InstancePoint(3334, 5393), 45);
chestIds.put(new InstancePoint(3346, 5392), 46);
chestIds.put(new InstancePoint(3342, 5392), 47);
chestIds.put(new InstancePoint(3332, 5392), 48);
chestIds.put(new InstancePoint(3350, 5391), 49);
chestIds.put(new InstancePoint(3346, 5391), 50);
chestIds.put(new InstancePoint(3340, 5391), 51);
chestIds.put(new InstancePoint(3339, 5391), 52);
chestIds.put(new InstancePoint(3336, 5391), 53);
chestIds.put(new InstancePoint(3333, 5391), 54);
chestIds.put(new InstancePoint(3349, 5390), 55);
chestIds.put(new InstancePoint(3343, 5390), 56);
chestIds.put(new InstancePoint(3337, 5390), 57);
chestIds.put(new InstancePoint(3335, 5390), 58);
chestIds.put(new InstancePoint(3344, 5389), 59);
chestIds.put(new InstancePoint(3340, 5389), 60);
chestIds.put(new InstancePoint(3336, 5389), 61);
chestIds.put(new InstancePoint(3333, 5389), 62);
chestIds.put(new InstancePoint(3346, 5388), 63);
chestIds.put(new InstancePoint(3340, 5387), 64);
chestIds.put(new InstancePoint(3337, 5386), 65);
chestIds.put(new InstancePoint(3333, 5386), 66);
chestIds.put(new InstancePoint(3338, 5385), 67);
chestIds.put(new InstancePoint(3336, 5385), 68);
chestIds.put(new InstancePoint(3337, 5384), 69);
chestIds.put(new InstancePoint(3340, 5382), 70);
chestIds.put(new InstancePoint(3334, 5383), 71);
chestIds.put(new InstancePoint(3340, 5379), 72);
chestIds.put(new InstancePoint(3338, 5380), 73);
chestIds.put(new InstancePoint(3336, 5381), 74);
break;
case STRAIGHT:
chestIds.put(new InstancePoint(3308, 5378), 1);
chestIds.put(new InstancePoint(3305, 5379), 2);
chestIds.put(new InstancePoint(3307, 5379), 3);
chestIds.put(new InstancePoint(3304, 5381), 4);
chestIds.put(new InstancePoint(3310, 5381), 5);
chestIds.put(new InstancePoint(3302, 5382), 6);
chestIds.put(new InstancePoint(3307, 5382), 7);
chestIds.put(new InstancePoint(3312, 5382), 8);
chestIds.put(new InstancePoint(3317, 5382), 9);
chestIds.put(new InstancePoint(3319, 5382), 10);
chestIds.put(new InstancePoint(3304, 5383), 11);
chestIds.put(new InstancePoint(3305, 5383), 12);
chestIds.put(new InstancePoint(3307, 5383), 13);
chestIds.put(new InstancePoint(3310, 5383), 14);
chestIds.put(new InstancePoint(3315, 5383), 15);
chestIds.put(new InstancePoint(3320, 5383), 16);
chestIds.put(new InstancePoint(3300, 5384), 17);
chestIds.put(new InstancePoint(3309, 5384), 18);
chestIds.put(new InstancePoint(3311, 5384), 19);
chestIds.put(new InstancePoint(3313, 5384), 20);
chestIds.put(new InstancePoint(3317, 5384), 21);
chestIds.put(new InstancePoint(3318, 5384), 22);
chestIds.put(new InstancePoint(3302, 5385), 23);
chestIds.put(new InstancePoint(3306, 5385), 24);
chestIds.put(new InstancePoint(3310, 5385), 25);
chestIds.put(new InstancePoint(3313, 5385), 26);
chestIds.put(new InstancePoint(3320, 5385), 27);
chestIds.put(new InstancePoint(3302, 5386), 28);
chestIds.put(new InstancePoint(3305, 5386), 29);
chestIds.put(new InstancePoint(3316, 5386), 30);
chestIds.put(new InstancePoint(3321, 5386), 31);
chestIds.put(new InstancePoint(3300, 5387), 32);
chestIds.put(new InstancePoint(3308, 5387), 33);
chestIds.put(new InstancePoint(3314, 5387), 34);
chestIds.put(new InstancePoint(3317, 5387), 35);
chestIds.put(new InstancePoint(3301, 5388), 36);
chestIds.put(new InstancePoint(3306, 5388), 37);
chestIds.put(new InstancePoint(3312, 5388), 38);
chestIds.put(new InstancePoint(3322, 5388), 39);
chestIds.put(new InstancePoint(3309, 5389), 40);
chestIds.put(new InstancePoint(3311, 5389), 41);
chestIds.put(new InstancePoint(3313, 5389), 42);
chestIds.put(new InstancePoint(3316, 5389), 43);
chestIds.put(new InstancePoint(3320, 5389), 44);
chestIds.put(new InstancePoint(3300, 5390), 45);
chestIds.put(new InstancePoint(3303, 5390), 46);
chestIds.put(new InstancePoint(3304, 5390), 47);
chestIds.put(new InstancePoint(3312, 5390), 48);
chestIds.put(new InstancePoint(3320, 5390), 49);
chestIds.put(new InstancePoint(3307, 5391), 50);
chestIds.put(new InstancePoint(3310, 5391), 51);
chestIds.put(new InstancePoint(3317, 5391), 52);
chestIds.put(new InstancePoint(3318, 5391), 53);
chestIds.put(new InstancePoint(3323, 5391), 54);
chestIds.put(new InstancePoint(3301, 5392), 55);
chestIds.put(new InstancePoint(3303, 5392), 56);
chestIds.put(new InstancePoint(3309, 5392), 57);
chestIds.put(new InstancePoint(3314, 5392), 58);
chestIds.put(new InstancePoint(3322, 5392), 59);
chestIds.put(new InstancePoint(3305, 5393), 60);
chestIds.put(new InstancePoint(3307, 5393), 61);
chestIds.put(new InstancePoint(3316, 5393), 62);
chestIds.put(new InstancePoint(3309, 5394), 63);
chestIds.put(new InstancePoint(3312, 5394), 64);
chestIds.put(new InstancePoint(3322, 5394), 65);
chestIds.put(new InstancePoint(3310, 5379), 66);
break;
}
}
public int indentifyChest(ThievingChest chest)
{
int id = chestIds.get(chest.getInstancePoint());
chest.setChestId(id);
return id;
}
private Map<InstancePoint, Integer> chestIds;
}

View File

@@ -0,0 +1,165 @@
/*
* Copyright (c) 2018, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving.BatSolver;
import lombok.Getter;
import java.util.HashSet;
import java.util.Arrays;
import java.util.Set;
// Each Thieving room has 4 empty chests
// User-reported data shows these 4 come in groups,
//
// e.g. if there is an empty chest in L room chest 1, the other empty chests could be 16, 17, 38, 54, 55
// See https://dikkenoob.github.io/ for more information
public class SolutionSet
{
public static final SolutionSet[] SOLUTION_SETS =
{
new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 16, 17, 55),
new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 17, 38, 54),
new SolutionSet(ThievingRoomType.LEFT_TURN, 2, 7, 21, 37),
new SolutionSet(ThievingRoomType.LEFT_TURN, 3, 5, 19, 30),
new SolutionSet(ThievingRoomType.LEFT_TURN, 3, 11, 15, 40),
new SolutionSet(ThievingRoomType.LEFT_TURN, 4, 22, 27, 46),
new SolutionSet(ThievingRoomType.LEFT_TURN, 5, 9, 19, 45),
new SolutionSet(ThievingRoomType.LEFT_TURN, 6, 24, 26, 41),
new SolutionSet(ThievingRoomType.LEFT_TURN, 6, 26, 32, 52),
new SolutionSet(ThievingRoomType.LEFT_TURN, 7, 13, 44, 59),
new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 14, 41, 43),
new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 10, 28, 33),
new SolutionSet(ThievingRoomType.LEFT_TURN, 8, 31, 47, 50),
new SolutionSet(ThievingRoomType.LEFT_TURN, 10, 35, 54, 63),
new SolutionSet(ThievingRoomType.LEFT_TURN, 10, 30, 32, 59),
new SolutionSet(ThievingRoomType.LEFT_TURN, 12, 40, 53, 56),
new SolutionSet(ThievingRoomType.LEFT_TURN, 12, 13, 42, 54),
new SolutionSet(ThievingRoomType.LEFT_TURN, 13, 22, 27, 46),
new SolutionSet(ThievingRoomType.LEFT_TURN, 14, 18, 23, 51),
new SolutionSet(ThievingRoomType.LEFT_TURN, 15, 43, 44, 58),
new SolutionSet(ThievingRoomType.LEFT_TURN, 15, 16, 42, 45),
new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 29, 45, 51),
new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 25, 32, 34),
new SolutionSet(ThievingRoomType.LEFT_TURN, 20, 28, 51, 62),
new SolutionSet(ThievingRoomType.LEFT_TURN, 21, 39, 41, 58),
new SolutionSet(ThievingRoomType.LEFT_TURN, 22, 25, 54, 64),
new SolutionSet(ThievingRoomType.LEFT_TURN, 23, 31, 47, 55),
new SolutionSet(ThievingRoomType.LEFT_TURN, 23, 33, 37, 60),
new SolutionSet(ThievingRoomType.LEFT_TURN, 24, 34, 55),
new SolutionSet(ThievingRoomType.LEFT_TURN, 26, 50, 63, 27),
new SolutionSet(ThievingRoomType.LEFT_TURN, 29, 39, 41, 61),
new SolutionSet(ThievingRoomType.LEFT_TURN, 33, 46, 52, 57),
new SolutionSet(ThievingRoomType.LEFT_TURN, 34, 45, 49, 60),
new SolutionSet(ThievingRoomType.LEFT_TURN, 36, 40, 42, 62),
new SolutionSet(ThievingRoomType.LEFT_TURN, 37, 38, 51, 64),
new SolutionSet(ThievingRoomType.LEFT_TURN, 48, 53, 55, 56),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 1, 6, 28, 41),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 1, 42, 55, 60),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 2, 10, 31, 44),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 2, 33, 51, 68),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 3, 31, 43, 46),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 3, 5, 21, 48),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 4, 20, 24, 33),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 4, 38, 47),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 5, 21, 48),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 5, 17, 35, 63),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 7, 17, 45, 47),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 7, 37, 41, 52),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 8, 13, 40, 42),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 8, 20, 24, 30),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 9, 15, 23, 35),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 11, 13, 21, 50),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 11, 18, 37, 39),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 12, 14, 27, 34),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 14, 45, 67, 71),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 16, 22, 29, 32),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 18, 28, 31, 64),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 19, 21, 63, 69),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 20, 51, 68, 72),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 22, 29, 56, 61),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 23, 53, 66, 74),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 26, 35, 53, 59),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 27, 30, 55, 57),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 31, 58, 60, 73),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 34, 57, 58, 70),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 38, 56, 61, 70),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 40, 54, 65, 72),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 42, 46, 65),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 47, 49, 66, 67),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 48, 62, 69),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 9, 19, 32, 41),
new SolutionSet(ThievingRoomType.RIGHT_TURN, 16, 26, 36, 39),
new SolutionSet(ThievingRoomType.STRAIGHT, 1, 39, 43, 51),
new SolutionSet(ThievingRoomType.STRAIGHT, 2, 15, 20, 53),
new SolutionSet(ThievingRoomType.STRAIGHT, 3, 10, 42, 44),
new SolutionSet(ThievingRoomType.STRAIGHT, 4, 14, 38, 52),
new SolutionSet(ThievingRoomType.STRAIGHT, 5, 6, 35, 41),
new SolutionSet(ThievingRoomType.STRAIGHT, 7, 16, 34, 49),
new SolutionSet(ThievingRoomType.STRAIGHT, 9, 12, 26, 27),
new SolutionSet(ThievingRoomType.STRAIGHT, 13, 25, 30, 31),
new SolutionSet(ThievingRoomType.STRAIGHT, 15, 20, 53),
new SolutionSet(ThievingRoomType.STRAIGHT, 17, 24, 34, 58),
new SolutionSet(ThievingRoomType.STRAIGHT, 18, 23, 35, 57),
new SolutionSet(ThievingRoomType.STRAIGHT, 19, 26, 47, 65),
new SolutionSet(ThievingRoomType.STRAIGHT, 21, 33, 36, 61),
new SolutionSet(ThievingRoomType.STRAIGHT, 21, 54, 66),
new SolutionSet(ThievingRoomType.STRAIGHT, 22, 25, 46, 55),
new SolutionSet(ThievingRoomType.STRAIGHT, 24, 34, 58),
new SolutionSet(ThievingRoomType.STRAIGHT, 28, 40, 52, 62),
new SolutionSet(ThievingRoomType.STRAIGHT, 29, 41, 42, 63),
new SolutionSet(ThievingRoomType.STRAIGHT, 30, 32, 37, 64),
new SolutionSet(ThievingRoomType.STRAIGHT, 39, 43, 51),
new SolutionSet(ThievingRoomType.STRAIGHT, 43, 45, 50, 60),
new SolutionSet(ThievingRoomType.STRAIGHT, 51, 53, 56, 59)
};
SolutionSet(ThievingRoomType type)
{
this.type = type;
emptyChests = new HashSet<>();
}
private SolutionSet(ThievingRoomType type, Integer... emptyChests)
{
this.type = type;
this.emptyChests = new HashSet<>(Arrays.asList(emptyChests));
}
public void addEmptyChest(int chestId)
{
emptyChests.add(chestId);
}
public boolean containsChest(int chestId)
{
return emptyChests.contains(chestId);
}
@Getter
private ThievingRoomType type;
@Getter
private Set<Integer> emptyChests;
}

View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2018, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving.BatSolver;
// There are three distinct Thieving rooms, distinguished by the position of the entrance relative to the exit
// e.g. If you enter the room and must turn left to get to the exit and trough, this is a LEFT_TURN
import net.runelite.client.plugins.raidsthieving.InstancePoint;
public enum ThievingRoomType
{
LEFT_TURN(3271, 5389),
RIGHT_TURN(3350, 5399),
STRAIGHT(3317, 5397);
private final int x;
private final int y;
ThievingRoomType(int x, int y)
{
this.x = x;
this.y = y;
}
public static ThievingRoomType IdentifyByInstancePoint(InstancePoint point)
{
for (ThievingRoomType type : ThievingRoomType.values())
{
if (Math.abs(type.x - point.getX()) <= 1 &&
Math.abs(type.y - point.getY()) <= 1)
{
return type;
}
}
return null;
}
}

View File

@@ -0,0 +1,172 @@
/*
* Copyright (c) 2018, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.plugins.raidsthieving.BatSolver.BatSolver;
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.components.ProgressPieComponent;
import javax.inject.Inject;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.util.Map;
import java.util.TreeSet;
/**
* Represents the overlay that shows timers on traps that are placed by the
* player.
*/
public class ChestOverlay extends Overlay
{
private final Client client;
private final RaidsThievingPlugin plugin;
private final RaidsThievingConfig config;
@Inject
ChestOverlay(Client client, RaidsThievingPlugin plugin, RaidsThievingConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.plugin = plugin;
this.config = config;
this.client = client;
}
@Override
public Dimension render(Graphics2D graphics)
{
drawChests(graphics);
return null;
}
/**
* Updates the timer colors.
*/
public void updateConfig()
{
}
/**
* Iterates over all the traps that were placed by the local player, and
* draws a circle or a timer on the trap, depending on the trap state.
*
* @param graphics
*/
private void drawChests(Graphics2D graphics)
{
for (Map.Entry<WorldPoint, ThievingChest> entry : plugin.getChests().entrySet())
{
ThievingChest chest = entry.getValue();
WorldPoint pos = entry.getKey();
if (chest != null)
{
if (!plugin.isBatsFound() && !chest.isEverOpened())
{
if (shouldDrawChest(pos))
{
Color drawColor = new Color(config.getPotentialBatColor().getRed(),
config.getPotentialBatColor().getGreen(),
config.getPotentialBatColor().getBlue(),
getChestOpacity(pos));
drawCircleOnTrap(graphics, chest, drawColor);
}
}
if (chest.isPoison())
{
drawCircleOnTrap(graphics, chest, config.getPoisonTrapColor());
}
}
}
}
private boolean shouldDrawChest(WorldPoint chestPos)
{
if (plugin.numberOfEmptyChestsFound() == 0)
{
return true;
}
int chestId = plugin.getChestId(chestPos);
BatSolver solver = plugin.getSolver();
if (solver != null && chestId != -1)
{
TreeSet<Integer> matches = solver.matchSolutions();
return matches.contains(chestId) || matches.size() == 0;
}
return true;
}
/**
* Draws a timer on a given trap.
*
* @param graphics
* @param chest The chest on which the circle needs to be drawn
* @param fill The fill color of the timer
*/
private void drawCircleOnTrap(Graphics2D graphics, ThievingChest chest, Color fill)
{
if (chest.getLocalPoint().getPlane() != client.getPlane())
{
return;
}
LocalPoint localLoc = LocalPoint.fromWorld(client, chest.getLocalPoint());
if (localLoc == null)
{
return;
}
Point loc = Perspective.localToCanvas(client, localLoc, chest.getLocalPoint().getPlane());
ProgressPieComponent pie = new ProgressPieComponent();
pie.setFill(fill);
pie.setBorderColor(Color.BLACK);
pie.setPosition(loc);
pie.setProgress(1);
if (graphics != null && loc != null)
{
pie.render(graphics);
}
}
private int getChestOpacity(WorldPoint chestPos)
{
int chestId = plugin.getChestId(chestPos);
BatSolver solver = plugin.getSolver();
if (solver != null && chestId != -1)
{
return (int) (255 * solver.relativeLikelihoodPoison(chestId));
}
return 255;
}
}

View File

@@ -0,0 +1,98 @@
package net.runelite.client.plugins.raidsthieving;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.Point;
import net.runelite.api.coords.WorldPoint;
import java.util.Objects;
/**
* Represents a point in the instance chunk, invariant of rotation.
*/
@Getter
public class InstancePoint
{
private static final int CHUNK_SIZE = 8;
private static final double CHUNK_OFFSET = 3.5;
public InstancePoint(int x, int y, int rot)
{
this.x = x;
this.y = y;
this.rot = rot;
}
public InstancePoint(int x, int y)
{
this.x = x;
this.y = y;
this.rot = 0;
}
public static InstancePoint buildFromPoint(WorldPoint worldPoint, Client client)
{
Point point = new Point(worldPoint.getX(), worldPoint.getY());
Point base = new Point(client.getBaseX(), client.getBaseY());
int plane = worldPoint.getPlane();
int deltaX = point.getX() - base.getX();
int deltaY = point.getY() - base.getY();
int chunkIndexX = deltaX / CHUNK_SIZE;
int chunkIndexY = deltaY / CHUNK_SIZE;
int chunkData = client.getInstanceTemplateChunks()[plane][chunkIndexX][chunkIndexY];
int rotation = chunkData >> 1 & 0x3;
int y = (chunkData >> 3 & 0x7FF) * 8;
int x = (chunkData >> 14 & 0x3FF) * 8;
return buildFromTile(base, point, rotation, new Point(x, y));
}
public static InstancePoint buildFromTile(Point base, Point tile, int rot, Point chunkOrigin)
{
int deltaX = tile.getX() - base.getX();
int deltaY = tile.getY() - base.getY();
double chunkOffsetX = (deltaX % CHUNK_SIZE) - CHUNK_OFFSET;
double chunkOffsetY = (deltaY % CHUNK_SIZE) - CHUNK_OFFSET;
for (int i = 0; i < rot; i++)
{
double temp = chunkOffsetX;
chunkOffsetX = -chunkOffsetY;
chunkOffsetY = temp;
}
chunkOffsetX += CHUNK_OFFSET;
chunkOffsetY += CHUNK_OFFSET;
int invariantChunkOffsetX = (int) chunkOffsetX;
int invariantChunkOffsetY = (int) chunkOffsetY;
return new InstancePoint(
chunkOrigin.getX() + invariantChunkOffsetX,
chunkOrigin.getY() + invariantChunkOffsetY,
rot);
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
InstancePoint that = (InstancePoint) o;
return x == that.x &&
y == that.y;
}
@Override
public int hashCode()
{
return Objects.hash(x, y);
}
private int x;
private int y;
private int rot;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2017, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import java.awt.Color;
@ConfigGroup("raidsthievingplugin")
public interface RaidsThievingConfig extends Config
{
@ConfigItem(
position = 1,
keyName = "hexColorPotentialBat",
name = "Potential Bat",
description = "Color of marker for chests which could have bat"
)
default Color getPotentialBatColor()
{
return Color.YELLOW;
}
@ConfigItem(
position = 2,
keyName = "hexColorPoison",
name = "Poison trap",
description = "Color of chest with poison"
)
default Color getPoisonTrapColor()
{
return Color.GREEN;
}
@ConfigItem(
position = 5,
keyName = "batNotify",
name = "Notify when found",
description = "Send notification if you see bats being found."
)
default boolean batFoundNotify()
{
return false;
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2017, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving;
public class RaidsThievingConstants
{
public static final int CLOSED_CHEST_ID = 29742;
public static final int OPEN_EMPTY_CHEST = 29743;
public static final int OPEN_FULL_CHEST_1 = 29744;
public static final int OPEN_FULL_CHEST_2 = 29745;
public static final int EMPTY_TROUGH = 29746;
public static final int[] STORAGE = {29769, 29770, 29771, 29772};
}

View File

@@ -0,0 +1,271 @@
/*
* Copyright (c) 2017, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving;
import com.google.inject.Provides;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.GraphicsObject;
import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GraphicsObjectCreated;
import net.runelite.api.events.VarbitChanged;
import net.runelite.client.Notifier;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.raidsthieving.BatSolver.BatSolver;
import net.runelite.client.plugins.raidsthieving.BatSolver.ChestIdentifier;
import net.runelite.client.plugins.raidsthieving.BatSolver.ThievingRoomType;
import net.runelite.client.ui.overlay.OverlayManager;
import javax.inject.Inject;
import java.text.MessageFormat;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@PluginDescriptor(
name = "Raids Bat Finder",
description = "Tracks which chests need to be searched for bats and which poison",
tags = {"overlay", "skilling", "raid"},
type = "PVM"
)
public class RaidsThievingPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private ChestOverlay overlay;
@Inject
private Notifier notifier;
@Inject
private RaidsThievingConfig config;
@Getter
private final Map<WorldPoint, ThievingChest> chests = new HashMap<>();
@Getter
private Instant lastActionTime = Instant.ofEpochMilli(0);
private boolean inRaidChambers;
@Getter
private boolean batsFound;
@Getter
private BatSolver solver;
@Getter
private ChestIdentifier mapper;
@Provides
RaidsThievingConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(RaidsThievingConfig.class);
}
@Override
protected void startUp()
{
overlayManager.add(overlay);
overlay.updateConfig();
reset();
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
lastActionTime = Instant.ofEpochMilli(0);
chests.clear();
}
@Subscribe
public void onGameObjectSpawned(GameObjectSpawned event)
{
GameObject obj = event.getGameObject();
WorldPoint loc = obj.getWorldLocation();
InstancePoint absLoc = InstancePoint.buildFromPoint(loc, client);
if (obj.getId() == RaidsThievingConstants.EMPTY_TROUGH)
{
ThievingRoomType type = ThievingRoomType.IdentifyByInstancePoint(absLoc);
if (type != null)
{
solver = new BatSolver(type);
mapper = new ChestIdentifier(type);
for (ThievingChest chest : chests.values())
{
mapper.indentifyChest(chest);
}
}
else
{
log.error(MessageFormat.format("Unable to identify room type with: {0} {1} {2} {3} {4}.",
loc.getX(), loc.getY(), absLoc.getX(), absLoc.getY(), absLoc.getRot()));
log.error("Please report this @https://github.com/runelite/runelite/pull/4914!");
}
}
if (obj.getId() == RaidsThievingConstants.CLOSED_CHEST_ID)
{
if (!chests.containsKey(loc))
{
ThievingChest chest = new ThievingChest(obj, absLoc);
if (mapper != null)
{
mapper.indentifyChest(chest);
}
chests.put(loc, chest);
}
else
{
checkForBats();
}
}
if (obj.getId() == RaidsThievingConstants.OPEN_FULL_CHEST_1 ||
obj.getId() == RaidsThievingConstants.OPEN_FULL_CHEST_2)
{
ThievingChest chest = chests.get(obj.getWorldLocation());
// We found a chest that has grubs
log.info(MessageFormat.format("Found grubs at {0}, {1} chestId: {2}", loc.getX(), loc.getY(), chest.getChestId()));
if (solver != null && chest.getChestId() != -1)
{
chest.setEverOpened(true);
solver.addGrubsChest(chest.getChestId());
}
checkForBats();
}
if (obj.getId() == RaidsThievingConstants.OPEN_EMPTY_CHEST)
{
ThievingChest chest = chests.get(obj.getWorldLocation());
// We found a chest that could have poison
if (solver != null && chest.getChestId() != -1)
{
chest.setEmpty(true);
chest.setEverOpened(true);
solver.addEmptyChest(chest.getChestId());
}
}
}
@Subscribe
public void onGraphicsObjectCreated(GraphicsObjectCreated event)
{
GraphicsObject obj = event.getGraphicsObject();
if (obj.getId() == 184)
{
log.debug("Found poison splat");
WorldPoint loc = WorldPoint.fromLocal(client, obj.getLocation());
chests.get(loc).setPoison(true);
}
}
@Subscribe
public void onVarbitChanged(VarbitChanged event)
{
boolean setting = client.getVar(Varbits.IN_RAID) == 1;
if (inRaidChambers != setting)
{
inRaidChambers = setting;
reset();
}
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (event.getGroup().equals("raidsthievingplugin"))
{
overlay.updateConfig();
}
}
private void reset()
{
chests.clear();
batsFound = false;
solver = null;
mapper = null;
}
public int numberOfEmptyChestsFound()
{
int total = 0;
for (ThievingChest chest : chests.values())
{
if (chest.isEmpty())
{
total++;
}
}
return total;
}
private boolean checkForBats()
{
for (ThievingChest chest : chests.values())
{
if (chest.isEmpty() && !chest.isPoison())
{
batsFound = true;
if (config.batFoundNotify())
{
notifier.notify("Bats have been found!");
}
return true;
}
}
return false;
}
public int getChestId(WorldPoint worldPoint)
{
return chests.get(worldPoint).getChestId();
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (c) 2019, Tim Lehner <Timothy.Lehner.2011@live.rhul.ac.uk>
* 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.raidsthieving;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.GameObject;
import net.runelite.api.coords.WorldPoint;
/**
* Wrapper class for a GameObject that represents a chest in the thieving room of Chambers of Xeric.
*/
@Getter
public class ThievingChest
{
/**
* If the chest has never been opened, it could have bats.
*/
@Setter
private boolean everOpened;
/**
* If the chest is empty, it could have bats.
*/
@Setter
private boolean empty;
/**
* If the chest contains a poison trap instead.
*/
@Setter
private boolean poison;
@Setter
private int chestId;
private final WorldPoint localPoint;
private final InstancePoint instancePoint;
/**
* Constructor for a ThievingChest object
*
* @param gameObject The gameobject thats corresponds with this trap.
*/
ThievingChest(GameObject gameObject, InstancePoint instancePoint)
{
this.everOpened = false;
this.poison = false;
this.empty = false;
localPoint = gameObject.getWorldLocation();
this.instancePoint = instancePoint;
this.chestId = -1;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (c) 2018, Infinitay <https://github.com/Infinitay>
* Copyright (c) 2018, Shaun Dreclin <https://github.com/ShaunDreclin>
*
* 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.rememberclan;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("rememberclan")
public interface RememberClanConfig extends Config
{
@ConfigItem(
position = 1,
keyName = "clanname",
name = "Clan Name",
description = "Clanname to always remember"
)
default String clanname()
{
return "";
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2018, Infinitay <https://github.com/Infinitay>
* Copyright (c) 2018, Shaun Dreclin <https://github.com/ShaunDreclin>
* 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.rememberclan;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.vars.AccountType;
import net.runelite.client.chat.ChatColorType;
import net.runelite.client.chat.ChatMessageBuilder;
import net.runelite.client.chat.ChatMessageManager;
import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Remember Clan",
description = "Remember a specific clan!",
type = "utility",
enabledByDefault = false
)
public class RememberClanPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private RememberClanConfig config;
@Inject
private ChatMessageManager chatMessageManager;
private boolean loggingIn;
@Provides
RememberClanConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(RememberClanConfig.class);
}
@Subscribe
public void onGameTick(GameTick event)
{
client.setVar(VarClientStr.RECENT_CLAN_CHAT,config.clanname());
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2019, FlaxOnEm <flax.on.em@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.stronghold;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.runelite.api.widgets.Widget;
import java.util.HashMap;
import java.util.Map;
@Getter
@RequiredArgsConstructor
enum StrongholdAnswer {
PAIR_0("To pass you must answer me this: Hey adventurer!<br>You've been randomly selected for a prize of 1 year of<br>free membership! I'm just going to need some of your<br>account details so I can put it on your account!", "No way! I'm reporting you to Jagex!"),
PAIR_1("To pass you must answer me this: Can I leave my<br>account logged in while I'm out of the room?", "No."),
PAIR_2("To pass you must answer me this: How do I remove a<br>hijacker from my account?", "Use the Account Recovery System."),
PAIR_3("To pass you must answer me this: What do you do if<br>someone asks you for your password or bank PIN to<br>make you a player moderator?", "Don't give them the information and send an 'Abuse report'."),
PAIR_4("To pass you must answer me this: You're watching a<br>stream by someone claiming to be Jagex offering double<br>xp. What do you do?", "Report the stream as a scam. Real Jagex streams have a 'verified' mark."),
PAIR_5("To pass you must answer me this: My friend asks me<br>for my password so that he can do a difficult quest for<br>me. Do I give it to them?", "Don't give them my password."),
PAIR_6("To pass you must answer me this: Who can I give my<br>password to?", "Nobody."),
PAIR_7("To pass you must answer me this: How do I set up<br>two-factor authentication for my Old School RuneScape<br>account?", "Through account settings on oldschool.runescape.com."),
PAIR_8("To pass you must answer me this: What is an example<br>of a good bank PIN?", "The birthday of a famous person or event."),
PAIR_9("To pass you must answer me this: What should you do<br>if your real-life friend asks for your password so he<br>can check your stats?", "Don't give out your password to anyone. Not even close friends."),
PAIR_A("To pass you must answer me this: A player tells you to<br>search for a video online, click the link in the description<br>and comment on the forum post to win a cash prize.<br>What do you do?", "Report the player for phishing."),
PAIR_B("To pass you must answer me this: You have been<br>offered an opportunity to check out a free giveaway or<br>double XP signup via email or in game chat. What<br>should I do?", "Report the incident and do not click any links."),
PAIR_C("To pass you must answer me this: How do I set a<br>bank PIN?", "Talk to any banker."),
PAIR_D("To pass you must answer me this: What do I do if a<br>moderator asks me for my account details?", "Politely tell them no and then use the 'Report Abuse' button."),
PAIR_E("To pass you must answer me this: You are part way<br>through the Stronghold of Security when you have to<br>answer another question. After you answer the question,<br>you should...", "Read the text and follow the advice given."),
PAIR_F("To pass you must answer me this: Will Jagex prevent<br>me from saying my PIN in game?", "No."),
PAIR_G("that sound?", "No way! You'll just take my gold for your own! Reported!"),
PAIR_H("To pass you must answer me this: What should I do if<br>I receive an email asking me to verify my identity or<br>Account details due to suspicious activity?", "Don't click any links, forward the email to reportphishing@jagex.com."),
PAIR_I("To pass you must answer me this: A website claims that<br>they can make me a player moderator. What should I<br>do?", "Inform Jagex by emailing reportphishing@jagex.com."),
PAIR_J("react?", "Don't share your information and report the player."),
PAIR_K("To pass you must answer me this: What do you do if<br>someone asks you for your password or bank PIN to<br>make you a member for free?", "Don't tell them anything and click the 'Report Abuse' button."),
PAIR_L("To pass you must answer me this: Is it OK to buy an<br>Old School RuneScape account?", "No, you should never buy an account."),
PAIR_M("To pass you must answer me this: You have been<br>offered an opportunity to check out a free giveaway or<br>double XP signup via social media or stream. What<br>should I do?", "Report the incident and do not click any links."),
PAIR_N("To pass you must answer me this: Where is it safe to<br>use my Old School RuneScape password?", "Only on the Old School RuneScape website."),
PAIR_O("To pass you must answer me this: What is the best<br>way to secure your account?", "Authenticator and two-step login on my registered email."),
PAIR_P("To pass you must answer me this: Who is it ok to<br>share my account with?", "Nobody."),
PAIR_Q("To pass you must answer me this: What should you do<br>if another player messages you recommending a website<br>to purchase items and/or gold?", "Do not visit the website and report the player who messaged you."),
PAIR_R("To pass you must answer me this: Whose responsibility<br>is it to keep your account secure?", "Me."),
PAIR_S("To pass you must answer me this: Is it safe to pay<br>someone to level your account?", "No, you should never allow anyone to level your account."),
PAIR_T("To pass you must answer me this: What do I do if my<br>account is compromised?", "Secure my device and reset my password."),
PAIR_U("respond?", "Decline the offer and report that player."),
PAIR_V("To pass you must answer me this: A player says that<br>Jagex prevents you from saying your password<br>backwards in game. What do you do?", "Don't type in my password backwards and report the player."),
PAIR_W("To pass you must answer me this: What do I do if I<br>think I have a keylogger or virus?", "Virus scan my device then change my password."),
PAIR_X("To pass you must answer me this: What is the best<br>security step you can take to keep your registered<br>email secure?", "Set up 2 step authentication with my email provider.");
static final Map<String, String> MATCHES = new HashMap<>();
static {
for (StrongholdAnswer strongholdAnswer : StrongholdAnswer.values()) {
MATCHES.put(strongholdAnswer.question, strongholdAnswer.answer);
}
}
private final String question;
private final String answer;
static Widget findCorrect(final String question, final Widget[] widgets) {
final String s = MATCHES.get(question);
for (Widget widget: widgets) {
if (widget != null && widget.getText().equals(s))
return widget;
}
return null;
}
}

View File

@@ -0,0 +1,108 @@
/*
* Copyright (c) 2019, FlaxOnEm <flax.on.em@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.stronghold;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.events.ClientTick;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetID;
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.util.ColorUtil;
import javax.inject.Inject;
import java.awt.Color;
@PluginDescriptor(
name = "Stronghold",
description = "Highlights the correct answer to Stronghold of Security questions",
tags = {"stronghold", "security", "overlay", "answer", "highlight"},
type = "utility"
)
@Slf4j
public class StrongholdPlugin extends Plugin {
private static final Color ANSWER_COLOR = new Color(230, 0, 230);
@Inject
private Client client;
private boolean queueNPCDialogue;
private boolean queueNPCOption;
private String questionCache;
@Subscribe
public void onWidgetLoaded(WidgetLoaded widgetLoaded) {
switch (widgetLoaded.getGroupId()) {
case WidgetID.DIALOG_NPC_GROUP_ID:
queueNPCDialogue = true;
break;
case WidgetID.DIALOG_OPTION_GROUP_ID:
queueNPCOption = true;
break;
}
}
@Subscribe
public void onClientTick(ClientTick t) {
if (queueNPCDialogue) {
queueNPCDialogue = false;
onNPCDialogue();
}
if (queueNPCOption) {
queueNPCOption = false;
onNPCOption();
}
}
private void onNPCDialogue() {
final Widget debugWidget = client.getWidget(WidgetInfo.DIALOG_NPC_TEXT);
final String npcText = debugWidget.getText();
if (StrongholdAnswer.MATCHES.containsKey(npcText))
questionCache = npcText;
}
private void onNPCOption() {
if (questionCache == null)
return;
final Widget optionsWidget = client.getWidget(WidgetInfo.DIALOG_OPTION);
if (optionsWidget == null)
return;
final Widget[] widgets = optionsWidget.getParent().getChildren();
final Widget answerWidget = StrongholdAnswer.findCorrect(questionCache, widgets);
questionCache = null;
if (answerWidget == null)
return;
final String answerText = answerWidget.getText();
answerWidget.setText(ColorUtil.wrapWithColorTag(answerText, ANSWER_COLOR));
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright (c) 2018, Andrew EP | ElPinche256 <https://github.com/ElPinche256>
* 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.warindicators;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("warIndicators")
public interface WarIndicatorConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "highLightCallers",
name = "Highlight Callers",
description = "Highlight listed caller(s)"
)
default boolean highLightCallers()
{
return true;
}
@ConfigItem(
position = 1,
keyName = "callerColor",
name = "Caller(s) Color",
description = "Color to highlight caller's name"
)
default Color getCallerColor()
{
return new Color(36, 255, 237);
}
@ConfigItem(
position = 2,
keyName = "callerMinimap",
name = "Callers on Minimap",
description = "Show your caller(s) on the minimap"
)
default boolean callerMinimap()
{
return false;
}
@ConfigItem(
position = 3,
keyName = "callerTile",
name = "Show Caller's Tile",
description = "Show the tile your target is standing on"
)
default boolean callerTile()
{
return false;
}
@ConfigItem(
position = 4,
keyName = "activeCallers",
name = "Callers",
description = "Adds a user to your caller list. Format: (caller), (caller)"
)
default String getActiveCallers()
{
return "";
}
@ConfigItem(
position = 5,
keyName = "activeCallers",
name = "",
description = ""
)
void setActiveCallers(String key);
@ConfigItem(
position = 6,
keyName = "highlightSnipes",
name = "Highlight Targets",
description = "Highlight listed target(s)"
)
default boolean highlightSnipes()
{
return true;
}
@ConfigItem(
position = 7,
keyName = "snipeColor",
name = "Target(s) Color",
description = "Color to highlight target name"
)
default Color getSnipeColor()
{
return new Color(255, 0, 0);
}
@ConfigItem(
position = 8,
keyName = "snipeMinimap",
name = "Targets on Minimap",
description = "Show your target on the minimap"
)
default boolean snipeMinimap()
{
return false;
}
@ConfigItem(
position = 9,
keyName = "snipeTile",
name = "Show Target's Tile",
description = "Show the tile your target is standing on"
)
default boolean snipeTile()
{
return false;
}
@ConfigItem(
position = 10,
keyName = "targetedSnipes",
name = "Targets",
description = "Adds a user to your snipe list. Format: (target), (target)"
)
default String getTargetedSnipes()
{
return "";
}
@ConfigItem(
position = 11,
keyName = "targetedSnipes",
name = "",
description = ""
)
void setTargetedSnipe(String key);
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2018, Andrew EP | ElPinche256 <https://github.com/ElPinche256>
* 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.warindicators;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Player;
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.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
import org.apache.commons.lang3.ArrayUtils;
@Singleton
public class WarIndicatorMiniMapOverlay extends Overlay
{
private final WarIndicatorService warIndicatorService;
private final WarIndicatorConfig config;
@Inject
private WarIndicatorMiniMapOverlay(WarIndicatorConfig config, WarIndicatorService warIndicatorService)
{
this.config = config;
this.warIndicatorService = warIndicatorService;
setLayer(OverlayLayer.ABOVE_WIDGETS);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
warIndicatorService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
{
final String name = actor.getName().replace('\u00A0', ' ');
final net.runelite.api.Point minimapLocation = actor.getMinimapLocation();
String[] callers = config.getActiveCallers().split(", ");
String[] targets = config.getTargetedSnipes().split(", ");
if (config.callerMinimap() && ArrayUtils.contains(callers, actor.getName()))
{
if (minimapLocation != null)
{
OverlayUtil.renderTextLocation(graphics, minimapLocation, name, color);
}
}
if (config.snipeMinimap() && ArrayUtils.contains(targets, actor.getName()))
{
if (minimapLocation != null)
{
OverlayUtil.renderTextLocation(graphics, minimapLocation, name, color);
}
}
}
}

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2018, Andrew EP | ElPinche256 <https://github.com/ElPinche256>
* 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.warindicators;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.apache.commons.lang3.ArrayUtils;
import net.runelite.api.Player;
import net.runelite.api.Point;
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.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
@Singleton
public class WarIndicatorOverlay extends Overlay
{
private final WarIndicatorService warIndicatorService;
private final WarIndicatorConfig config;
@Inject
private WarIndicatorOverlay(WarIndicatorConfig config, WarIndicatorService warIndicatorService)
{
this.config = config;
this.warIndicatorService = warIndicatorService;
setLayer(OverlayLayer.ABOVE_SCENE);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
warIndicatorService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
{
if (!config.highlightSnipes() && !config.highLightCallers())
{
return;
}
Polygon poly = actor.getCanvasTilePoly();
String[] callers = config.getActiveCallers().split(", ");
String[] targets = config.getTargetedSnipes().split(", ");
if (config.callerTile() && ArrayUtils.contains(callers, actor.getName()))
{
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, color);
}
}
if (config.snipeTile() && ArrayUtils.contains(targets, actor.getName()))
{
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, color);
}
}
String name = actor.getName().replace('\u00A0', ' ');
int offset = actor.getLogicalHeight() + 40;
Point textLocation = actor.getCanvasTextLocation(graphics, name, offset);
if (textLocation != null)
{
OverlayUtil.renderTextLocation(graphics, textLocation, name, color);
}
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (c) 2018, Andrew EP | ElPinche256 <https://github.com/ElPinche256>
* 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.warindicators;
import com.google.common.collect.Sets;
import com.google.common.eventbus.Subscribe;
import com.google.inject.Provides;
import java.awt.Color;
import java.util.Collection;
import javax.inject.Inject;
import org.apache.commons.lang3.ArrayUtils;
import net.runelite.api.Client;
import static net.runelite.api.MenuAction.FOLLOW;
import static net.runelite.api.MenuAction.ITEM_USE_ON_PLAYER;
import static net.runelite.api.MenuAction.PLAYER_EIGTH_OPTION;
import static net.runelite.api.MenuAction.PLAYER_FIFTH_OPTION;
import static net.runelite.api.MenuAction.PLAYER_FIRST_OPTION;
import static net.runelite.api.MenuAction.PLAYER_FOURTH_OPTION;
import static net.runelite.api.MenuAction.PLAYER_SECOND_OPTION;
import static net.runelite.api.MenuAction.PLAYER_SEVENTH_OPTION;
import static net.runelite.api.MenuAction.PLAYER_SIXTH_OPTION;
import static net.runelite.api.MenuAction.PLAYER_THIRD_OPTION;
import static net.runelite.api.MenuAction.SPELL_CAST_ON_PLAYER;
import static net.runelite.api.MenuAction.TRADE;
import net.runelite.api.MenuEntry;
import net.runelite.api.Player;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "War calling indicators",
description = "War War War.",
tags = {"skill", "total", "max", "PVP"},
type = "PVP",
enabledByDefault = false
)
public class WarIndicatorPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private WarIndicatorConfig config;
@Inject
private WarIndicatorOverlay warIndicatorOverlay;
@Inject
private WarIndicatorMiniMapOverlay warIndicatorMiniMapOverlay;
@Inject
private Client client;
@Provides
WarIndicatorConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(WarIndicatorConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(warIndicatorOverlay);
overlayManager.add(warIndicatorMiniMapOverlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(warIndicatorOverlay);
overlayManager.remove(warIndicatorMiniMapOverlay);
}
@Subscribe
public void onMenuEntryAdd(MenuEntryAdded menuEntryAdded)
{
int type = menuEntryAdded.getType();
if (type >= 2000)
{
type -= 2000;
}
int identifier = menuEntryAdded.getIdentifier();
if (type == FOLLOW.getId() || type == TRADE.getId()
|| type == SPELL_CAST_ON_PLAYER.getId()
|| type == ITEM_USE_ON_PLAYER.getId()
|| type == PLAYER_FIRST_OPTION.getId()
|| type == PLAYER_SECOND_OPTION.getId()
|| type == PLAYER_THIRD_OPTION.getId()
|| type == PLAYER_FOURTH_OPTION.getId()
|| type == PLAYER_FIFTH_OPTION.getId()
|| type == PLAYER_SIXTH_OPTION.getId()
|| type == PLAYER_SEVENTH_OPTION.getId()
|| type == PLAYER_EIGTH_OPTION.getId())
{
Player[] players = client.getCachedPlayers();
Player player = null;
String player2 = null;
String[] callers = config.getActiveCallers().split(", ");
String[] targets = config.getTargetedSnipes().split(", ");
if (identifier >= 0 && identifier < players.length)
{
player = players[identifier];
player2 = players[identifier].getName();
}
if (player == null)
{
return;
}
Color color = null;
if (config.highLightCallers() && ArrayUtils.contains(callers, player2))
{
color = config.getCallerColor();
}
if (config.highlightSnipes() && ArrayUtils.contains(targets, player2))
{
color = config.getSnipeColor();
}
if (color != null)
{
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry lastEntry = menuEntries[menuEntries.length - 1];
String target = lastEntry.getTarget();
int idx = target.indexOf('>');
if (idx != -1)
{
target = target.substring(idx + 1);
}
lastEntry.setTarget("<col=" + Integer.toHexString(color.getRGB() & 0xFFFFFF) + ">" + target);
client.setMenuEntries(menuEntries);
}
}
}
}

View File

@@ -0,0 +1,106 @@
/*
* Copyright (c) 2018, Andrew EP | ElPinche256 <https://github.com/ElPinche256>
* 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.warindicators;
import net.runelite.api.Client;
import net.runelite.api.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.awt.*;
import java.util.function.BiConsumer;
@Singleton
public class WarIndicatorService
{
private final Client client;
private final WarIndicatorConfig config;
@Inject
private WarIndicatorService(Client client, WarIndicatorConfig config)
{
this.config = config;
this.client = client;
}
public void forEachPlayer(final BiConsumer<Player, Color> consumer)
{
if (!config.highlightSnipes() && !config.highLightCallers())
{
return;
}
if (config.highlightSnipes())
{
for (Player player : client.getPlayers())
{
if (player == null || player.getName() == null)
{
continue;
}
String[] targets = config.getTargetedSnipes().split(", ");
if (targets == null)
{
return;
}
for (int i = 0; i < targets.length; i++)
{
if (player.getName().equalsIgnoreCase(targets[i]))
{
consumer.accept(player, config.getSnipeColor());
}
}
}
}
if (config.highLightCallers())
{
for (Player player : client.getPlayers())
{
if (player == null || player.getName() == null)
{
continue;
}
String[] callers = config.getActiveCallers().split(", ");
if (callers == null)
{
return;
}
for (int i = 0; i < callers.length; i++)
{
if (player.getName().equalsIgnoreCase(callers[i]))
{
consumer.accept(player, config.getCallerColor());
}
}
}
}
}
}