Pile Indicators plugin (#452)

* Pile Indicators plugin

Ability to highlight players, NPCS, and both that are stacked on each other. (PvP, chinning, etc.)

https://gyazo.com/8461d5188887a476aede1e4471ed7366

* Number only render, and fixed up some method names

* Update PileIndicatorsOverlay.java

checkstyle fix
This commit is contained in:
vanni
2019-05-31 04:17:10 -04:00
committed by Kyleeld
parent 1299e8769d
commit fde38f0126
4 changed files with 445 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.pileindicators;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Range;
import java.awt.*;
@ConfigGroup("pileindicators")
public interface PileIndicatorsConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "enablePlayers",
name = "Enable Player Piling",
description = "Enable the option to highlight players when they pile.",
group = "1. Player Piles"
)
default boolean enablePlayers()
{
return true;
}
@ConfigItem(
position = 1,
keyName = "wildyOnlyPlayer",
name = "Wilderness Only",
description = "Show player piling only when in the Wilderness.",
group = "1. Player Piles"
)
default boolean wildyOnlyPlayer()
{
return true;
}
@ConfigItem(
position = 3,
keyName = "enableNPCS",
name = "Enable NPC Piling",
description = "Enable the option to highlight NPCs when they pile.",
group = "2. NPC Piles"
)
default boolean enableNPCS()
{
return false;
}
@ConfigItem(
position = 2,
keyName = "playerPileColor",
name = "Player Pile Color",
description = "Color used for player piles.",
group = "1. Player Piles"
)
default Color playerPileColor()
{
return Color.RED;
}
@ConfigItem(
position = 4,
keyName = "npcPileColor",
name = "NPC Pile Color",
description = "Color used for NPC piles.",
group = "2. NPC Piles"
)
default Color npcPileColor()
{
return Color.BLUE;
}
@ConfigItem(
position = 5,
keyName = "mixedPileColor",
name = "Mixed Pile Color",
description = "Color used for mixed piles.",
group = "3. Mixed Piles"
)
default Color mixedPileColor()
{
return new Color(255, 0, 255);
}
@Range(
min = 2
)
@ConfigItem(
position = 6,
keyName = "minimumPileSize",
name = "Minimum Pile Size",
description = "Any pile under this size will not show up. (Minimum: 2)",
group = "4. Pile Size"
)
default int minimumPileSize()
{
return 2;
}
@ConfigItem(
position = 7,
keyName = "numberOnly",
name = "Display Number Only",
description = "Shorten \"PILE SIZE: 1\" to \"1\"",
group = "5. Miscellaneous"
)
default boolean numberOnly()
{
return false;
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.pileindicators;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.*;
import javax.inject.Inject;
import java.awt.*;
import java.util.ArrayList;
public class PileIndicatorsOverlay extends Overlay
{
private final Client client;
private final PileIndicatorsPlugin plugin;
private final PileIndicatorsConfig config;
@Inject
PileIndicatorsOverlay(final Client client, final PileIndicatorsPlugin plugin, final PileIndicatorsConfig config)
{
super(plugin);
this.client = client;
this.plugin = plugin;
this.config = config;
setLayer(OverlayLayer.ABOVE_SCENE);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
ArrayList<ArrayList<Actor>> stackList = plugin.getStacks();
if (stackList != null)
{
for (ArrayList<Actor> actorArrayList : stackList)
{
PileType pileType = plugin.getPileType(actorArrayList);
Color pileColor = plugin.getColorByPileType(pileType);
try
{
Actor actorToRender = actorArrayList.get(0); //guaranteed to have at least two players
final String text;
if (config.numberOnly())
{
text = "" + actorArrayList.size();
}
else
{
text = "PILE SIZE: " + actorArrayList.size();
}
OverlayUtil.renderPolygon(graphics, actorToRender.getCanvasTilePoly(), pileColor);
OverlayUtil.renderTextLocation(graphics, actorToRender.getCanvasTextLocation(graphics, text, 40), text, pileColor);
}
catch (Exception ignored)
{
}
}
}
return null;
}
}

View File

@@ -0,0 +1,186 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.pileindicators;
import com.google.inject.Binder;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.*;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import net.runelite.client.ui.overlay.OverlayManager;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.awt.*;
import java.util.ArrayList;
@Singleton
@Slf4j
@PluginDescriptor(
name = "Pile Indicators",
description = "Highlight and count how many npcs/players are stacked on each other.",
tags = {"overlay", "pile", "stack", "pvp", "pvm", "pve"},
enabledByDefault = false,
type = PluginType.UTILITY
)
public class PileIndicatorsPlugin extends Plugin
{
@Inject
private Client client;
@Inject
private PileIndicatorsConfig config;
@Inject
private OverlayManager overlayManager;
@Inject
private PileIndicatorsOverlay overlay;
@Provides
PileIndicatorsConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(PileIndicatorsConfig.class);
}
@Override
public void configure(Binder binder)
{
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
}
protected ArrayList<ArrayList<Actor>> getStacks()
{
ArrayList<ArrayList<Actor>> outerArrayList = new ArrayList<>();
ArrayList<Actor> pileList = new ArrayList<>();
if (config.enableNPCS())
{
for (NPC npc : client.getNpcs())
{
if (npc != null)
{
pileList.add(npc);
}
}
}
if (config.enablePlayers())
{
if ((client.getVar(Varbits.IN_WILDERNESS) > 0 && config.wildyOnlyPlayer()) ^ (!config.wildyOnlyPlayer()))
{
for (Player player : client.getPlayers())
{
if (player != null)
{
pileList.add(player);
}
}
}
}
if (pileList.size() == 0)
{
return null;
}
for (Actor actor : pileList)
{
ArrayList<Actor> potentialStackArrayList = new ArrayList<>();
for (Actor actorToCompareTo : pileList)
{
if (!potentialStackArrayList.contains(actorToCompareTo))
{
if (actor.getWorldLocation().distanceTo(actorToCompareTo.getWorldLocation()) == 0)
{
potentialStackArrayList.add(actorToCompareTo);
}
}
}
if (potentialStackArrayList.size() >= config.minimumPileSize())
{
outerArrayList.add(potentialStackArrayList);
}
}
return outerArrayList.size() != 0 ? outerArrayList : null;
}
protected Color getColorByPileType(PileType pileType)
{
switch (pileType)
{
case PLAYER_PILE:
return config.playerPileColor();
case NPC_PILE:
return config.npcPileColor();
case MIXED_PILE:
return config.mixedPileColor();
}
return null;
}
protected PileType getPileType(ArrayList<Actor> pile)
{
PileType pileType = null;
for (Actor actor : pile)
{
if (actor instanceof NPC && pileType == null)
{
pileType = PileType.NPC_PILE;
}
if (actor instanceof Player && pileType == null)
{
pileType = PileType.PLAYER_PILE;
}
if (actor instanceof Player && pileType == PileType.NPC_PILE)
{
pileType = PileType.MIXED_PILE;
}
if (actor instanceof NPC && pileType == PileType.PLAYER_PILE)
{
pileType = PileType.MIXED_PILE;
}
}
return pileType;
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
* 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.pileindicators;
public enum PileType
{
PLAYER_PILE,
NPC_PILE,
MIXED_PILE
}