Plugins update (#7)

* Added plugins

* Added missing API

* Error fix
This commit is contained in:
James
2019-04-18 20:26:41 -07:00
committed by Tyler Bochard
parent bfe1482705
commit 216f7d94d1
277 changed files with 31789 additions and 858 deletions

View File

@@ -24,9 +24,14 @@
*/
package net.runelite.client.plugins.antidrag;
import java.awt.Color;
import java.awt.event.KeyEvent;
import net.runelite.client.config.Alpha;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Keybind;
import net.runelite.client.config.ModifierlessKeybind;
@ConfigGroup("antiDrag")
public interface AntiDragConfig extends Config
@@ -41,4 +46,49 @@ public interface AntiDragConfig extends Config
{
return 600 / 20; // one game tick
}
@ConfigItem(
keyName = "keybind",
name = "keybind",
description = "The keybind you want to use for antidrag",
position = 2
)
default Keybind key()
{
return new ModifierlessKeybind(KeyEvent.VK_SHIFT, 0);
}
@ConfigItem(
keyName = "reqfocus",
name = "Reset on focus loss",
description = "Disable antidrag when losing focus (like alt tabbing)",
position = 3
)
default boolean reqfocus()
{
return false;
}
@ConfigItem(
keyName = "overlay",
name = "Enable overlay",
description = "Do you really need a description?",
position = 4
)
default boolean overlay()
{
return true;
}
@Alpha
@ConfigItem(
keyName = "color",
name = "Overlay color",
description = "Change the overlay color, duh",
position = 5
)
default Color color()
{
return new Color(255, 0, 0, 30);
}
}

View File

@@ -0,0 +1,47 @@
package net.runelite.client.plugins.antidrag;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import net.runelite.api.Client;
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;
@Singleton
public class AntiDragOverlay extends Overlay
{
private static final int RADIUS = 20;
private Client client;
private AntiDragConfig config;
@Inject
private AntiDragOverlay(Client client, AntiDragConfig config)
{
this.config = config;
this.client = client;
setPosition(OverlayPosition.TOOLTIP);
setPriority(OverlayPriority.HIGHEST);
setLayer(OverlayLayer.ALWAYS_ON_TOP);
}
@Override
public Dimension render(Graphics2D g)
{
final Color color = config.color();
g.setColor(color);
final net.runelite.api.Point mouseCanvasPosition = client.getMouseCanvasPosition();
final Point mousePosition = new Point(mouseCanvasPosition.getX() - RADIUS, mouseCanvasPosition.getY() - RADIUS);
final Rectangle bounds = new Rectangle(mousePosition.x, mousePosition.y, 2 * RADIUS, 2 * RADIUS);
g.fillOval(bounds.x, bounds.y, bounds.height, bounds.width);
return bounds.getSize();
}
}

View File

@@ -25,25 +25,26 @@
package net.runelite.client.plugins.antidrag;
import com.google.inject.Provides;
import java.awt.event.KeyEvent;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.events.FocusChanged;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.HotkeyListener;
@PluginDescriptor(
name = "Shift Anti Drag",
description = "Prevent dragging an item for a specified delay",
tags = {"antidrag", "delay", "inventory", "items"}
)
public class AntiDragPlugin extends Plugin implements KeyListener
public class AntiDragPlugin extends Plugin
{
private static final int DEFAULT_DELAY = 5;
private boolean toggleDrag;
@Inject
private Client client;
@@ -51,6 +52,12 @@ public class AntiDragPlugin extends Plugin implements KeyListener
@Inject
private AntiDragConfig config;
@Inject
private AntiDragOverlay overlay;
@Inject
private OverlayManager overlayManager;
@Inject
private KeyManager keyManager;
@@ -63,46 +70,50 @@ public class AntiDragPlugin extends Plugin implements KeyListener
@Override
protected void startUp() throws Exception
{
keyManager.registerKeyListener(this);
keyManager.registerKeyListener(hotkeyListener);
toggleDrag = false;
}
@Override
protected void shutDown() throws Exception
{
client.setInventoryDragDelay(DEFAULT_DELAY);
keyManager.unregisterKeyListener(this);
keyManager.unregisterKeyListener(hotkeyListener);
toggleDrag = false;
overlayManager.remove(overlay);
}
@Override
public void keyTyped(KeyEvent e)
private final HotkeyListener hotkeyListener = new HotkeyListener(() -> config.key())
{
}
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
@Override
public void hotkeyPressed()
{
client.setInventoryDragDelay(config.dragDelay());
}
}
toggleDrag = !toggleDrag;
if (toggleDrag)
{
if (config.overlay())
{
overlayManager.add(overlay);
}
@Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
{
client.setInventoryDragDelay(DEFAULT_DELAY);
client.setInventoryDragDelay(config.dragDelay());
}
else
{
overlayManager.remove(overlay);
client.setInventoryDragDelay(DEFAULT_DELAY);
}
}
}
};
@Subscribe
public void onFocusChanged(FocusChanged focusChanged)
{
if (!focusChanged.isFocused())
if (!focusChanged.isFocused() && config.reqfocus())
{
client.setInventoryDragDelay(DEFAULT_DELAY);
overlayManager.remove(overlay);
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.aoewarnings;
import net.runelite.api.coords.LocalPoint;
import java.time.Instant;
public class AoeProjectile
{
private final Instant startTime;
private final LocalPoint targetPoint;
private final AoeProjectileInfo aoeProjectileInfo;
public AoeProjectile(Instant startTime, LocalPoint targetPoint, AoeProjectileInfo aoeProjectileInfo)
{
this.startTime = startTime;
this.targetPoint = targetPoint;
this.aoeProjectileInfo = aoeProjectileInfo;
}
public Instant getStartTime()
{
return startTime;
}
public LocalPoint getTargetPoint()
{
return targetPoint;
}
public AoeProjectileInfo getAoeProjectileInfo()
{
return aoeProjectileInfo;
}
}

View File

@@ -0,0 +1,128 @@
package net.runelite.client.plugins.aoewarnings;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import net.runelite.api.ProjectileID;
public enum AoeProjectileInfo
{
LIZARDMAN_SHAMAN_AOE(ProjectileID.LIZARDMAN_SHAMAN_AOE, 3000, 3),
CRAZY_ARCHAEOLOGIST_AOE(ProjectileID.CRAZY_ARCHAEOLOGIST_AOE, 3000, 3),
ICE_DEMON_RANGED_AOE(ProjectileID.ICE_DEMON_RANGED_AOE, 3000, 3),
/**
* When you don't have pray range on ice demon does an ice barrage
*/
ICE_DEMON_ICE_BARRAGE_AOE(ProjectileID.ICE_DEMON_ICE_BARRAGE_AOE, 3000, 3),
/**
* The AOE when vasa first starts
*/
VASA_AWAKEN_AOE(ProjectileID.VASA_AWAKEN_AOE, 4500, 3),
VASA_RANGED_AOE(ProjectileID.VASA_RANGED_AOE, 3000, 3),
TEKTON_METEOR_AOE(ProjectileID.TEKTON_METEOR_AOE, 4000, 3),
/**
* The AOEs of Vorkath
*/
VORKATH_BOMB(ProjectileID.VORKATH_BOMB_AOE, 2400, 3),
VORKATH_POISON_POOL(ProjectileID.VORKATH_POISON_POOL_AOE, 1800, 1),
VORKATH_SPAWN(ProjectileID.VORKATH_SPAWN_AOE, 3000, 1), //extra tick because hard to see otherwise
VORKATH_TICK_FIRE(ProjectileID.VORKATH_TICK_FIRE_AOE, 600, 1),
/**
* the AOEs of Galvek
*/
GALVEK_MINE(ProjectileID.GALVEK_MINE, 3600, 3),
GALVEK_BOMB(ProjectileID.GALVEK_BOMB, 2400, 3),
DAWN_FREEZE(ProjectileID.DAWN_FREEZE, 3000, 3),
DUSK_CEILING(ProjectileID.DUSK_CEILING, 3000, 3),
/**
* the AOE of Vet'ion
*/
VETION_LIGHTNING(ProjectileID.VETION_LIGHTNING, 3000, 1),
/**
* the AOE of Chaos Fanatic
*/
CHAOS_FANATIC(ProjectileID.CHAOS_FANATIC_AOE, 3000, 1),
/**
* the AOE of the Corporeal Beast
*/
CORPOREAL_BEAST(ProjectileID.CORPOREAL_BEAST_AOE, 3000, 1),
CORPOREAL_BEAST_DARK_CORE(ProjectileID.CORPOREAL_BEAST_DARK_CORE_AOE, 3000, 3),
/**
* the AOEs of The Great Olm
* missing ids and length, please help
*/
OLM_FALLING_CRYSTAL(1357, 3000, 3),
OLM_BURNING(1349, 2400, 1),
OLM_FALLING_CRYSTAL_TRAIL(1352, 2400, 1),
OLM_ACID_TRAIL(1354, 2400, 1),
OLM_FIRE_LINE(1347, 2400, 1),
/**
* the AOE of the Wintertodt snow that falls
*/
WINTERTODT_SNOW_FALL(1310, 4000, 3);
/**
* The id of the projectile to trigger this AoE warning
*/
private final int id;
/**
* How long the indicator should last for this AoE warning This might
* need to be a bit longer than the projectile actually takes to land as
* there is a fade effect on the warning
*/
private final Duration lifeTime;
/**
* The size of the splash radius of the AoE warning Ex. Lizardman shaman
* AoE is a 3x3, so aoeSize = 3
*/
private final int aoeSize;
private static final Map<Integer, AoeProjectileInfo> map = new HashMap<>();
static
{
for (AoeProjectileInfo aoe : values())
{
map.put(aoe.id, aoe);
}
}
AoeProjectileInfo(int id, int lifeTimeMillis, int aoeSize)
{
this.id = id;
this.lifeTime = Duration.ofMillis(lifeTimeMillis);
this.aoeSize = aoeSize;
}
public Duration getLifeTime()
{
return lifeTime;
}
public int getId()
{
return id;
}
public int getAoeSize()
{
return aoeSize;
}
public static AoeProjectileInfo getById(int id)
{
return map.get(id);
}
}

View File

@@ -0,0 +1,213 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.aoewarnings;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("aoe")
public interface AoeWarningConfig extends Config
{
@ConfigItem(
keyName = "enabled",
name = "AoE Warnings Enabled",
description = "Configures whether or not AoE Projectile Warnings plugin is displayed"
)
default boolean enabled()
{
return true;
}
@ConfigItem(
keyName = "lizardmanaoe",
name = "Lizardman Shamans",
description = "Configures whether or not AoE Projectile Warnings for Lizardman Shamans is displayed"
)
default boolean isShamansEnabled()
{
return true;
}
@ConfigItem(
keyName = "archaeologistaoe",
name = "Crazy Archaeologist",
description = "Configures whether or not AoE Projectile Warnings for Archaeologist is displayed"
)
default boolean isArchaeologistEnabled()
{
return true;
}
@ConfigItem(
keyName = "icedemon",
name = "Ice Demon",
description = "Configures whether or not AoE Projectile Warnings for Ice Demon is displayed"
)
default boolean isIceDemonEnabled()
{
return true;
}
@ConfigItem(
keyName = "vasa",
name = "Vasa",
description = "Configures whether or not AoE Projectile Warnings for Vasa is displayed"
)
default boolean isVasaEnabled()
{
return true;
}
@ConfigItem(
keyName = "tekton",
name = "Tekton",
description = "Configures whether or not AoE Projectile Warnings for Tekton is displayed"
)
default boolean isTektonEnabled()
{
return true;
}
@ConfigItem(
keyName = "vorkath",
name = "Vorkath",
description = "Configures whether or not AoE Projectile Warnings for Vorkath are displayed"
)
default boolean isVorkathEnabled()
{
return true;
}
@ConfigItem(
keyName = "galvek",
name = "Galvek",
description = "Configures whether or not AoE Projectile Warnings for Galvek are displayed"
)
default boolean isGalvekEnabled()
{
return true;
}
@ConfigItem(
keyName = "gargboss",
name = "Gargoyle Boss",
description = "Configs whether or not AoE Projectile Warnings for Dawn/Dusk are displayed"
)
default boolean isGargBossEnabled()
{
return true;
}
@ConfigItem(
keyName = "vetion",
name = "Vet'ion",
description = "Configures whether or not AoE Projectile Warnings for Vet'ion are displayed"
)
default boolean isVetionEnabled()
{
return true;
}
@ConfigItem(
keyName = "chaosfanatic",
name = "Chaos Fanatic",
description = "Configures whether or not AoE Projectile Warnings for Chaos Fanatic are displayed"
)
default boolean isChaosFanaticEnabled()
{
return true;
}
@ConfigItem(
keyName = "olm",
name = "Great Olm",
description = "Configures whether or not AoE Projectile Warnings for The Great Olm are displayed"
)
default boolean isOlmEnabled()
{
return true;
}
@ConfigItem(
keyName = "bombDisplay",
name = "Display crystal phase bomb tracker",
description = "Display a timer and colour-coded AoE for Olm's crystal-phase bombs."
)
default boolean bombDisplay()
{
return true;
}
@ConfigItem(
keyName = "corp",
name = "Corporeal Beast",
description = "Configures whether or not AoE Projectile Warnings for the Corporeal Beast are displayed"
)
default boolean isCorpEnabled()
{
return true;
}
@ConfigItem(
keyName = "wintertodt",
name = "Wintertodt Snow Fall",
description = "Configures whether or not AOE Projectile Warnings for the Wintertodt snow fall are displayed"
)
default boolean isWintertodtEnabled()
{
return true;
}
@ConfigItem(
keyName = "outline",
name = "Display Outline",
description = "Configures whether or not AoE Projectile Warnings have an outline"
)
default boolean isOutlineEnabled()
{
return true;
}
@ConfigItem(
keyName = "lightning",
name = "Show Lightning Trails",
description = "Show Lightning Trails"
)
default boolean LightningTrail()
{
return true;
}
@ConfigItem(
keyName = "fade",
name = "Fade Warnings",
description = "Configures whether or not AoE Projectile Warnings fade over time"
)
default boolean isFadeEnabled()
{
return true;
}
}

View File

@@ -0,0 +1,166 @@
/*
* Copyright (c) 2017, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.aoewarnings;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Projectile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import javax.annotation.Nullable;
import javax.inject.Inject;
import java.awt.*;
import java.time.Instant;
import java.util.Iterator;
import java.util.Map;
public class AoeWarningOverlay extends Overlay
{
private static final int FILL_START_ALPHA = 25;
private static final int OUTLINE_START_ALPHA = 255;
private final Client client;
private final AoeWarningPlugin plugin;
private final AoeWarningConfig config;
@Inject
public AoeWarningOverlay(@Nullable Client client, AoeWarningPlugin plugin, AoeWarningConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.UNDER_WIDGETS);
this.client = client;
this.plugin = plugin;
this.config = config;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.enabled())
{
return null;
}
for (WorldPoint point : plugin.getLightningTrail())
{
drawTile(graphics, point, new Color(0,150,200), 2, 150, 50);
}
for (WorldPoint point : plugin.getAcidTrail())
{
drawTile(graphics, point, new Color(69, 241, 44), 2, 150, 50);
}
for (WorldPoint point : plugin.getCrystalSpike())
{
drawTile(graphics, point, new Color(255, 0, 84), 2, 150, 50);
}
Instant now = Instant.now();
Map<Projectile, AoeProjectile> projectiles = plugin.getProjectiles();
for (Iterator<AoeProjectile> it = projectiles.values().iterator(); it.hasNext();)
{
AoeProjectile aoeProjectile = it.next();
if (now.isAfter(aoeProjectile.getStartTime().plus(aoeProjectile.getAoeProjectileInfo().getLifeTime())))
{
it.remove();
continue;
}
Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, aoeProjectile.getTargetPoint(), aoeProjectile.getAoeProjectileInfo().getAoeSize());
if (tilePoly == null)
{
continue;
}
// how far through the projectiles lifetime between 0-1.
double progress = (System.currentTimeMillis() - aoeProjectile.getStartTime().toEpochMilli()) / (double) aoeProjectile.getAoeProjectileInfo().getLifeTime().toMillis();
int fillAlpha, outlineAlpha;
if (config.isFadeEnabled())
{
fillAlpha = (int) ((1 - progress) * FILL_START_ALPHA);//alpha drop off over lifetime
outlineAlpha = (int) ((1 - progress) * OUTLINE_START_ALPHA);
}
else
{
fillAlpha = FILL_START_ALPHA;
outlineAlpha = OUTLINE_START_ALPHA;
}
if (fillAlpha < 0)
{
fillAlpha = 0;
}
if (outlineAlpha < 0)
{
outlineAlpha = 0;
}
if (fillAlpha > 255)
{
fillAlpha = 255;
}
if (outlineAlpha > 255)
{
outlineAlpha = 255;//Make sure we don't pass in an invalid alpha
}
if (config.isOutlineEnabled())
{
graphics.setColor(new Color(0, 150, 200, outlineAlpha));
graphics.drawPolygon(tilePoly);
}
graphics.setColor(new Color(0, 150, 200, fillAlpha));
graphics.fillPolygon(tilePoly);
}
return null;
}
private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha) {
WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
if (point.distanceTo(playerLocation) >= 32) {
return;
}
LocalPoint lp = LocalPoint.fromWorld(client, point);
if (lp == null) {
return;
}
Polygon poly = Perspective.getCanvasTilePoly(client, lp);
if (poly == null) {
return;
}
//OverlayUtil.renderPolygon(graphics, poly, color);
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha));
graphics.setStroke(new BasicStroke(strokeWidth));
graphics.draw(poly);
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
graphics.fill(poly);
}
}

View File

@@ -0,0 +1,307 @@
/*
* Copyright (c) 2018, Adam <Adam@sigterm.info>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.plugins.aoewarnings;
import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
import net.runelite.api.GraphicID;
import net.runelite.api.GraphicsObject;
import net.runelite.api.ObjectID;
import net.runelite.api.Projectile;
import net.runelite.api.Client;
import net.runelite.api.Tile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.GameObjectDespawned;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.GraphicsObjectCreated;
import net.runelite.api.events.ProjectileMoved;
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.ui.overlay.OverlayManager;
import javax.inject.Inject;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Logger;
@PluginDescriptor(
name = "<font color=\"green\">!AoE Warnings</font>",
description = "Shows the final destination for AoE Attack projectiles",
tags = {"bosses", "combat", "pve", "overlay"}
)
@Slf4j
public class AoeWarningPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private AoeWarningOverlay coreOverlay;
@Inject
public AoeWarningConfig config;
@Inject
private BombOverlay bombOverlay;
@Inject
private Client client;
@Inject
private Notifier notifier;
@Getter
private final Map<WorldPoint, CrystalBomb> bombs = new HashMap<>();
@Getter(AccessLevel.PACKAGE)
private List<WorldPoint> LightningTrail = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private List<WorldPoint> AcidTrail = new ArrayList<>();
@Getter(AccessLevel.PACKAGE)
private List<WorldPoint> CrystalSpike = new ArrayList<>();
@Provides
AoeWarningConfig getConfig(ConfigManager configManager)
{
return configManager.getConfig(AoeWarningConfig.class);
}
private final Map<Projectile, AoeProjectile> projectiles = new HashMap<>();
public Map<Projectile, AoeProjectile> getProjectiles()
{
return projectiles;
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(coreOverlay);
overlayManager.add(bombOverlay);
LightningTrail.clear();
AcidTrail.clear();
CrystalSpike.clear();
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(coreOverlay);
overlayManager.remove(bombOverlay);
}
@Subscribe
public void onProjectileMoved(ProjectileMoved event)
{
Projectile projectile = event.getProjectile();
int projectileId = projectile.getId();
AoeProjectileInfo aoeProjectileInfo = AoeProjectileInfo.getById(projectileId);
if (aoeProjectileInfo != null && isConfigEnabledForProjectileId(projectileId))
{
LocalPoint targetPoint = event.getPosition();
AoeProjectile aoeProjectile = new AoeProjectile(Instant.now(), targetPoint, aoeProjectileInfo);
projectiles.put(projectile, aoeProjectile);
}
}
@Subscribe
public void onGameObjectSpawned(GameObjectSpawned event)
{
final GameObject gameObject = event.getGameObject();
final WorldPoint bombLocation = gameObject.getWorldLocation();
switch (gameObject.getId())
{
case ObjectID.CRYSTAL_BOMB:
bombs.put(bombLocation, new CrystalBomb(gameObject, client.getTickCount()));
break;
case ObjectID.ACID_POOL:
AcidTrail.add(bombLocation);
break;
case ObjectID.SMALL_CRYSTALS:
//todo
CrystalSpike.add(bombLocation);
break;
}
}
@Subscribe
public void onGameObjectDespawned(GameObjectDespawned event)
{
GameObject gameObject = event.getGameObject();
WorldPoint bombLocation = gameObject.getWorldLocation();
switch (gameObject.getId())
{
case ObjectID.CRYSTAL_BOMB:
//might as well check the ObjectID to save some time.
purgeBombs(bombs);
break;
case ObjectID.ACID_POOL:
AcidTrail.remove(bombLocation);
break;
case ObjectID.SMALL_CRYSTALS:
//todo
CrystalSpike.remove(bombLocation);
break;
}
}
@Subscribe
public void onGameStateChanged(GameStateChanged delta)
{
if (client.getGameState() == GameState.LOGGED_IN)
{
purgeBombs(bombs);
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (config.LightningTrail())
{
LightningTrail.clear();
for (GraphicsObject o : client.getGraphicsObjects())
{
if (o.getId() == 1356)
{
LightningTrail.add(WorldPoint.fromLocal(client, o.getLocation()));
}
}
}
Iterator<Map.Entry<WorldPoint, CrystalBomb>> it = bombs.entrySet().iterator();
while (it.hasNext())
{
Map.Entry<WorldPoint, CrystalBomb> entry = it.next();
CrystalBomb bomb = entry.getValue();
bomb.bombClockUpdate();
//bombClockUpdate smooths the shown timer; not using this results in 1.2 --> .6 vs. 1.2 --> 1.1, etc.
}
}
private void purgeBombs(Map<WorldPoint, CrystalBomb> bombs)
{
Iterator<Map.Entry<WorldPoint, CrystalBomb>> it = bombs.entrySet().iterator();
Tile[][][] tiles = client.getScene().getTiles();
while (it.hasNext())
{
Map.Entry<WorldPoint, CrystalBomb> entry = it.next();
WorldPoint world = entry.getKey();
LocalPoint local = LocalPoint.fromWorld(client, world);
Tile tile = tiles[world.getPlane()][local.getSceneX()][local.getSceneY()];
GameObject[] objects = tile.getGameObjects();
boolean containsObjects = false;
for (GameObject object : objects)
{
if (object != null)
{
containsObjects = true;
}
}
if (!containsObjects)
{
it.remove();
}
}
}
private boolean isConfigEnabledForProjectileId(int projectileId)
{
AoeProjectileInfo projectileInfo = AoeProjectileInfo.getById(projectileId);
if (projectileInfo == null)
{
return false;
}
switch (projectileInfo)
{
case LIZARDMAN_SHAMAN_AOE:
return config.isShamansEnabled();
case CRAZY_ARCHAEOLOGIST_AOE:
return config.isArchaeologistEnabled();
case ICE_DEMON_RANGED_AOE:
case ICE_DEMON_ICE_BARRAGE_AOE:
return config.isIceDemonEnabled();
case VASA_AWAKEN_AOE:
case VASA_RANGED_AOE:
return config.isVasaEnabled();
case TEKTON_METEOR_AOE:
return config.isTektonEnabled();
case VORKATH_BOMB:
case VORKATH_POISON_POOL:
case VORKATH_SPAWN:
case VORKATH_TICK_FIRE:
return config.isVorkathEnabled();
case VETION_LIGHTNING:
return config.isVetionEnabled();
case CHAOS_FANATIC:
return config.isChaosFanaticEnabled();
case GALVEK_BOMB:
case GALVEK_MINE:
return config.isGalvekEnabled();
case DAWN_FREEZE:
case DUSK_CEILING:
return config.isGargBossEnabled();
case OLM_FALLING_CRYSTAL:
case OLM_BURNING:
case OLM_FALLING_CRYSTAL_TRAIL:
case OLM_ACID_TRAIL:
case OLM_FIRE_LINE:
return config.isOlmEnabled();
case CORPOREAL_BEAST:
case CORPOREAL_BEAST_DARK_CORE:
return config.isCorpEnabled();
case WINTERTODT_SNOW_FALL:
return config.isWintertodtEnabled();
}
return false;
}
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright (c) 2018, PallasDieKatze (Pallas Cat)
* 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.aoewarnings;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.plugins.aoewarnings.CrystalBomb;
import net.runelite.client.ui.overlay.*;
import javax.inject.Inject;
import java.awt.Graphics2D;
import java.awt.Dimension;
import java.awt.Color;
import java.awt.Polygon;
import java.awt.BasicStroke;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.Instant;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
@Slf4j
public class BombOverlay extends Overlay
{
private static final String SAFE = "#00cc00";
//safe
private static final String CAUTION = "#ffff00";
//1 tile in range (minor damage)
private static final String WARNING = "#ff9933";
//2 tiles in range (moderate damage)
private static final String DANGER = "#ff6600";
//3 tiles in range/adjacent to bomb (major damage)
private static final String LETHAL = "#cc0000";
//On the bomb, using it as a makeshift space launch vehicle. (massive damage)
private static final int BOMB_AOE = 7;
private static final int BOMB_DETONATE_TIME = 8;
//This is in ticks. It should be 10, but it varies from 8 to 11.
private static final double ESTIMATED_TICK_LENGTH = .6;
//Thank you Woox & co. for this assumption. .6 seconds/tick.
//Utilized from the npc highlight code for formatting text being displayed on the client canvas.
private static final NumberFormat TIME_LEFT_FORMATTER =
DecimalFormat.getInstance(Locale.US);
static
{
((DecimalFormat) TIME_LEFT_FORMATTER).applyPattern("#0.0");
}
private final Client client;
private final AoeWarningConfig config;
private final AoeWarningPlugin plugin;
@Inject
public BombOverlay(Client client, AoeWarningPlugin plugin, AoeWarningConfig config)
{
this.client = client;
this.plugin = plugin;
this.config = config;
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (config.bombDisplay())
{
drawBombs(graphics);
}
return null;
}
private void drawBombs(Graphics2D graphics)
//I can condense drawDangerZone into this. Ambivalent though.
{
Iterator<Map.Entry<WorldPoint, CrystalBomb>> it = plugin.getBombs().entrySet().iterator();
while (it.hasNext())
{
Map.Entry<WorldPoint, CrystalBomb> entry = it.next();
CrystalBomb bomb = entry.getValue();
drawDangerZone(graphics, bomb);
}
}
private void drawDangerZone(Graphics2D graphics, CrystalBomb bomb)
{
final Player localPlayer = client.getLocalPlayer();
LocalPoint localLoc = LocalPoint.fromWorld(client, bomb.getWorldLocation());
double distance_x = Math.abs(bomb.getWorldLocation().getX() - localPlayer.getWorldLocation().getX());
double distance_y = Math.abs(bomb.getWorldLocation().getY() - localPlayer.getWorldLocation().getY());
Color color_code = Color.decode(SAFE);
//defaults to this unless conditionals met below.
if (distance_x < 1 && distance_y < 1)
{
color_code = Color.decode(LETHAL);
}
else if (distance_x < 2 && distance_y < 2)
{
color_code = Color.decode(DANGER);
}
else if (distance_x < 3 && distance_y < 3)
{
color_code = Color.decode(WARNING);
}
else if (distance_x < 4 && distance_y < 4)
{
color_code = Color.decode(CAUTION);
}
LocalPoint CenterPoint = new LocalPoint(localLoc.getX() + 0, localLoc.getY() + 0);
Polygon poly = Perspective.getCanvasTileAreaPoly(client, CenterPoint, BOMB_AOE);
if (poly != null)
{
//manually generating the polygon so as to assign a custom alpha value. Request adtl' arg for alpha maybe?
graphics.setColor(color_code);
graphics.setStroke(new BasicStroke(1));
graphics.drawPolygon(poly);
graphics.setColor(new Color(0, 0, 0, 10));
graphics.fillPolygon(poly);
}
Instant now = Instant.now();
double timeLeft = ((BOMB_DETONATE_TIME - (client.getTickCount() -
bomb.getTickStarted())) * ESTIMATED_TICK_LENGTH) -
(now.toEpochMilli() - bomb.getLastClockUpdate().toEpochMilli()) / 1000.0;
//divided by 1000.00 because of milliseconds :)
timeLeft = Math.max(0.0, timeLeft);
String bombTimerString = TIME_LEFT_FORMATTER.format(timeLeft);
int textWidth = graphics.getFontMetrics().stringWidth(bombTimerString);
int textHeight = graphics.getFontMetrics().getAscent();
Point canvasPoint = Perspective.localToCanvas(client, localLoc.getX(),
localLoc.getY(), bomb.getWorldLocation().getPlane());
if (canvasPoint != null)
{
Point canvasCenterPoint = new Point(
canvasPoint.getX() - textWidth / 2,
canvasPoint.getY() + textHeight / 2);
OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, bombTimerString, color_code);
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 2018, PallasDieKatze (Pallas Cat)
* 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.aoewarnings;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.GameObject;
import net.runelite.api.coords.WorldPoint;
import java.time.Instant;
@Slf4j
public class CrystalBomb
{
@Getter
private Instant plantedOn;
@Getter
private Instant lastClockUpdate;
@Getter
private int objectId;
@Getter
private int tickStarted;
//
@Getter
private WorldPoint worldLocation;
public CrystalBomb(GameObject gameObject, int startTick)
{
this.plantedOn = Instant.now();
this.objectId = gameObject.getId();
this.worldLocation = gameObject.getWorldLocation();
this.tickStarted = startTick;
}
public void bombClockUpdate()
{
lastClockUpdate = Instant.now();
}
}

View File

@@ -37,17 +37,53 @@ public interface BarbarianAssaultConfig extends Config
name = "Show call change timer",
description = "Show time to next call change"
)
default boolean showTimer()
{
return true;
}
default boolean showTimer() { return true; }
@ConfigItem(
keyName = "waveTimes",
name = "Show wave and game duration",
description = "Displays wave and game duration"
)
default boolean waveTimes() { return true; }
@ConfigItem(
keyName = "showEggCountMessage",
name = "Show count of eggs collected as collector.",
description = "Display egg count as collector after each wave",
position = 0
)
default boolean showEggCount() { return false; }
@ConfigItem(
keyName = "showEggCountOverlay",
name = "Overlay of eggs counted",
description = "Display current egg count as collector",
position = 1
)
default boolean showEggCountOverlay() { return false; }
@ConfigItem(
keyName = "showHpCountMessage",
name = "Show count of Hp healed as healer.",
description = "Display healed count as healer after each wave",
position = 2
)
default boolean showHpCount() { return false; }
@ConfigItem(
keyName = "showHpCountOverlay",
name = "Overlay of Hp counted",
description = "Display current healed count as healer",
position = 3
)
default boolean showHpCountOverlay() { return false; }
@ConfigItem(
keyName = "highlightCollectorEggs",
name = "Highlight collector eggs",
description = "Highlight called egg colors"
)
default boolean waveTimes()
default boolean highlightCollectorEggs()
{
return true;
}

View File

@@ -24,24 +24,37 @@
*/
package net.runelite.client.plugins.barbarianassault;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.util.Map;
import javax.inject.Inject;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.widgets.Widget;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayUtil;
class BarbarianAssaultOverlay extends Overlay
{
private static final int MAX_EGG_DISTANCE = 2500;
private final Client client;
private final BarbarianAssaultPlugin plugin;
private final BarbarianAssaultConfig config;
@@ -82,12 +95,95 @@ class BarbarianAssaultOverlay extends Overlay
if (config.showTimer() && roleText != null && roleSprite != null)
{
roleText.setText(String.format("00:%02d", currentRound.getTimeToChange()));
if (config.showEggCountOverlay() && role.equals(Role.COLLECTOR))
{
roleText.setText(String.format("(%d) 00:%02d", plugin.getCollectedEggCount(), currentRound.getTimeToChange()));
}
else if (config.showHpCountOverlay() && role.equals(Role.HEALER))
{
roleText.setText(String.format("(%d) 00:%02d", plugin.getHpHealed(), currentRound.getTimeToChange()));
}
else
{
roleText.setText(String.format("00:%02d", currentRound.getTimeToChange()));
}
Rectangle spriteBounds = roleSprite.getBounds();
roleSprite.setHidden(true);
graphics.drawImage(plugin.getClockImage(), spriteBounds.x, spriteBounds.y, null);
}
if (role == Role.COLLECTOR && config.highlightCollectorEggs())
{
String heardCall = plugin.getCollectorHeardCall();
Color highlightColor;
Map<WorldPoint, Integer> calledEggMap;
Map<WorldPoint, Integer> yellowEggMap = plugin.getYellowEggs();
switch (heardCall)
{
case "Red eggs":
calledEggMap = plugin.getRedEggs();
highlightColor = Color.RED;
break;
case "Green eggs":
calledEggMap = plugin.getGreenEggs();
highlightColor = Color.GREEN;
break;
case "Blue eggs":
calledEggMap = plugin.getBlueEggs();
highlightColor = Color.BLUE;
break;
default:
calledEggMap = null;
highlightColor = null;
}
if (calledEggMap != null)
{
for (WorldPoint worldPoint : calledEggMap.keySet())
{
int quantity = calledEggMap.get(worldPoint);
renderEggLocation(graphics, worldPoint, quantity, highlightColor);
}
}
// Always show yellow eggs
for (WorldPoint worldPoint : yellowEggMap.keySet())
{
int quantity = yellowEggMap.get(worldPoint);
renderEggLocation(graphics, worldPoint, quantity, highlightColor);
}
}
return null;
}
private void renderEggLocation(Graphics2D graphics, WorldPoint location, int quantity, Color color)
{
LocalPoint groundPoint = LocalPoint.fromWorld(client, location);
Player player = client.getLocalPlayer();
if (groundPoint == null || player == null)
{
return;
}
if (player.getLocalLocation().distanceTo(groundPoint) > MAX_EGG_DISTANCE)
{
return;
}
Polygon poly = Perspective.getCanvasTilePoly(client, groundPoint);
final Stroke originalStroke = graphics.getStroke();
graphics.setColor(color);
graphics.setStroke(new BasicStroke(2));
graphics.drawPolygon(poly);
graphics.setStroke(originalStroke);
String quantityText = "x" + quantity;
Point textPoint = Perspective.getCanvasTextLocation(client, graphics, groundPoint, quantityText, 0);
OverlayUtil.renderTextLocation(graphics, textPoint, quantityText, Color.WHITE);
}
}

View File

@@ -28,13 +28,23 @@ package net.runelite.client.plugins.barbarianassault;
import com.google.inject.Provides;
import java.awt.Font;
import java.awt.Image;
import java.util.HashMap;
import javax.inject.Inject;
import lombok.Getter;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.ItemID;
import net.runelite.api.Player;
import net.runelite.api.Tile;
import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.ItemDespawned;
import net.runelite.api.events.ItemDespawned;
import net.runelite.api.events.ItemSpawned;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.events.WidgetLoaded;
import net.runelite.api.kit.KitType;
@@ -58,18 +68,38 @@ import net.runelite.client.util.ImageUtil;
description = "Show a timer to the next call change and game/wave duration in chat.",
tags = {"minigame", "overlay", "timer"}
)
public class BarbarianAssaultPlugin extends Plugin
{
public class BarbarianAssaultPlugin extends Plugin {
private static final int BA_WAVE_NUM_INDEX = 2;
private static final String START_WAVE = "1";
private static final String ENDGAME_REWARD_NEEDLE_TEXT = "<br>5";
@Getter
private int collectedEggCount = 0;
@Getter
private int HpHealed = 0;
@Getter
private int totalCollectedEggCount = 0;
@Getter
private int totalHpHealed = 0;
private Font font;
private Image clockImage;
private int inGameBit = 0;
private String currentWave = START_WAVE;
private GameTimer gameTime;
@Getter(AccessLevel.PACKAGE)
private HashMap<WorldPoint, Integer> redEggs;
@Getter(AccessLevel.PACKAGE)
private HashMap<WorldPoint, Integer> greenEggs;
@Getter(AccessLevel.PACKAGE)
private HashMap<WorldPoint, Integer> blueEggs;
@Getter(AccessLevel.PACKAGE)
private HashMap<WorldPoint, Integer> yellowEggs;
@Inject
private Client client;
@@ -86,74 +116,90 @@ public class BarbarianAssaultPlugin extends Plugin
private BarbarianAssaultOverlay overlay;
@Provides
BarbarianAssaultConfig provideConfig(ConfigManager configManager)
{
BarbarianAssaultConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(BarbarianAssaultConfig.class);
}
@Override
protected void startUp() throws Exception
{
protected void startUp() throws Exception {
overlayManager.add(overlay);
font = FontManager.getRunescapeFont()
.deriveFont(Font.BOLD, 24);
.deriveFont(Font.BOLD, 24);
clockImage = ImageUtil.getResourceStreamFromClass(getClass(), "clock.png");
redEggs = new HashMap<>();
greenEggs = new HashMap<>();
blueEggs = new HashMap<>();
yellowEggs = new HashMap<>();
}
@Override
protected void shutDown() throws Exception
{
protected void shutDown() throws Exception {
overlayManager.remove(overlay);
gameTime = null;
currentWave = START_WAVE;
inGameBit = 0;
collectedEggCount = 0;
HpHealed = 0;
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event)
{
if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID)
{
public void onWidgetLoaded(WidgetLoaded event) {
if (event.getGroupId() == WidgetID.BA_REWARD_GROUP_ID) {
Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT);
if (config.waveTimes() && rewardWidget != null && rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && gameTime != null)
{
announceTime("Game finished, duration: ", gameTime.getTime(false));
String amt,type,totalMsg,total;
amt=type=totalMsg=total="";
if (config.waveTimes() && rewardWidget != null && rewardWidget.getText().contains(ENDGAME_REWARD_NEEDLE_TEXT) && gameTime != null) {
if (config.showHpCount() && HpHealed > 0) {
totalMsg = "; Total Healed: ";
total = ""+totalHpHealed;
}
else if (config.showEggCount() && collectedEggCount > 0) {
totalMsg = "; Total Collected: ";
total = ""+totalCollectedEggCount;
}
announceTime("Game finished, duration: ", gameTime.getTime(false),type, amt, totalMsg, total);
}
}
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
public void onChatMessage(ChatMessage event) {
if (event.getType() == ChatMessageType.GAMEMESSAGE
&& event.getMessage().startsWith("---- Wave:"))
{
&& event.getMessage().startsWith("---- Wave:")) {
String[] message = event.getMessage().split(" ");
currentWave = message[BA_WAVE_NUM_INDEX];
collectedEggCount = 0;
HpHealed = 0;
if (currentWave.equals(START_WAVE))
{
if (currentWave.equals(START_WAVE)) {
gameTime = new GameTimer();
}
else if (gameTime != null)
{
totalHpHealed = 0;
totalCollectedEggCount = 0;
} else if (gameTime != null) {
gameTime.setWaveStartTime();
}
} else if (event.getType() == ChatMessageType.GAMEMESSAGE
&& event.getMessage().contains("egg explode")) {
collectedEggCount -= 2;
} else if (event.getType() == ChatMessageType.GAMEMESSAGE
&& event.getMessage().contains("healed")) {
String message = event.getMessage();
String[] tokens = message.split(" ");
if (Integer.parseInt(tokens[2]) > 0) {
int Hp = Integer.parseInt(tokens[2]);
HpHealed += Hp;
}
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (client.getVar(Varbits.IN_GAME_BA) == 0 || client.getLocalPlayer() == null || overlay.getCurrentRound() != null)
{
public void onGameTick(GameTick event) {
if (client.getVar(Varbits.IN_GAME_BA) == 0 || client.getLocalPlayer() == null || overlay.getCurrentRound() != null) {
return;
}
switch (client.getLocalPlayer().getPlayerComposition().getEquipmentId(KitType.CAPE))
{
switch (client.getLocalPlayer().getPlayerComposition().getEquipmentId(KitType.CAPE)) {
case ItemID.ATTACKER_ICON:
overlay.setCurrentRound(new Round(Role.ATTACKER));
break;
@@ -170,39 +216,146 @@ public class BarbarianAssaultPlugin extends Plugin
}
@Subscribe
public void onVarbitChanged(VarbitChanged event)
{
public void onVarbitChanged(VarbitChanged event) {
int inGame = client.getVar(Varbits.IN_GAME_BA);
if (inGameBit != inGame)
{
if (inGameBit == 1)
{
String amt,type,totalMsg,total;
amt=type=totalMsg=total="";
if (inGameBit != inGame) {
if (inGameBit == 1) {
overlay.setCurrentRound(null);
if (config.waveTimes() && gameTime != null)
{
announceTime("Wave " + currentWave + " duration: ", gameTime.getTime(true));
if (config.waveTimes() && gameTime != null) {
totalCollectedEggCount += collectedEggCount;
totalHpHealed += HpHealed;
if (config.showHpCount() && HpHealed > 0) {
amt = "" + HpHealed;
type = "; Healed: ";
totalMsg = "; Total Healed: ";
total = ""+totalHpHealed;
}
else if (config.showEggCount() && collectedEggCount > 0) {
amt = "" + collectedEggCount;
type = "; Collected: ";
totalMsg = "; Total Collected: ";
total = ""+totalCollectedEggCount;
}
if (currentWave.equals("10"))
{
totalMsg=total="";
}
announceTime("Wave " + currentWave + " duration: ", gameTime.getTime(true), type, amt, totalMsg, total);
}
}
}
inGameBit = inGame;
}
private void announceTime(String preText, String time)
@Subscribe
public void onItemSpawned(ItemSpawned itemSpawned)
{
int itemId = itemSpawned.getItem().getId();
WorldPoint worldPoint = itemSpawned.getTile().getWorldLocation();
HashMap<WorldPoint, Integer> eggMap = getEggMap(itemId);
if (eggMap != null)
{
Integer existingQuantity = eggMap.putIfAbsent(worldPoint, 1);
if (existingQuantity != null)
{
eggMap.put(worldPoint, existingQuantity + 1);
}
}
}
@Subscribe
public void onItemDespawned(ItemDespawned event)
{
if (client.getVar(Varbits.IN_GAME_BA) == 0 || !isEgg(event.getItem().getId()))
{
return;
}
if (isUnderPlayer(event.getTile()))
{
collectedEggCount++;
}
}
String getCollectorHeardCall()
{
Widget widget = client.getWidget(WidgetInfo.BA_COLL_HEARD_TEXT);
String call = null;
if (widget != null)
{
call = widget.getText();
}
return call;
}
private HashMap<WorldPoint, Integer> getEggMap(int itemID)
{
switch (itemID)
{
case ItemID.RED_EGG:
return redEggs;
case ItemID.GREEN_EGG:
return greenEggs;
case ItemID.BLUE_EGG:
return blueEggs;
case ItemID.YELLOW_EGG:
return yellowEggs;
default:
return null;
}
}
private void announceTime(String preText, String time, String type, String amt, String totalMsg, String total) {
final String chatMessage = new ChatMessageBuilder()
.append(ChatColorType.NORMAL)
.append(preText)
.append(ChatColorType.HIGHLIGHT)
.append(time)
.build();
.append(ChatColorType.NORMAL)
.append(preText)
.append(ChatColorType.HIGHLIGHT)
.append(time)
.append(ChatColorType.NORMAL)
.append(type)
.append(ChatColorType.HIGHLIGHT)
.append(amt)
.append(ChatColorType.NORMAL)
.append(totalMsg)
.append(ChatColorType.HIGHLIGHT)
.append(total)
.build();
chatMessageManager.queue(QueuedMessage.builder()
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(chatMessage)
.build());
.type(ChatMessageType.CONSOLE)
.runeLiteFormattedMessage(chatMessage)
.build());
}
private boolean isEgg(int itemID)
{
if (itemID == ItemID.RED_EGG || itemID == ItemID.GREEN_EGG
|| itemID == ItemID.BLUE_EGG || itemID == ItemID.YELLOW_EGG)
{
return true;
}
return false;
}
private boolean isUnderPlayer(Tile tile) {
Player local = client.getLocalPlayer();
if (local == null)
{
return false;
}
return (tile.getWorldLocation().equals(local.getWorldLocation()));
}
public Font getFont()

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* 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.batools;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("BATools")
public interface BAToolsConfig extends Config
{
@ConfigItem(
keyName = "defTimer",
name = "Defender Tick Timer",
description = "Shows the current cycle tick of runners."
)
default boolean defTimer()
{
return false;
}
@ConfigItem(
keyName = "calls",
name = "Remove Incorrect Calls",
description = "Remove incorrect calls."
)
default boolean calls()
{
return false;
}
@ConfigItem(
keyName = "swapLadder",
name = "Swap ladder option",
description = "Swap Climb-down with Quick-start in the wave lobbies"
)
default boolean swapLadder()
{
return true;
}
@ConfigItem(
keyName = "healerCodes",
name = "Healer Codes",
description = "Overlay to show healer codes"
)
default boolean healerCodes()
{
return false;
}
@ConfigItem(
keyName = "healerMenuOption",
name = "Healer menu options",
description = "asd"
)
default boolean healerMenuOption()
{
return false;
}
@ConfigItem(
keyName = "antiDrag",
name = "Anti Drag",
description = "asd"
)
default boolean antiDrag()
{
return false;
}
@ConfigItem(
keyName = "antiDragDelay",
name = "Anti Drag Delay",
description = "asd"
)
default int antiDragDelay()
{
return 5;
}
@ConfigItem(
keyName = "eggBoi",
name = "Collector helper",
description = "asd"
)
default boolean eggBoi()
{
return false;
}
@ConfigItem(
keyName = "osHelp",
name = "Shift OS",
description = "asd"
)
default boolean osHelp()
{
return false;
}
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
* 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.batools;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import net.runelite.api.NPCComposition;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.OverlayUtil;
import net.runelite.client.ui.overlay.Overlay;
import java.time.Duration;
import java.time.Instant;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BAToolsOverlay extends Overlay
{
private static final Color RED = new Color(221, 44, 0);
private static final Color GREEN = new Color(0, 200, 83);
private static final Color ORANGE = new Color(255, 109, 0);
private static final Color YELLOW = new Color(255, 214, 0);
private static final Color CYAN = new Color(0, 184, 212);
private static final Color BLUE = new Color(41, 98, 255);
private static final Color DEEP_PURPLE = new Color(98, 0, 234);
private static final Color PURPLE = new Color(170, 0, 255);
private static final Color GRAY = new Color(158, 158, 158);
private final BAToolsConfig config;
private Client client;
private BAToolsPlugin plugin;
@Inject
public BAToolsOverlay(Client client, BAToolsPlugin plugin, BAToolsConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.config = config;
this.client = client;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
if(!config.healerCodes())
{
return null;
}
for (Healer healer : plugin.getHealers().values())
{
NPCComposition composition = healer.getNpc().getComposition();
Color color = composition.getCombatLevel() > 1 ? YELLOW : ORANGE;
if (composition.getConfigs() != null)
{
NPCComposition transformedComposition = composition.transform();
if (transformedComposition == null)
{
color = GRAY;
}
else
{
composition = transformedComposition;
}
}
int timeLeft = healer.getLastFoodTime() - (int)Duration.between(plugin.getWave_start(), Instant.now()).getSeconds();
timeLeft = timeLeft < 1 ? 0 : timeLeft;
if(healer.getFoodRemaining() > 1)
{
color = GREEN;
}
else if(healer.getFoodRemaining() == 1)
{
if(timeLeft > 0)
{
color = RED;
}
else
{
color = GREEN;
}
}
else
{
continue;
}
String text = String.format("%d %d",
healer.getFoodRemaining(),
timeLeft);
OverlayUtil.renderActorOverlay(graphics, healer.getNpc(), text, color);
}
return null;
}
}

View File

@@ -0,0 +1,643 @@
/*
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
* Copyright (c) 2018, Jacob M <https://github.com/jacoblairm>
* 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.batools;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Actor;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import static net.runelite.api.Constants.CHUNK_SIZE;
import net.runelite.api.ItemID;
import net.runelite.api.MenuEntry;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.HitsplatApplied;
import net.runelite.api.events.InteractingChanged;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.api.events.VarbitChanged;
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.chat.ChatMessageManager;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.ItemManager;
import net.runelite.client.input.KeyListener;
import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.Text;
@Slf4j
@PluginDescriptor(
name = "BA Tools",
description = "Custom tools for Barbarian Assault",
tags = {"minigame", "overlay", "timer"}
)
public class BAToolsPlugin extends Plugin implements KeyListener
{
int inGameBit = 0;
int tickNum;
int pastCall = 0;
private int currentWave = 1;
private static final int BA_WAVE_NUM_INDEX = 2;
private final List<MenuEntry> entries = new ArrayList<>();
private HashMap<Integer, Instant> foodPressed = new HashMap<>();
private CycleCounter counter;
private Actor lastInteracted;
private boolean shiftDown;
@Inject
private Client client;
@Inject
private ConfigManager configManager;
@Inject
private ChatMessageManager chatMessageManager;
@Inject
private OverlayManager overlayManager;
@Inject
private BAToolsConfig config;
@Inject
private ItemManager itemManager;
@Inject
private InfoBoxManager infoBoxManager;
@Inject
private BAToolsOverlay overlay;
@Getter
private Map<NPC, Healer> healers;
@Getter
private Instant wave_start;
@Inject
private KeyManager keyManager;
@Provides
BAToolsConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(BAToolsConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
healers = new HashMap<>();
wave_start = Instant.now();
lastInteracted = null;
foodPressed.clear();
client.setInventoryDragDelay(config.antiDragDelay());
keyManager.registerKeyListener(this);
}
@Override
protected void shutDown() throws Exception
{
removeCounter();
healers.clear();
inGameBit = 0;
lastInteracted = null;
overlayManager.remove(overlay);
client.setInventoryDragDelay(5);
keyManager.unregisterKeyListener(this);
shiftDown = false;
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event)
{
switch (event.getGroupId())
{
case WidgetID.BA_REWARD_GROUP_ID:
{
Widget rewardWidget = client.getWidget(WidgetInfo.BA_REWARD_TEXT);
if (rewardWidget != null && rewardWidget.getText().contains("<br>5"))
{
tickNum = 0;
}
}
}
}
@Subscribe
public void onGameTick(GameTick event)
{
if (config.antiDrag())
{
client.setInventoryDragDelay(config.antiDragDelay());
}
Widget callWidget = getWidget();
if (callWidget != null)
{
if (callWidget.getTextColor() != pastCall && callWidget.getTextColor() == 16316664)
{
tickNum = 0;
}
pastCall = callWidget.getTextColor();
}
if (inGameBit == 1)
{
if (tickNum > 9)
{
tickNum = 0;
}
if (counter == null)
{
addCounter();
}
//counter.setText(String.valueOf(tickNum));
counter.setCount(tickNum);
if (config.defTimer())
{
log.info("" + tickNum++);
}
}
}
private Widget getWidget()
{
if (client.getWidget(WidgetInfo.BA_DEF_CALL_TEXT) != null)
{
return client.getWidget(WidgetInfo.BA_DEF_CALL_TEXT);
}
else if (client.getWidget(WidgetInfo.BA_ATK_CALL_TEXT) != null)
{
return client.getWidget(WidgetInfo.BA_ATK_CALL_TEXT);
}
else if (client.getWidget(WidgetInfo.BA_COLL_CALL_TEXT) != null)
{
return client.getWidget(WidgetInfo.BA_COLL_CALL_TEXT);
}
else if (client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT) != null)
{
return client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT);
}
return null;
}
@Subscribe
public void onVarbitChanged(VarbitChanged event)
{
int inGame = client.getVar(Varbits.IN_GAME_BA);
if (inGameBit != inGame)
{
if (inGameBit == 1)
{
pastCall = 0;
removeCounter();
foodPressed.clear();
}
else
{
addCounter();
}
}
inGameBit = inGame;
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
if (event.getType() == ChatMessageType.CONSOLE
&& event.getMessage().startsWith("---- Wave:"))
{
String[] message = event.getMessage().split(" ");
currentWave = Integer.parseInt(message[BA_WAVE_NUM_INDEX]);
wave_start = Instant.now();
healers.clear();
}
}
@Subscribe
public void onNpcSpawned(NpcSpawned event)
{
NPC npc = event.getNpc();
if (isNpcHealer(npc.getId()))
{
if (checkNewSpawn(npc) || Duration.between(wave_start, Instant.now()).getSeconds() < 16)
{
int spawnNumber = healers.size();
healers.put(npc, new Healer(npc, spawnNumber, currentWave));
log.info("spawn number: " + spawnNumber + " on wave " + currentWave);
}
}
}
@Subscribe
public void onHitsplatApplied(HitsplatApplied hitsplatApplied)
{
Actor actor = hitsplatApplied.getActor();
if (healers.isEmpty() && !(actor instanceof NPC) && lastInteracted == null)
{
return;
}
for (Healer healer : healers.values())
{
if (healer.getNpc() == actor && actor == lastInteracted)
{
healer.setFoodRemaining(healer.getFoodRemaining() - 1);
}
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned event)
{
if (healers.remove(event.getNpc()) != null && healers.isEmpty())
{
healers.clear();
}
}
@Subscribe
public void onInteractingChanged(InteractingChanged event)
{
Actor opponent = event.getTarget();
if (opponent != null && opponent instanceof NPC && isNpcHealer(((NPC) opponent).getId()) && event.getSource() != client.getLocalPlayer())
{
lastInteracted = opponent;
}
}
public static boolean isNpcHealer(int npcId)
{
return npcId == NpcID.PENANCE_HEALER ||
npcId == NpcID.PENANCE_HEALER_5766 ||
npcId == NpcID.PENANCE_HEALER_5767 ||
npcId == NpcID.PENANCE_HEALER_5768 ||
npcId == NpcID.PENANCE_HEALER_5769 ||
npcId == NpcID.PENANCE_HEALER_5770 ||
npcId == NpcID.PENANCE_HEALER_5771 ||
npcId == NpcID.PENANCE_HEALER_5772 ||
npcId == NpcID.PENANCE_HEALER_5773 ||
npcId == NpcID.PENANCE_HEALER_5774;
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event)
{
if (config.calls() && getWidget() != null && event.getTarget().endsWith("horn") && !event.getTarget().contains("Unicorn"))
{
MenuEntry[] menuEntries = client.getMenuEntries();
Widget callWidget = getWidget();
String call = Calls.getOption(callWidget.getText());
MenuEntry correctCall = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
String option = entry.getOption();
if (option.equals(call))
{
correctCall = entry;
}
else if (!option.startsWith("Tell-"))
{
entries.add(entry);
}
}
if (correctCall != null) //&& callWidget.getTextColor()==16316664)
{
entries.add(correctCall);
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
}
else if (config.calls() && event.getTarget().endsWith("horn"))
{
entries.clear();
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
String option = Text.removeTags(event.getOption()).toLowerCase();
String target = Text.removeTags(event.getTarget()).toLowerCase();
if (config.swapLadder() && option.equals("climb-down") && target.equals("ladder"))
{
swap("quick-start", option, target, true);
}
if (inGameBit == 1 && config.healerMenuOption() && event.getTarget().contains("Penance Healer"))
{
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry lastEntry = menuEntries[menuEntries.length - 1];
String targett = lastEntry.getTarget();
if (foodPressed.containsKey(lastEntry.getIdentifier()))
{
lastEntry.setTarget(lastEntry.getTarget().split("\\(")[0] + "(" + Duration.between(foodPressed.get(lastEntry.getIdentifier()), Instant.now()).getSeconds() + ")");
if (Duration.between(foodPressed.get(lastEntry.getIdentifier()), Instant.now()).getSeconds() > 20)
{
lastEntry.setTarget(lastEntry.getTarget().replace("<col=ffff00>", "<col=2bff63>"));
}
}
else
{
lastEntry.setTarget(targett.replace("<col=ffff00>", "<col=2bff63>"));
}
client.setMenuEntries(menuEntries);
}
if (client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT) != null && inGameBit == 1 && config.eggBoi() && event.getTarget().endsWith("egg") && shiftDown)
{
String[] currentCall = client.getWidget(WidgetInfo.BA_COLL_LISTEN_TEXT).getText().split(" ");
log.info("1 " + currentCall[0]);
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (entry.getTarget().contains(currentCall[0]) && entry.getOption().equals("Take"))
{
correctEgg = entry;
}
}
if (correctEgg != null)
{
entries.add(correctEgg);
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
}
if (client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT) != null && inGameBit == 1 && config.osHelp() && event.getTarget().equals("<col=ffff>Healer item machine") && shiftDown)
{
String[] currentCall = client.getWidget(WidgetInfo.BA_HEAL_LISTEN_TEXT).getText().split(" ");
if (!currentCall[0].contains("Pois."))
{
return;
}
MenuEntry[] menuEntries = client.getMenuEntries();
MenuEntry correctEgg = null;
entries.clear();
for (MenuEntry entry : menuEntries)
{
if (entry.getOption().equals("Take-" + currentCall[1]))
{
correctEgg = entry;
}
}
if (correctEgg != null)
{
entries.add(correctEgg);
client.setMenuEntries(entries.toArray(new MenuEntry[entries.size()]));
}
}
}
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event)
{
if (!config.healerMenuOption() || !event.getMenuTarget().contains("Penance Healer") || client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT) == null)
{
return;
}
String currentCall = client.getWidget(WidgetInfo.BA_HEAL_CALL_TEXT).getText();
String target = event.getMenuTarget();
if ((currentCall.equals("Pois. Worms") && (target.contains("Poisoned worms") && target.contains("->") && target.contains("Penance Healer")))
|| (currentCall.equals("Pois. Meat") && (target.contains("Poisoned meat") && target.contains("->") && target.contains("Penance Healer")))
|| (currentCall.equals("Pois. Tofu") && (target.contains("Poisoned tofu") && target.contains("->") && target.contains("Penance Healer"))))
{
foodPressed.put(event.getId(), Instant.now());
}
if (target.contains("->") && target.contains("Penance Healer"))
{
foodPressed.put(event.getId(), Instant.now());
}
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (config.antiDrag())
{
client.setInventoryDragDelay(config.antiDragDelay());
}
}
private void addCounter()
{
if (!config.defTimer() || counter != null)
{
return;
}
int itemSpriteId = ItemID.FIGHTER_TORSO;
BufferedImage taskImg = itemManager.getImage(itemSpriteId);
counter = new CycleCounter(taskImg, this, tickNum);
infoBoxManager.addInfoBox(counter);
}
private void removeCounter()
{
if (counter == null)
{
return;
}
infoBoxManager.removeInfoBox(counter);
counter = null;
}
private void swap(String optionA, String optionB, String target, boolean strict)
{
MenuEntry[] entries = client.getMenuEntries();
int idxA = searchIndex(entries, optionA, target, strict);
int idxB = searchIndex(entries, optionB, target, strict);
if (idxA >= 0 && idxB >= 0)
{
MenuEntry entry = entries[idxA];
entries[idxA] = entries[idxB];
entries[idxB] = entry;
client.setMenuEntries(entries);
}
}
private int searchIndex(MenuEntry[] entries, String option, String target, boolean strict)
{
for (int i = entries.length - 1; i >= 0; i--)
{
MenuEntry entry = entries[i];
String entryOption = Text.removeTags(entry.getOption()).toLowerCase();
String entryTarget = Text.removeTags(entry.getTarget()).toLowerCase();
if (strict)
{
if (entryOption.equals(option) && entryTarget.equals(target))
{
return i;
}
}
else
{
if (entryOption.contains(option.toLowerCase()) && entryTarget.equals(target))
{
return i;
}
}
}
return -1;
}
private static WorldPoint rotate(WorldPoint point, int rotation)
{
int chunkX = point.getX() & ~(CHUNK_SIZE - 1);
int chunkY = point.getY() & ~(CHUNK_SIZE - 1);
int x = point.getX() & (CHUNK_SIZE - 1);
int y = point.getY() & (CHUNK_SIZE - 1);
switch (rotation)
{
case 1:
return new WorldPoint(chunkX + y, chunkY + (CHUNK_SIZE - 1 - x), point.getPlane());
case 2:
return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - x), chunkY + (CHUNK_SIZE - 1 - y), point.getPlane());
case 3:
return new WorldPoint(chunkX + (CHUNK_SIZE - 1 - y), chunkY + x, point.getPlane());
}
return point;
}
private boolean checkNewSpawn(NPC npc)
{
int regionId = 7509;
int regionX = 42;
int regionY = 46;
int z = 0;
// world point of the tile marker
WorldPoint worldPoint = new WorldPoint(
((regionId >>> 8) << 6) + regionX,
((regionId & 0xff) << 6) + regionY,
z
);
int[][][] instanceTemplateChunks = client.getInstanceTemplateChunks();
for (int x = 0; x < instanceTemplateChunks[z].length; ++x)
{
for (int y = 0; y < instanceTemplateChunks[z][x].length; ++y)
{
int chunkData = instanceTemplateChunks[z][x][y];
int rotation = chunkData >> 1 & 0x3;
int templateChunkY = (chunkData >> 3 & 0x7FF) * CHUNK_SIZE;
int templateChunkX = (chunkData >> 14 & 0x3FF) * CHUNK_SIZE;
if (worldPoint.getX() >= templateChunkX && worldPoint.getX() < templateChunkX + CHUNK_SIZE
&& worldPoint.getY() >= templateChunkY && worldPoint.getY() < templateChunkY + CHUNK_SIZE)
{
WorldPoint p = new WorldPoint(client.getBaseX() + x * CHUNK_SIZE + (worldPoint.getX() & (CHUNK_SIZE - 1)),
client.getBaseY() + y * CHUNK_SIZE + (worldPoint.getY() & (CHUNK_SIZE - 1)),
worldPoint.getPlane());
p = rotate(p, rotation);
if (p.distanceTo(npc.getWorldLocation()) < 5)
{
return true;
}
}
}
}
return false;
}
@Override
public void keyTyped(KeyEvent e)
{
}
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
{
shiftDown = true;
}
}
@Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SHIFT)
{
shiftDown = false;
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2018, Cameron <https://github.com/noremac201>
* 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.batools;
import java.util.HashMap;
import java.util.Map;
public enum Calls
{
//Attacker Calls
RED_EGG("Red egg", "Tell-red"),
GREEN_EGG("Green egg", "Tell-green"),
BLUE_EGG("Blue egg", "Tell-blue"),
//Collector Calls
CONTROLLED("Controlled/Bullet/Wind", "Tell-controlled"),
ACCURATE("Accurate/Field/Water", "Tell-accurate"),
AGGRESSIVE("Aggressive/Blunt/Earth", "Tell-aggressive"),
DEFENSIVE("Defensive/Barbed/Fire", "Tell-defensive"),
//Healer Calls
TOFU("Tofu", "Tell-tofu"),
CRACKERS("Crackers", "Tell-crackers"),
WORMS("Worms", "Tell-worms"),
//Defender Calls
POIS_WORMS("Pois. Worms", "Tell-worms"),
POIS_TOFU("Pois. Tofu", "Tell-tofu"),
POIS_MEAT("Pois. Meat", "Tell-meat");
private final String call;
private final String option;
private static final Map<String, String> CALL_MENU = new HashMap<>();
static
{
for (Calls s : values())
{
CALL_MENU.put(s.getCall(), s.getOption());
}
}
Calls(String call, String option)
{
this.call = call;
this.option = option;
}
public String getCall()
{
return call;
}
public String getOption()
{
return option;
}
public static String getOption(String call)
{
return CALL_MENU.get(call);
}
}

View File

@@ -0,0 +1,14 @@
package net.runelite.client.plugins.batools;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.ui.overlay.infobox.Counter;
import java.awt.image.BufferedImage;
public class CycleCounter extends Counter
{
public CycleCounter(BufferedImage img, Plugin plugin, int tick)
{
super(img, plugin, tick);
}
}

View File

@@ -0,0 +1,84 @@
package net.runelite.client.plugins.batools;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.NPC;
import net.runelite.api.Actor;
public class Healer
{
@Getter
private NPC npc;
@Getter
@Setter
private int wave;
@Getter
@Setter
private int spawnNumber;
@Getter
@Setter
private int foodRemaining;
@Getter
@Setter
private int lastFoodTime;
@Getter
@Setter
private int firstCallFood;
@Getter
@Setter
private int secondCallFood;
public Healer(NPC npc, int spawnNumber, int wave)
{
this.npc = npc;
this.wave = wave;
this.spawnNumber = spawnNumber;
this.firstCallFood = getCode(wave).getFirstCallFood()[spawnNumber];
this.secondCallFood = getCode(wave).getSecondCallFood()[spawnNumber];
this.foodRemaining = firstCallFood + secondCallFood;
this.lastFoodTime = getCode(wave).getSpacing()[spawnNumber];
}
private HealerCode getCode(int wave)
{
switch(wave)
{
case 1:
return HealerCode.WAVEONE;
case 2:
return HealerCode.WAVETWO;
case 3:
return HealerCode.WAVETHREE;
case 4:
return HealerCode.WAVEFOUR;
case 5:
return HealerCode.WAVEFIVE;
case 6:
return HealerCode.WAVESIX;
case 7:
return HealerCode.WAVESEVEN;
case 8:
return HealerCode.WAVEEIGHT;
case 9:
return HealerCode.WAVENINE;
case 10:
return HealerCode.WAVETEN;
default: return null;
}
}
}

View File

@@ -0,0 +1,34 @@
package net.runelite.client.plugins.batools;
import lombok.Getter;
enum HealerCode
{
WAVEONE(new int[] {1,1}, new int[] {0,0}, new int[] {0,0}),
WAVETWO(new int[] {1,1,2}, new int[] {0,0,0}, new int[] {0,0,21}),
WAVETHREE(new int[] {1,6,2}, new int[] {0,0,0}, new int[] {0,0,0}),
WAVEFOUR(new int[] {2,5,2,0}, new int[] {0,0,7,10}, new int[] {0,0,0,0}),
WAVEFIVE(new int[] {2,5,2,3,0}, new int[] {0,0,0,0,7}, new int[] {0,0,21,30,0}),
WAVESIX(new int[] {3,5,3,1,0,0}, new int[] {0,0,0,2,9,10}, new int[] {18,0,0,0,0,0}),
WAVESEVEN(new int[] {5,2,1,1,0,0,0}, new int[] {0,0,0,0,6,8,10}, new int[] {27,33,0,0,51,0,0}),
WAVEEIGHT(new int[] {2,8,1,1,0,0,0}, new int[] {1,0,1,1,3,1,10}, new int[] {36,0,33,39,45,48,0}),
WAVENINE(new int[] {2,8,1,1,0,0,0,0}, new int[] {1,1,1,1,1,1,1,10}, new int[] {0,21,0,0,0,0,0,0,0}),
WAVETEN(new int[] {5,2,1,1,0,0,0}, new int[] {0,1,1,1,3,3,10}, new int[] {27,33,0,0,51,0,0});
@Getter
private final int[] firstCallFood;
@Getter
private final int[] secondCallFood;
@Getter
private final int[] spacing;
HealerCode(int[] firstCallFood, int[] secondCallFood, int[] spacing)
{
this.firstCallFood = firstCallFood;
this.secondCallFood = secondCallFood;
this.spacing = spacing;
}
}

View File

@@ -83,4 +83,24 @@ public interface CannonConfig extends Config
{
return true;
}
@ConfigItem(
keyName = "ammoAmount",
name = "Ammo left",
description = "Configure to set the amount of ammo left to receive ammo left notification"
)
default int ammoAmount()
{
return 5;
}
@ConfigItem(
keyName = "notifyAmmoLeft",
name = "Ammo left notification",
description = "Sends a notification when cannon ammo is under the specified amount"
)
default boolean notifyAmmoLeft()
{
return true;
}
}

View File

@@ -46,12 +46,7 @@ import net.runelite.api.Projectile;
import static net.runelite.api.ProjectileID.CANNONBALL;
import static net.runelite.api.ProjectileID.GRANITE_CANNONBALL;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.api.events.ProjectileMoved;
import net.runelite.api.events.*;
import net.runelite.client.Notifier;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
@@ -275,6 +270,7 @@ public class CannonPlugin extends Plugin
if (!skipProjectileCheckThisTick)
{
cballsLeft--;
client.getCallbacks().post(new CannonballFired());
}
}
}
@@ -379,6 +375,13 @@ public class CannonPlugin extends Plugin
{
return Color.orange;
}
else if (cballsLeft <= config.ammoAmount())
{
if (config.notifyAmmoLeft())
{
notifier.notify("Your cannon has " + config.ammoAmount() + " balls left!");
}
}
return Color.red;
}

View File

@@ -126,4 +126,37 @@ public interface ClanChatConfig extends Config
{
return false;
}
@ConfigItem(
keyName = "discord",
name = "Discord",
description = "Send clan chats to a discord webhook <br> See https://support.discordapp.com/hc/en-us/articles/228383668",
position = 8
)
default boolean discord()
{
return false;
}
@ConfigItem(
keyName = "discordPath",
name = "Webhook path",
description = "Your webhook id and webhook token <br> (the part after \"/webhooks/\")",
position = 9
)
default String discordPath()
{
return "";
}
@ConfigItem(
keyName = "discordAccount",
name = "Discord/RS account",
description = "The login username (not rsn!) of the runescape account you want to use this on",
position = 10
)
default String discordAccount()
{
return "";
}
}

View File

@@ -39,6 +39,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ChatLineBuffer;
import net.runelite.api.ChatMessageType;
import net.runelite.api.ClanMember;
@@ -72,18 +73,22 @@ import net.runelite.client.game.ClanManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.clanchat.discord.DiscordClient;
import net.runelite.client.plugins.clanchat.discord.DiscordMessage;
import static net.runelite.client.ui.JagexColors.CHAT_CLAN_NAME_OPAQUE_BACKGROUND;
import static net.runelite.client.ui.JagexColors.CHAT_CLAN_NAME_TRANSPARENT_BACKGROUND;
import static net.runelite.client.ui.JagexColors.CHAT_CLAN_TEXT_OPAQUE_BACKGROUND;
import static net.runelite.client.ui.JagexColors.CHAT_CLAN_TEXT_TRANSPARENT_BACKGROUND;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
import net.runelite.client.util.Text;
import static net.runelite.client.util.Text.removeTags;
@PluginDescriptor(
name = "Clan Chat",
description = "Add rank icons to users talking in clan chat",
tags = {"icons", "rank", "recent"}
)
@Slf4j
public class ClanChatPlugin extends Plugin
{
private static final int MAX_CHATS = 10;
@@ -113,6 +118,9 @@ public class ClanChatPlugin extends Plugin
private List<String> chats = new ArrayList<>();
private List<Player> clanMembers = new ArrayList<>();
private ClanChatIndicator clanMemberCounter;
private DiscordClient discordClient;
/**
* queue of temporary messages added to the client
*/
@@ -138,6 +146,7 @@ public class ClanChatPlugin extends Plugin
clanMembers.clear();
removeClanCounter();
resetClanChats();
stopDiscordClient();
}
@Subscribe
@@ -158,6 +167,15 @@ public class ClanChatPlugin extends Plugin
{
removeClanCounter();
}
if (config.discord())
{
startDiscordClient();
}
else
{
stopDiscordClient();
}
}
}
@@ -285,6 +303,38 @@ public class ClanChatPlugin extends Plugin
addClanActivityMessages();
}
private void submitMessage(String message, String user, String url)
{
if (discordClient == null)
{
return;
}
DiscordMessage discordMessage = new DiscordMessage();
message = removeTags(message);
if (!user.contains("<img=2>") && !user.contains("<img=10>"))
{
discordMessage.setContent(message);
}
else if (user.contains("img=10"))
{
discordMessage.setContent("<:hcim:557056153834487819> " + message);
}
else
{
discordMessage.setContent("<:iron:557056153729630209> " + message);
}
discordMessage.setUsername(removeTags(user));
discordMessage.setAvatar_url(url);
discordClient.submit(discordMessage, config.discordPath());
}
private void submitMessage(String message)
{
submitMessage(message, "", "");
}
private void timeoutClanMessages()
{
if (clanJoinMessages.isEmpty())
@@ -346,7 +396,7 @@ public class ClanChatPlugin extends Plugin
private void addActivityMessage(ClanMember member, ClanActivityType activityType)
{
final String activityMessage = activityType == ClanActivityType.JOINED ? " has joined." : " has left.";
final String activityMessage = activityType == ClanActivityType.JOINED ? " has joined. " : " has left. ";
final ClanMemberRank rank = member.getRank();
Color textColor = CHAT_CLAN_TEXT_OPAQUE_BACKGROUND;
Color channelColor = CHAT_CLAN_NAME_OPAQUE_BACKGROUND;
@@ -358,7 +408,7 @@ public class ClanChatPlugin extends Plugin
channelColor = CHAT_CLAN_NAME_TRANSPARENT_BACKGROUND;
}
if (config.clanChatIcons() && rank != null && rank != ClanMemberRank.UNRANKED)
if (config.clanChatIcons() && rank != ClanMemberRank.UNRANKED)
{
rankIcon = clanManager.getIconNumber(rank);
}
@@ -378,6 +428,10 @@ public class ClanChatPlugin extends Plugin
final String messageString = message.build();
client.addChatMessage(ChatMessageType.FRIENDSCHATNOTIFICATION, "", messageString, "");
if (discordClient != null)
{
submitMessage(member.getUsername() + activityMessage + client.getClanChatCount() + " people online.");
}
final ChatLineBuffer chatLineBuffer = client.getChatLineMap().get(ChatMessageType.FRIENDSCHATNOTIFICATION.getType());
final MessageNode[] lines = chatLineBuffer.getLines();
@@ -399,12 +453,7 @@ public class ClanChatPlugin extends Plugin
@Subscribe
public void onChatMessage(ChatMessage chatMessage)
{
if (client.getGameState() != GameState.LOADING && client.getGameState() != GameState.LOGGED_IN)
{
return;
}
if (client.getClanChatCount() <= 0)
if (client.getGameState() != GameState.LOADING && client.getGameState() != GameState.LOGGED_IN || client.getClanChatCount() <= 0)
{
return;
}
@@ -426,6 +475,12 @@ public class ClanChatPlugin extends Plugin
}
break;
case FRIENDSCHAT:
if (discordClient != null)
{
String url = clanManager.getRank(chatMessage.getName()).getDiscavatar();
submitMessage(chatMessage.getMessage(), chatMessage.getName(), url);
}
if (!config.clanChatIcons())
{
return;
@@ -447,8 +502,12 @@ public class ClanChatPlugin extends Plugin
{
clanMembers.clear();
removeClanCounter();
clanJoinMessages.clear();
if (gameState == GameState.LOGIN_SCREEN)
{
stopDiscordClient();
}
}
}
@@ -477,6 +536,11 @@ public class ClanChatPlugin extends Plugin
if (event.isJoined())
{
clanJoinedTick = client.getTickCount();
if (config.discord())
{
startDiscordClient();
}
}
else
{
@@ -595,4 +659,22 @@ public class ClanChatPlugin extends Plugin
clanMemberCounter = new ClanChatIndicator(image, this);
infoBoxManager.addInfoBox(clanMemberCounter);
}
private void startDiscordClient()
{
if (discordClient == null && config.discordAccount().equals(client.getUsername()))
{
discordClient = new DiscordClient();
submitMessage("Started\n\n" + client.getLocalPlayer().getName() + " has joined.");
}
}
private void stopDiscordClient()
{
if (discordClient != null)
{
submitMessage(client.getLocalPlayer().getName() + " has left.\n\nStopped");
discordClient = null;
}
}
}

View File

@@ -0,0 +1,63 @@
package net.runelite.client.plugins.clanchat.discord;
import com.google.gson.Gson;
import java.io.IOException;
import static java.lang.Integer.parseInt;
import java.time.Instant;
import lombok.extern.slf4j.Slf4j;
import net.runelite.http.api.RuneLiteAPI;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
@Slf4j
public class DiscordClient
{
private static final MediaType JSON = MediaType.parse("application/json");
private static final Gson GSON = RuneLiteAPI.GSON;
private int rateLimit = 1;
private Instant rateReset = Instant.EPOCH;
public void submit(DiscordMessage message, String path)
{
if (rateLimit < 1 && Instant.now().isBefore(rateReset))
{
return;
}
final HttpUrl url = new HttpUrl.Builder()
.scheme("https")
.host("discordapp.com")
.addPathSegments("api/webhooks")
.addPathSegments(path)
.build();
Request request = new Request.Builder()
.post(RequestBody.create(JSON, GSON.toJson(message)))
.url(url)
.build();
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
log.debug("discord message failed", e);
}
@Override
public void onResponse(Call call, Response response)
{
rateLimit = parseInt(response.header("X-RateLimit-Remaining"));
rateReset = Instant.ofEpochSecond((parseInt(response.header("X-RateLimit-Reset"))));
log.debug("Submitted discord message, limit: {}, reset: {}", rateLimit, rateReset);
response.close();
}
});
}
}

View File

@@ -0,0 +1,12 @@
package net.runelite.client.plugins.clanchat.discord;
import lombok.Data;
@Data
public class DiscordMessage
{
private String username;
private String content;
private String avatar_url;
}

View File

@@ -0,0 +1,168 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("clanmanmode")
public interface ClanManModeConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "highlightattackable",
name = "Highlight attackable targets",
description = "Highlights targets attackable by all clan members"
)
default boolean highlightAttackable()
{
return false;
}
@ConfigItem(
position = 1,
keyName = "attackablecolor",
name = "Attackable target c olor",
description = "Color of targets all clan members can target"
)
default Color getAttackableColor()
{
return new Color(0, 184, 212);
}
@ConfigItem(
position = 2,
keyName = "highlightattacked",
name = "Highlight clan targets",
description = "Highlights people being attacked by your clan"
)
default boolean highlightAttacked()
{
return false;
}
@ConfigItem(
position = 3,
keyName = "attackedcolor",
name = "Clan target color",
description = "Color of players being attacked by clan"
)
default Color getClanAttackableColor()
{
return new Color(0, 184, 212);
}
@ConfigItem(
position = 4,
keyName = "drawPlayerTiles",
name = "Draw tiles under players",
description = "Configures whether or not tiles under highlighted players should be drawn"
)
default boolean drawTiles()
{
return false;
}
@ConfigItem(
position = 5,
keyName = "drawOverheadPlayerNames",
name = "Draw names above players",
description = "Configures whether or not player names should be drawn above players"
)
default boolean drawOverheadPlayerNames()
{
return true;
}
@ConfigItem(
position = 6,
keyName = "drawMinimapNames",
name = "Draw names on minimap",
description = "Configures whether or not minimap names for players with rendered names should be drawn"
)
default boolean drawMinimapNames()
{
return false;
}
@ConfigItem(
position = 7,
keyName = "showtargets",
name = "Highlight My Attackers",
description = "Shows players interacting with you"
)
default boolean showAttackers()
{
return false;
}
@ConfigItem(
position = 8,
keyName = "attackcolor",
name = "Attacker Color",
description = "Color of attackers"
)
default Color getAttackerColor()
{
return new Color(255, 0, 0);
}
@ConfigItem(
position = 9,
keyName = "showbold",
name = "Bold names of clan targets",
description = "Turns names of clan targets bold"
)
default boolean ShowBold() { return false; }
@ConfigItem(
position = 10,
keyName = "hideafter",
name = "Hide attackable targets after login",
description = "Automatically disables attackable player highlighting after login"
)
default boolean hideAttackable() { return false; }
@ConfigItem(
position = 11,
keyName = "hidetime",
name = "Ticks to hide",
description = "How many ticks after you are logged in that attackbles are hidden (1 tick = 0.6 seconds)"
)
default int hideTime() { return 5; }
@ConfigItem(
position = 12,
keyName = "mycblvl",
name = "Calc targets on my own combat level",
description = "Calculates potential targets based off your own combat lvl instead of clans"
)
default boolean CalcSelfCB() { return false; }
@ConfigItem(
position = 13,
keyName = "hideatkopt",
name = "Hide attack option for clan members",
description = "Disables attack option for clan members"
)
default boolean hideAtkOpt() { return false; }
@ConfigItem(
position = 14,
keyName = "showclanmembers",
name = "Persistent Clan Members",
description = "Will highlight clan members even when not in clan chat"
)
default boolean PersistentClan() { return false; }
@ConfigItem(
position = 15,
keyName = "clancolor",
name = "Clan Member Color",
description = "Color of clan members"
)
default Color getClanMemberColor()
{
return new Color(255, 0, 0);
}
}

View File

@@ -0,0 +1,52 @@
package net.runelite.client.plugins.clanmanmode;
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;
@Singleton
public class ClanManModeMinimapOverlay extends Overlay
{
private final ClanManModeService ClanManModeService;
private final ClanManModeConfig config;
@Inject
private ClanManModeMinimapOverlay(ClanManModeConfig config, ClanManModeService ClanManModeService)
{
this.config = config;
this.ClanManModeService = ClanManModeService;
setLayer(OverlayLayer.ABOVE_WIDGETS);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
ClanManModeService.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', ' ');
if (config.drawMinimapNames())
{
final net.runelite.api.Point minimapLocation = actor.getMinimapLocation();
if (minimapLocation != null)
{
OverlayUtil.renderTextLocation(graphics, minimapLocation, name, color);
}
}
}
}

View File

@@ -0,0 +1,63 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.ClanMemberRank;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.client.game.ClanManager;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
@Singleton
public class ClanManModeOverlay extends Overlay
{
private final ClanManModeService ClanManModeService;
private final ClanManModeConfig config;
private final ClanManager clanManager;
@Inject
private ClanManModeOverlay(ClanManModeConfig config, ClanManModeService ClanManModeService,
ClanManager clanManager)
{
this.config = config;
this.ClanManModeService = ClanManModeService;
this.clanManager = clanManager;
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
ClanManModeService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
{
if (!config.drawOverheadPlayerNames())
{
return;
}
String name = actor.getName().replace('\u00A0', ' ');
int offset = actor.getLogicalHeight() + 40;
Point textLocation = actor.getCanvasTextLocation(graphics, name, offset);
if (textLocation != null)
{
if (config.getClanAttackableColor().equals(color) && config.ShowBold()) {
graphics.setFont(FontManager.getRunescapeBoldFont());
}
OverlayUtil.renderTextLocation(graphics, textLocation, name, color);
}
}
}

View File

@@ -0,0 +1,137 @@
package net.runelite.client.plugins.clanmanmode;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.ClanManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.Text;
import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "<font color=\"aqua\">!Clan Man Mode</font>",
description = "Assists in clan PVP scenarios",
tags = {"highlight", "minimap", "overlay", "players"}
)
public class ClanManModePlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private ClanManModeConfig config;
@Inject
private ClanManModeOverlay ClanManModeOverlay;
@Inject
private ClanManModeTileOverlay ClanManModeTileOverlay;
@Inject
private ClanManModeMinimapOverlay ClanManModeMinimapOverlay;
@Inject
private Client client;
@Inject
private ClanManager clanManager;
@Provides
ClanManModeConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(ClanManModeConfig.class);
}
int wildernessLevel;
int clanmin;
int clanmax;
int inwildy;
int ticks;
Map<String, Integer> clan = new HashMap<>();
@Override
protected void startUp() throws Exception {
overlayManager.add(ClanManModeOverlay);
overlayManager.add(ClanManModeTileOverlay);
overlayManager.add(ClanManModeMinimapOverlay);
}
@Override
protected void shutDown() throws Exception {
overlayManager.remove(ClanManModeOverlay);
overlayManager.remove(ClanManModeTileOverlay);
overlayManager.remove(ClanManModeMinimapOverlay);
clan.clear();
ticks = 0;
wildernessLevel = 0;
clanmin = 0;
clanmax = 0;
inwildy = 0;
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged) {
if (gameStateChanged.getGameState() == GameState.LOGIN_SCREEN || gameStateChanged.getGameState() == GameState.HOPPING) {
ticks = 0;
}
}
@Subscribe
public void onGameTick(GameTick event) {
ticks++;
final Player localPlayer = client.getLocalPlayer();
if (!clan.containsKey(localPlayer.getName())) {
clan.put(localPlayer.getName(), localPlayer.getCombatLevel());
}
WorldPoint a = localPlayer.getWorldLocation();
int underLevel = ((a.getY() - 9920) / 8) + 1;
int upperLevel = ((a.getY() - 3520) / 8) + 1;
wildernessLevel = a.getY() > 6400 ? underLevel : upperLevel;
inwildy = client.getVar(Varbits.IN_WILDERNESS);
if (clan.size() > 0) {
clanmin = Collections.min(clan.values());
clanmax = Collections.max(clan.values());
}
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event) {
if (!config.hideAtkOpt()) {
return;
}
if (client.getGameState() != GameState.LOGGED_IN) {
return;
}
final String option = Text.removeTags(event.getOption()).toLowerCase();
if (option.equals("attack")) {
final Pattern ppattern = Pattern.compile("<col=ffffff>(.+?)<col=");
final Matcher pmatch = ppattern.matcher(event.getTarget());
pmatch.find();
if (pmatch.matches()) {
if (pmatch.group(1) != null) {
if (clan.containsKey(pmatch.group(1).replace(" ", " "))) {
MenuEntry[] entries = client.getMenuEntries();
entries = ArrayUtils.removeElement(entries, entries[entries.length - 1]);
client.setMenuEntries(entries);
}
}
}
}
}
}

View File

@@ -0,0 +1,157 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.NPC;
import net.runelite.api.Player;
import net.runelite.api.coords.WorldPoint;
@Singleton
public class ClanManModeService
{
private final Client client;
private final ClanManModeConfig config;
private final ClanManModePlugin plugin;
@Inject
private ClanManModeService(Client client, ClanManModeConfig config, ClanManModePlugin plugin)
{
this.config = config;
this.client = client;
this.plugin = plugin;
}
Map<String, String> interactors = new HashMap<>();
public void forEachPlayer(final BiConsumer<Player, Color> consumer)
{
int minatk = plugin.clanmax - plugin.wildernessLevel;
int maxatk = plugin.clanmin + plugin.wildernessLevel;
final Player localPlayer = client.getLocalPlayer();
final String localName = localPlayer.getName();
int selfmin = localPlayer.getCombatLevel() - plugin.wildernessLevel;
int selfmax = localPlayer.getCombatLevel() + plugin.wildernessLevel;
for (Player player : client.getPlayers())
{
if (player == null || player.getName() == null) {
continue;
}
if (player == localPlayer) {
continue;
}
boolean isClanMember = player.isClanMember();
Actor interacting = player.getInteracting();
Player interactor = null;
if (interacting != null && !(interacting instanceof NPC)) {
interactor = ((Player) interacting);
}
if (config.showAttackers()) {
if (interactor != null) {
if (interactor.getName().equals(localName)) {
consumer.accept(player, config.getAttackerColor());
}
}
}
if (plugin.inwildy == 1) {
if (isClanMember) {
if (!plugin.clan.containsKey(player.getName())) {
plugin.clan.put(player.getName(), player.getCombatLevel());
}
if (config.highlightAttacked()) {
if (interactor != null) {
if (!interactors.containsKey(interactor.getName())) {
WorldPoint a = interactor.getWorldLocation();
int underLevel = ((a.getY() - 9920) / 8) + 1;
int upperLevel = ((a.getY() - 3520) / 8) + 1;
int wildernessLevel = a.getY() > 6400 ? underLevel : upperLevel;
int wildydiff = plugin.wildernessLevel - wildernessLevel;
if (wildydiff < 0) {
wildydiff = 0;
}
if (config.CalcSelfCB()) {
if (interacting.getCombatLevel() <= selfmax && interacting.getCombatLevel() - wildydiff >= selfmin && !interactor.isClanMember()) {
interactors.put(interactor.getName(), player.getName());
consumer.accept(interactor, config.getClanAttackableColor());
}
} else {
if (interacting.getCombatLevel() <= maxatk && interacting.getCombatLevel() - wildydiff >= minatk && !interactor.isClanMember()) {
interactors.put(interactor.getName(), player.getName());
consumer.accept(interactor, config.getClanAttackableColor());
}
}
}
}
}
} else {
if (config.PersistentClan()) {
if (plugin.clan.containsKey(player.getName())) {
consumer.accept(player, config.getClanMemberColor());
}
}
if (config.highlightAttacked()) {
if (interactors.containsKey(player.getName())) {
String attackername = interactors.get(player.getName());
Boolean found = false;
for (Player attacker : client.getPlayers()) {
if (attacker == null || attacker.getName() == null) {
continue;
}
if (attacker.getName().equals(attackername)) {
found = true;
Actor ainteract = attacker.getInteracting();
if (ainteract != null) {
if (ainteract.getName().equals(player.getName())) {
consumer.accept(player, config.getClanAttackableColor());
} else {
interactors.remove(player.getName());
}
} else {
interactors.remove(player.getName());
}
break;
}
}
if (!found) {
interactors.remove(player.getName());
}
continue;
}
}
if (config.highlightAttackable()) {
if ((config.hideAttackable() && plugin.ticks >= config.hideTime()) || plugin.clan.containsKey(player.getName())) {
continue;
}
WorldPoint a = player.getWorldLocation();
int underLevel = ((a.getY() - 9920) / 8) + 1;
int upperLevel = ((a.getY() - 3520) / 8) + 1;
int wildernessLevel = a.getY() > 6400 ? underLevel : upperLevel;
int wildydiff = plugin.wildernessLevel - wildernessLevel;
if (wildydiff < 0) {
wildydiff = 0;
}
if (config.CalcSelfCB()) {
if (player.getCombatLevel() <= selfmax && player.getCombatLevel() - wildydiff >= selfmin) {
consumer.accept(player, config.getAttackableColor());
}
} else {
if (player.getCombatLevel() <= maxatk && player.getCombatLevel() - wildydiff >= minatk) {
consumer.accept(player, config.getAttackableColor());
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
package net.runelite.client.plugins.clanmanmode;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.inject.Inject;
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;
public class ClanManModeTileOverlay extends Overlay
{
private final ClanManModeService ClanManModeService;
private final ClanManModeConfig config;
@Inject
private ClanManModeTileOverlay(ClanManModeConfig config, ClanManModeService ClanManModeService)
{
this.config = config;
this.ClanManModeService = ClanManModeService;
setLayer(OverlayLayer.ABOVE_SCENE);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!config.drawTiles())
{
return null;
}
ClanManModeService.forEachPlayer((player, color) ->
{
final Polygon poly = player.getCanvasTilePoly();
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, color);
}
});
return null;
}
}

View File

@@ -310,7 +310,8 @@ public class ConfigPanel extends PluginPanel
String name = listItem.getName();
JLabel title = new JLabel(name);
title.setForeground(Color.WHITE);
title.setToolTipText("<html>" + name + ":<br>" + listItem.getDescription() + "</html>");
title.setText("<html>" + name +"</html>");
title.setToolTipText("<html>" + ":<br>" + listItem.getDescription() + "</html>");
topPanel.add(title);
for (ConfigItemDescriptor cid : cd.getItems())

View File

@@ -153,8 +153,10 @@ class PluginListItem extends JPanel
setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH, 20));
JLabel nameLabel = new JLabel(name);
nameLabel.setText("<html>" + name +"</html>");
nameLabel.setForeground(Color.WHITE);
if (!description.isEmpty())
{
nameLabel.setToolTipText("<html>" + name + ":<br>" + description + "</html>");

View File

@@ -0,0 +1,83 @@
/*
* Copyright (c) 2019, Jacky <liangj97@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.cox;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Range;
@ConfigGroup("hydra")
public interface CoxConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "showHydraTile",
name = "Hydra's Size Box ",
description = "Displays hydra's size box for luring over vents"
)
default boolean showHydraTile()
{
return false;
}
@ConfigItem(
position = 1,
keyName = "tileColour",
name = "Color of hydra tile size",
description = "Configures the color of hydra's size"
)
default Color hydraTileColour()
{
return Color.ORANGE;
}
@Range(
min = -1000,
max = 1000
)
@ConfigItem(
position = 2,
keyName = "prayerHeight",
name = "Sets hydra's prayer height",
description = "The height of the prayer indicator over Hydra"
)
default int prayerHeight()
{
return 450;
}
@ConfigItem(
position = 3,
keyName = "showHydraPrayer",
name = "Hydra's Attack Style Indicator",
description = "Displays hydra's size box for luring over vents"
)
default boolean showPrayer()
{
return false;
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (c) 2019, Jacky <https://github.com/jkybtw>
* 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.cox;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class CoxOverlay extends Overlay
{
private final Client client;
private final CoxPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
public CoxOverlay(Client client, CoxPlugin plugin)
{
this.client = client;
this.plugin = plugin;
setPosition(OverlayPosition.TOP_LEFT);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!client.isInInstancedRegion()) return null;
panelComponent.getChildren().clear();
{
if (plugin.getOlm() != null)
{
if (plugin.getAttackStyle() == 0)
{
panelComponent.getChildren().add(LineComponent.builder()
.left("Pray: ")
.right("Mage")
.build());
}
if (plugin.getAttackStyle() == 1)
{
panelComponent.getChildren().add(LineComponent.builder()
.left("Pray: ")
.right("Ranged")
.build());
}
}
}
return panelComponent.render(graphics);
}
}

View File

@@ -0,0 +1,124 @@
package net.runelite.client.plugins.cox;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.util.List;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Constants;
import net.runelite.api.GameObject;
import net.runelite.api.GraphicsObject;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.Scene;
import net.runelite.api.Tile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayUtil;
public class CoxOverlayAbove extends Overlay
{
private final Client client;
private final CoxPlugin plugin;
private CoxConfig config;
@Inject
public CoxOverlayAbove(Client client, CoxPlugin plugin, CoxConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
this.client = client;
this.config = config;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!client.isInInstancedRegion() && plugin.getOlm() == null) return null;
renderGroundObject(graphics);
renderTileObjects(graphics);
return null;
}
// renders special attack ground objects
private void renderGroundObject(Graphics2D graphics)
{
List<GraphicsObject> graphicsObjects = client.getGraphicsObjects();
for (GraphicsObject graphicsObject : graphicsObjects)
{
if (graphicsObject.getId() == 1447 || graphicsObject.getId() == 1356)
{
LocalPoint lp = graphicsObject.getLocation();
Polygon poly = Perspective.getCanvasTilePoly(client, lp);
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, Color.RED);
}
}
}
}
private void renderGameObjects(Graphics2D graphics, Tile tile, Player player)
{
GameObject[] gameObjects = tile.getGameObjects();
if (gameObjects != null)
{
for (GameObject gameObject : gameObjects)
{
if (gameObject != null && gameObject.getId() == 30033)
{
if (player.getLocalLocation().distanceTo(gameObject.getLocalLocation()) <= 5)
{
// Draw a polygon around the convex hull
// of the model vertices
Polygon p = gameObject.getConvexHull();
if (p != null)
{
graphics.drawPolygon(p);
}
}
}
}
}
}
private void renderTileObjects(Graphics2D graphics)
{
Scene scene = client.getScene();
Tile[][][] tiles = scene.getTiles();
int z = client.getPlane();
for (int x = 0; x < Constants.SCENE_SIZE; ++x)
{
for (int y = 0; y < Constants.SCENE_SIZE; ++y)
{
Tile tile = tiles[z][x][y];
if (tile == null)
{
continue;
}
Player player = client.getLocalPlayer();
if (player == null)
{
continue;
}
renderGameObjects(graphics, tile, player);
}
}
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (c) 2019, Jacky <https://github.com/jkybtw>
* 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.cox;
import com.google.inject.Provides;
import java.util.List;
import javax.inject.Inject;
import lombok.Getter;
import net.runelite.api.Client;
import net.runelite.api.NPC;
import net.runelite.api.Projectile;
import net.runelite.api.events.GameTick;
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.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Cox",
description = "COX Helper",
tags = {"combat", "overlay", "pve", "pvm"}
)
public class CoxPlugin extends Plugin
{
@Getter
private NPC olm = null;
@Getter
private int attackStyle = 0; // 0 - mage // 1 - range
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private CoxOverlay coxOverlay;
@Inject CoxOverlayAbove coxOverlayAbove;
@Inject
private CoxConfig config;
@Provides
CoxConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(CoxConfig.class);
}
@Override
protected void startUp() throws Exception
{
overlayManager.add(coxOverlay);
overlayManager.add(coxOverlayAbove);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(coxOverlay);
overlayManager.remove(coxOverlayAbove);
}
@Subscribe
public void onGameTick(GameTick event)
{
if (!client.isInInstancedRegion())
{
olm = null;
return;
}
if (client.getPlane() != 0) return;
List<NPC> npcs = client.getNpcs();
for (NPC npc : npcs)
{
if (npc.getId() == 7554)
{
olm = npc;
}
}
if (olm == null) return;
List<Projectile> projectiles = client.getProjectiles();
for (Projectile projectile : projectiles)
{
if (projectile.getId() == 1339)
{
// mage
attackStyle = 0;
}
if (projectile.getId() == 1340)
{
// range
attackStyle = 1;
}
}
}
}

View File

@@ -0,0 +1,133 @@
package net.runelite.client.plugins.easy.bank;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("easybank")
public interface EasyBankConfig extends Config {
@ConfigItem(
keyName = "withdrawOne",
name = "Withdraw/Deposit One",
description = "",
position = 0
)
default boolean getWithdrawOne() {
return true;
}
@ConfigItem(
keyName = "withdrawOneItems",
name = "Items",
description = "",
position = 1
)
default String getWithdrawOneItems() {
return "";
}
@ConfigItem(
keyName = "withdrawFive",
name = "Withdraw/Deposit Five",
description = "",
position = 2
)
default boolean getWithdrawFive() {
return true;
}
@ConfigItem(
keyName = "withdrawFiveItems",
name = "Items",
description = "",
position = 3
)
default String getWithdrawFiveItems() {
return "";
}
@ConfigItem(
keyName = "withdrawTen",
name = "Withdraw/Deposit Ten",
description = "",
position = 4
)
default boolean getWithdrawTen() {
return true;
}
@ConfigItem(
keyName = "withdrawTenItems",
name = "Items",
description = "",
position = 5
)
default String getWithdrawTenItems() {
return "";
}
@ConfigItem(
keyName = "withdrawX",
name = "Withdraw/Deposit X",
description = "",
position = 6
)
default boolean getWithdrawX() {
return true;
}
@ConfigItem(
keyName = "withdrawXAmount",
name = "Amount",
description = "",
position = 7
)
default String getWithdrawXAmount() {
return "";
}
@ConfigItem(
keyName = "withdrawXItems",
name = "Items",
description = "",
position = 8
)
default String getWithdrawXItems() {
return "";
}
@ConfigItem(
keyName = "withdrawAll",
name = "Withdraw/Deposit All",
description = "",
position = 9
)
default boolean getWithdrawAll() {
return true;
}
@ConfigItem(
keyName = "withdrawAllItems",
name = "Items",
description = "",
position = 10
)
default String getWithdrawAllItems() {
return "";
}
}

View File

@@ -0,0 +1,133 @@
package net.runelite.client.plugins.easy.bank;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.MenuEntry;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.easy.util.Swapper;
import net.runelite.client.util.Text;
import javax.inject.Inject;
@PluginDescriptor(
name = "EasyBank",
description = "EasyBank.",
tags = {"EasyBank", "easy"}
)
@Slf4j
public class EasyBankPlugin extends Plugin {
private Swapper swapper = new Swapper();
private MenuEntry[] entries;
@Inject
private Client client;
@Inject
private EasyBankConfig config;
@Provides
EasyBankConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(EasyBankConfig.class);
}
@Override
public void startUp() {
log.debug("EasyBank Started.");
}
@Override
public void shutDown() {
log.debug("EasyBank Stopped.");
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event) {
if (client.getGameState() != GameState.LOGGED_IN) {
return;
}
Widget loginScreenOne = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN);
Widget loginScreenTwo = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN_MESSAGE_OF_THE_DAY);
if (loginScreenOne != null || loginScreenTwo != null) {
return;
}
final String option = Text.removeTags(event.getOption()).toLowerCase();
final String target = Text.removeTags(event.getTarget()).toLowerCase();
Widget widgetBankTitleBar = client.getWidget(WidgetInfo.BANK_TITLE_BAR);
swapper.setEntries(client.getMenuEntries());
if (!(widgetBankTitleBar == null) && !widgetBankTitleBar.isHidden()) {
if (config.getWithdrawOne()) {
for (String item : config.getWithdrawOneItems().split(",")) {
item = item.trim();
if (target.equalsIgnoreCase(item)) {
swapper.markForSwap("Withdraw-1", option, target);
swapper.markForSwap("Deposit-1", option, target);
}
}
}
if (config.getWithdrawFive()) {
for (String item : config.getWithdrawFiveItems().split(",")) {
item = item.trim();
if (target.equalsIgnoreCase(item)) {
swapper.markForSwap("Withdraw-5", option, target);
swapper.markForSwap("Deposit-5", option, target);
}
}
}
if (config.getWithdrawTen()) {
for (String item : config.getWithdrawTenItems().split(",")) {
item = item.trim();
if (target.equalsIgnoreCase(item)) {
swapper.markForSwap("Withdraw-10", option, target);
swapper.markForSwap("Deposit-10", option, target);
}
}
}
if (config.getWithdrawX()) {
for (String item : config.getWithdrawXItems().split(",")) {
item = item.trim();
if (target.equalsIgnoreCase(item)) {
swapper.markForSwap("Withdraw-" + config.getWithdrawXAmount(), option, target);
swapper.markForSwap("Deposit-" + config.getWithdrawXAmount(), option, target);
}
}
}
if (config.getWithdrawAll()) {
for (String item : config.getWithdrawAllItems().split(",")) {
item = item.trim();
if (target.equalsIgnoreCase(item)) {
swapper.markForSwap("Withdraw-All", option, target);
swapper.markForSwap("Deposit-All", option, target);
}
}
}
}
swapper.startSwap();
client.setMenuEntries(swapper.getEntries());
}
}

View File

@@ -0,0 +1,56 @@
package net.runelite.client.plugins.easy.pvp;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("easypvp")
public interface EasyPvpConfig extends Config {
@ConfigItem(
keyName = "showWildernessRange",
name = "Show Wilderness Range",
description = "",
position = 0
)
default boolean getShowWildernessRange() {
return true;
}
@ConfigItem(
keyName = "ShowAttackablePlayers",
name = "Show Attackable Players",
description = "",
position = 1
)
default boolean getShowAttackablePlayers() {
return true;
}
@ConfigItem(
keyName = "warnProtectItemOff",
name = "Warn Protect Item Off",
description = "",
position = 2
)
default boolean getWarnProtectItemOff() {
return true;
}
@ConfigItem(
keyName = "showFreezeTimers",
name = "Show Freeze Timers",
description = "",
position = 3
)
default boolean getShowFreezeTimers() {
return true;
}
}

View File

@@ -0,0 +1,102 @@
package net.runelite.client.plugins.easy.pvp;
import com.google.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
import java.awt.*;
public class EasyPvpOverlay extends Overlay {
private final Client client;
private final EasyPvpPlugin plugin;
private final EasyPvpConfig config;
@Inject
private EasyPvpOverlay(Client client, EasyPvpPlugin plugin, EasyPvpConfig config) {
this.client = client;
this.plugin = plugin;
this.config = config;
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics) {
if (config.getShowAttackablePlayers()) {
for (Player player : plugin.getTargets()) {
OverlayUtil.renderPolygon(graphics, player.getConvexHull(), Color.RED);
Point minimapLocation = player.getMinimapLocation();
if (minimapLocation != null) {
OverlayUtil.renderMinimapLocation(graphics, minimapLocation, Color.RED.darker());
OverlayUtil.renderTextLocation(graphics, minimapLocation, player.getName(), Color.RED);
}
}
}
//
return null;
}
}
// @Override
// public Dimension render(Graphics2D graphics)
// {
// if (config.getShowWildernessRange())
// {
//// plugin.getDeadNpcsToDisplay().forEach((id, npc) -> renderNpcRespawn(npc, graphics));
// }
//
// if (config.getShowAttackablePlayers())
//
// for (Player player : plugin.getAttackablePlayers()) {
// if (player != null) {
// renderNpcOverlay(graphics, player, player.getName(), Color.RED);
// } else {
// plugin.getAttackablePlayers().remove(player);
// }
// }
//
// return null;
// }
// private void renderNpcOverlay(Graphics2D graphics, Player actor, String name, Color color)
// {
// LocalPoint lp = actor.getLocalLocation();
//// Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, 1);
//
// renderTile(graphics, lp, color);
//// renderMinimap();
//
//// if (config.drawNames())
//// {
//// Point textLocation = actor.getCanvasTextLocation(graphics, name, actor.getLogicalHeight() + 40);
////
//// if (textLocation != null)
//// {
//// OverlayUtil.renderTextLocation(graphics, textLocation, name, color);
//// }
//// }
// }
// private void renderTile(final Graphics2D graphics, final LocalPoint dest, final Color color)
// {
// if (dest == null)
// {
// return;
// }
// final Polygon poly = Perspective.getCanvasTilePoly(client, dest);
// if (poly == null)
// {
// return;
// }
// OverlayUtil.renderPolygon(graphics, poly, color);
// }

View File

@@ -0,0 +1,197 @@
package net.runelite.client.plugins.easy.pvp;
import com.google.inject.Inject;
import com.google.inject.Provides;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.api.Varbits;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.GameTick;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import java.util.HashSet;
import java.util.Set;
@PluginDescriptor(
name = "EasyPvP",
description = "EasyPvP.",
tags = {"EasyPVP", "easy"}
)
@Slf4j
public class EasyPvpPlugin extends Plugin {
private int inWildy;
@Inject
private Client client;
@Inject
private EasyPvpConfig config;
@Inject
private OverlayManager overlayManager;
@Inject
private EasyPvpOverlay overlay;
@Getter(AccessLevel.PACKAGE)
private Set<Player> targets = new HashSet<>();
private String target;
private boolean prayMage;
private WorldPoint location;
private String spell;
private int currentExperience;
private int gainedExperience;
@Provides
EasyPvpConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(EasyPvpConfig.class);
}
@Override
public void startUp() {
prayMage = false;
spell = "";
overlayManager.add(overlay);
log.debug("EasyPvP Started.");
}
@Override
public void shutDown() {
overlayManager.remove(overlay);
log.debug("EasyPvP Stopped.");
}
@Subscribe
public void onGameTick(GameTick event) {
inWildy = client.getVar(Varbits.IN_WILDERNESS);
if (inWildy == 0) {
targets.clear();
return;
}
Widget wildyText = client.getWidget(WidgetInfo.PVP_WILDERNESS_LEVEL);
if (wildyText == null) {
return;
}
int wildyLevel = Integer.parseInt(wildyText.getText().split(":")[1].trim());
if (config.getShowAttackablePlayers()) {
for (Player player : client.getPlayers()) {
if (Math.abs(player.getCombatLevel() - client.getLocalPlayer().getCombatLevel()) <= wildyLevel) { // && !player.equals(client.getLocalPlayer())
targets.add(player);
} else targets.remove(player);
}
}
}
// @Subscribe
// public void onGameStateChanged(GameStateChanged event) {
// if (event.getGameState() == GameState.LOGGED_IN) {
// currentExperience = client.getSkillExperience(Skill.MAGIC);
// }
// }
//
// @Subscribe
// public void onMenuOptionClicked(MenuOptionClicked event) {
// if (event.getMenuTarget().contains("->")) {
// target = Text.removeTags(event.getMenuTarget()).split(" -> ")[1];
// spell = Text.removeTags(event.getMenuTarget()).split(" -> ")[0];
// log.debug("{} - {}", spell, target);
// prayMage = false;
// }
// }
//
// @Subscribe
// public void onExperienceChanged(ExperienceChanged event) {
// if (event.getSkill() == Skill.MAGIC) {
// gainedExperience = client.getSkillExperience(Skill.MAGIC) - currentExperience;
// currentExperience = client.getSkillExperience(Skill.MAGIC);
// long frozenTime = calculateFreezeTime(gainedExperience, spell, prayMage);
// if (frozenTime > 0) {
// for (Player player : client.getPlayers()) {
// if (player.getName().equals(target)) {
// location = player.getWorldLocation();
// if (player.getOverheadIcon() != null && player.getOverheadIcon().equals(HeadIcon.MAGIC)) {
// prayMage = true;
// break;
// }
// targets.add(new Markable(player, location, System.currentTimeMillis(), frozenTime));
// log.debug("Marked Target {}", player.getName());
// }
// }
// }
// }
// }
//
// public long calculateFreezeTime(int experience, String spell, boolean protectionPrayer) {
// long freezeTime = 0;
// switch (spell) {
// case "Bind":
// if (experience > 30) {
// if (protectionPrayer) {
// freezeTime = 2500;
// } else {
// freezeTime = 5000;
// }
// }
// break;
// case "Snare":
// if (experience > 60) {
// if (protectionPrayer) {
// freezeTime = 5000;
// } else {
// freezeTime = 10000;
// }
// }
// break;
// case "Entangle":
// if (experience > 89) {
// if (protectionPrayer) {
// freezeTime = 7500;
// } else {
// freezeTime = 15000;
// }
// }
// break;
// case "Ice Rush":
// if (experience > 34) {
// freezeTime = 5000;
// }
// break;
// case "Ice Burst":
// if (experience > 40) {
// freezeTime = 10000;
// }
// break;
// case "Ice Blitz":
// if (experience > 46) {
// freezeTime = 15000;
// }
// break;
// case "Ice Barrage":
// if (experience > 52) {
// freezeTime = 20000;
// }
// break;
// }
// return freezeTime;
// }
}

View File

@@ -0,0 +1,43 @@
package net.runelite.client.plugins.easy.scape;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("easyscape")
public interface EasyScapeConfig extends Config {
@ConfigItem(
keyName = "removeExamine",
name = "Remove Examine",
description = "Removes Examine from the list of options.",
position = 0
)
default boolean getRemoveExamine() {
return true;
}
@ConfigItem(
keyName = "removeObjects",
name = "Remove Objects",
description = "Removes interaction with the listed objects.",
position = 1
)
default boolean getRemoveObjects() {
return true;
}
@ConfigItem(
keyName = "removedObjects",
name = "Objects",
description = "Objects listed here will have all interaction be removed.",
position = 2
)
default String getRemovedObjects() {
return "";
}
}

View File

@@ -0,0 +1,111 @@
package net.runelite.client.plugins.easy.scape;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.MenuEntry;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.util.Text;
import org.apache.commons.lang3.ArrayUtils;
import javax.inject.Inject;
@PluginDescriptor(
name = "EasyScape",
description = "EasyScape.",
tags = {"EasyScape"},
enabledByDefault = false
)
@Slf4j
public class EasyScapePlugin extends Plugin {
private MenuEntry[] entries;
@Inject
private Client client;
@Inject
private EasyScapeConfig config;
@Provides
EasyScapeConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(EasyScapeConfig.class);
}
@Override
public void startUp() {
log.debug("EasyScape Started.");
}
@Override
public void shutDown() {
log.debug("EasyScape Stopped.");
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event) {
if (client.getGameState() != GameState.LOGGED_IN) {
return;
}
Widget loginScreenOne = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN);
Widget loginScreenTwo = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN_MESSAGE_OF_THE_DAY);
if (loginScreenOne != null || loginScreenTwo != null) {
return;
}
final String target = Text.removeTags(event.getTarget()).toLowerCase();
entries = client.getMenuEntries();
if (config.getRemoveExamine()) {
for (int i = entries.length - 1; i >= 0; i--) {
if (entries[i].getOption().equals("Examine")) {
entries = ArrayUtils.remove(entries, i);
i--;
}
}
client.setMenuEntries(entries);
}
if (config.getRemoveObjects() && !config.getRemovedObjects().equals("")) {
for (String removed : config.getRemovedObjects().split(",")) {
removed = removed.trim();
if (target.contains("(") && target.split(" \\(")[0].equalsIgnoreCase(removed)) {
delete(event.getIdentifier());
} else if (target.contains("->")) {
String trimmed = target.split("->")[1].trim();
if (trimmed.length() >= removed.length() && trimmed.substring(0, removed.length()).equalsIgnoreCase(removed)) {
delete(event.getIdentifier());
break;
}
} else if (target.length() >= removed.length() && target.substring(0, removed.length()).equalsIgnoreCase(removed)) {
delete(event.getIdentifier());
break;
}
}
}
}
private void delete(int target) {
for (int i = entries.length - 1; i >= 0; i--) {
if (entries[i].getIdentifier() == target) {
entries = ArrayUtils.remove(entries, i);
i--;
}
}
client.setMenuEntries(entries);
}
}

View File

@@ -0,0 +1,186 @@
package net.runelite.client.plugins.easy.shop;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("easyshop")
public interface EasyShopConfig extends Config {
@ConfigItem(
keyName = "swapBuyOne",
name = "Swappable Buy One",
description = "",
position = 0
)
default boolean getSwapBuyOne() {
return true;
}
@ConfigItem(
keyName = "buyOneItems",
name = "Items",
description = "",
position = 1
)
default String getBuyOneItems() {
return "";
}
@ConfigItem(
keyName = "swapBuyFive",
name = "Swappable Buy Five",
description = "",
position = 2
)
default boolean getSwapBuyFive() {
return true;
}
@ConfigItem(
keyName = "buyFiveItems",
name = "Items",
description = "",
position = 3
)
default String getBuyFiveItems() {
return "";
}
@ConfigItem(
keyName = "swapBuyTen",
name = "Swappable Buy Ten",
description = "",
position = 4
)
default boolean getSwapBuyTen() {
return true;
}
@ConfigItem(
keyName = "buyTenItems",
name = "Items",
description = "",
position = 5
)
default String getBuyTenItems() {
return "";
}
@ConfigItem(
keyName = "swapBuyFifty",
name = "Swappable Buy Fifty",
description = "",
position = 6
)
default boolean getSwapBuyFifty() {
return true;
}
@ConfigItem(
keyName = "buyFiftyItems",
name = "Items",
description = "",
position = 7
)
default String getBuyFiftyItems() {
return "";
}
@ConfigItem(
keyName = "swapSellOne",
name = "Swappable Sell One",
description = "",
position = 8
)
default boolean getSwapSellOne() {
return true;
}
@ConfigItem(
keyName = "sellOneItems",
name = "Items",
description = "",
position = 9
)
default String getSellOneItems() {
return "";
}
@ConfigItem(
keyName = "swapSellFive",
name = "Swappable Sell Five",
description = "",
position = 10
)
default boolean getSwapSellFive() {
return true;
}
@ConfigItem(
keyName = "sellFiveItems",
name = "Items",
description = "",
position = 11
)
default String getSellFiveItems() {
return "";
}
@ConfigItem(
keyName = "swapSellTen",
name = "Swappable Sell Ten",
description = "",
position = 12
)
default boolean getSwapSellTen() {
return true;
}
@ConfigItem(
keyName = "sellTenItems",
name = "Items",
description = "",
position = 13
)
default String getSellTenItems() {
return "";
}
@ConfigItem(
keyName = "swapSellFifty",
name = "Swappable Sell Fifty",
description = "",
position = 14
)
default boolean getSwapSellFifty() {
return true;
}
@ConfigItem(
keyName = "sellFiftyItems",
name = "Items",
description = "",
position = 15
)
default String getSellFiftyItems() {
return "";
}
}

View File

@@ -0,0 +1,140 @@
package net.runelite.client.plugins.easy.shop;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.easy.util.Swapper;
import net.runelite.client.util.Text;
import javax.inject.Inject;
@PluginDescriptor(
name = "EasyShop",
description = "EasyShop.",
tags = {"EasyShop", "easy"}
)
@Slf4j
public class EasyShopPlugin extends Plugin {
private Swapper swapper = new Swapper();
@Inject
private Client client;
@Inject
private EasyShopConfig config;
@Provides
EasyShopConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(EasyShopConfig.class);
}
@Override
public void startUp() {
log.debug("EasyShop Started.");
}
@Override
public void shutDown() {
log.debug("EasyShop Stopped.");
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event) {
if (client.getGameState() != GameState.LOGGED_IN) {
return;
}
Widget loginScreenOne = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN);
Widget loginScreenTwo = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN_MESSAGE_OF_THE_DAY);
if (loginScreenOne != null || loginScreenTwo != null) {
return;
}
final String option = Text.removeTags(event.getOption()).toLowerCase();
final String target = Text.removeTags(event.getTarget()).toLowerCase();
swapper.setEntries(client.getMenuEntries());
if (config.getSwapBuyOne() && !config.getBuyOneItems().equals("")) {
for (String item : config.getBuyOneItems().split(",")) {
if (target.equalsIgnoreCase(item.trim())) {
swapper.markForSwap("Buy 1", option, target);
}
}
}
if (config.getSwapBuyFive() && !config.getBuyFiveItems().equals("")) {
for (String item : config.getBuyFiveItems().split(",")) {
if (target.equalsIgnoreCase(item.trim())) {
swapper.markForSwap("Buy 5", option, target);
}
}
}
if (config.getSwapBuyTen() && !config.getBuyTenItems().equals("")) {
for (String item : config.getBuyTenItems().split(",")) {
if (target.equalsIgnoreCase(item.trim())) {
swapper.markForSwap("Buy 10", option, target);
}
}
}
if (config.getSwapBuyFifty() && !config.getBuyFiftyItems().equals("")) {
for (String item : config.getBuyFiftyItems().split(",")) {
if (target.equalsIgnoreCase(item.trim())) {
swapper.markForSwap("Buy 50", option, target);
}
}
}
if (config.getSwapSellOne() && !config.getSellOneItems().equals("")) {
for (String item : config.getSellOneItems().split(",")) {
if (target.equalsIgnoreCase(item.trim())) {
swapper.markForSwap("Sell 1", option, target);
}
}
}
if (config.getSwapSellFive() && !config.getSellFiveItems().equals("")) {
for (String item : config.getSellFiveItems().split(",")) {
if (target.equalsIgnoreCase(item.trim())) {
swapper.markForSwap("Sell 5", option, target);
}
}
}
if (config.getSwapSellTen() && !config.getSellTenItems().equals("")) {
for (String item : config.getSellTenItems().split(",")) {
if (target.equalsIgnoreCase(item.trim())) {
swapper.markForSwap("Sell 10", option, target);
}
}
}
if (config.getSwapSellFifty() && !config.getSellFiftyItems().equals("")) {
for (String item : config.getSellFiftyItems().split(",")) {
if (target.equalsIgnoreCase(item.trim())) {
swapper.markForSwap("Sell 50", option, target);
}
}
}
swapper.startSwap();
client.setMenuEntries(swapper.getEntries());
}
}

View File

@@ -0,0 +1,201 @@
package net.runelite.client.plugins.easy.swap;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.plugins.easy.util.DuelingRingMode;
import net.runelite.client.plugins.easy.util.EssenceMode;
import net.runelite.client.plugins.easy.util.GamesNecklaceMode;
import net.runelite.client.plugins.easy.util.GloryMode;
@ConfigGroup("easyswap")
public interface EasySwapConfig extends Config {
@ConfigItem(
keyName = "easyConstruction",
name = "Easy Construction",
description = "Makes \"Remove\" the default option for listed items in build mode.",
position = 0
)
default boolean getEasyConstruction() {
return true;
}
@ConfigItem(
keyName = "constructionItems",
name = "Construction Items",
description = "Items listed here will have the default option set to \"Removed\" in build mode.",
position = 1
)
default String getConstructionItems() {
return "";
}
@ConfigItem(
keyName = "swapSmithing",
name = "Swap Smithing",
description = "Enables swapping of smith-1 and smith-all options.",
position = 2
)
default boolean getSwapSmithing() {
return true;
}
@ConfigItem(
keyName = "swapTanning",
name = "Swap Tanning",
description = "Enables swapping of tan-1 and tan-all options.",
position = 3
)
default boolean getSwapTanning() {
return true;
}
@ConfigItem(
keyName = "swapCrafting",
name = "Swap Crafting",
description = "Enables swapping of Make-1 and Make-all options.",
position = 4
)
default boolean getSwapCrafting() {
return true;
}
@ConfigItem(
keyName = "swapArdougneCape",
name = "Swap Ardougne Cape",
description = "Enables swapping of teleport and wear.",
position = 5
)
default boolean getSwapArdougneCape() {
return true;
}
@ConfigItem(
keyName = "swapSawmill",
name = "Swap Sawmill Operator",
description = "Makes Buy-plank the default option on the sawmill operator.",
position = 6
)
default boolean getSwapSawmill() {
return true;
}
@ConfigItem(
keyName = "swapSawmillPlanks",
name = "Swap Buy Planks",
description = "Makes Buy All the default option in buy planks.",
position = 7
)
default boolean getSwapSawmillPlanks() {
return true;
}
@ConfigItem(
keyName = "swapPuroPuro",
name = "Swap Puro Puro Wheat",
description = "",
position = 8
)
default boolean getSwapPuro() {
return true;
}
@ConfigItem(
keyName = "swapEssencePounch",
name = "Swap Essence Pouch",
description = "",
position = 9
)
default boolean getSwapEssencePouch() {
return true;
}
@ConfigItem(
keyName = "essenceMode",
name = "Mode",
description = "",
position = 10
)
default EssenceMode getEssenceMode() {
return EssenceMode.RUNECRAFTING;
}
@ConfigItem(
keyName = "swapGamesNecklace",
name = "Swap Games Necklace",
description = "",
position = 11
)
default boolean getGamesNecklace() {
return true;
}
@ConfigItem(
keyName = "gamesNecklaceMode",
name = "Mode",
description = "",
position = 12
)
default GamesNecklaceMode getGamesNecklaceMode() {
return GamesNecklaceMode.BURTHORPE;
}
@ConfigItem(
keyName = "swapDuelingRing",
name = "Swap Dueling Ring",
description = "",
position = 13
)
default boolean getDuelingRing() {
return true;
}
@ConfigItem(
keyName = "duelingRingMode",
name = "Mode",
description = "",
position = 14
)
default DuelingRingMode getDuelingRingMode() {
return DuelingRingMode.DUEL_ARENA;
}
@ConfigItem(
keyName = "swapGlory",
name = "Swap Glory",
description = "",
position = 15
)
default boolean getGlory() {
return true;
}
@ConfigItem(
keyName = "gloryMode",
name = "Mode",
description = "",
position = 16
)
default GloryMode getGloryMode() {
return GloryMode.EDGEVILLE;
}
}

View File

@@ -0,0 +1,236 @@
package net.runelite.client.plugins.easy.swap;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
import net.runelite.api.Player;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.easy.util.Swapper;
import net.runelite.client.util.Text;
import net.runelite.api.events.GameObjectSpawned;
import net.runelite.api.events.GameStateChanged;
import javax.inject.Inject;
import static net.runelite.api.MenuAction.WALK;
import static net.runelite.api.ObjectID.PORTAL_4525;
@PluginDescriptor(
name = "EasySwap",
description = "EasySwap.",
tags = {"EasySwap", "easy"}
)
@Slf4j
public class EasySwapPlugin extends Plugin {
private static final int PURO_PURO_REGION_ID = 10307;
private Swapper swapper = new Swapper();
private boolean inHouse = false;
@Inject
private Client client;
@Inject
private EasySwapConfig config;
@Provides
EasySwapConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(EasySwapConfig.class);
}
@Override
public void startUp() {
log.debug("EasySwap Started.");
}
@Override
public void shutDown() {
log.debug("EasySwap Stopped.");
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event) {
if (client.getGameState() != GameState.LOGGED_IN) {
return;
}
Widget loginScreenOne = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN);
Widget loginScreenTwo = client.getWidget(WidgetInfo.LOGIN_CLICK_TO_PLAY_SCREEN_MESSAGE_OF_THE_DAY);
if (loginScreenOne != null || loginScreenTwo != null) {
return;
}
final String option = Text.removeTags(event.getOption()).toLowerCase();
final String target = Text.removeTags(event.getTarget()).toLowerCase();
swapper.setEntries(client.getMenuEntries());
if (config.getSwapPuro() && isPuroPuro()) {
if (event.getType() == WALK.getId()) {
swapper.deprioritizeWalk();
} else if (option.equalsIgnoreCase("examine")) {
swapper.markForSwap("push-through", option, target);
} else if (option.equalsIgnoreCase("use")) {
swapper.markForSwap("escape", option, target);
}
}
if (config.getEasyConstruction() && !config.getConstructionItems().equals("") && inHouse) {
if (event.getType() == WALK.getId()) {
swapper.deprioritizeWalk();
}
swapper.markForSwap("Build", option, target);
for (int i = swapper.getEntries().length - 1; i >= 0; i--) {
for (String item : config.getConstructionItems().split(",")) {
if (item.trim().equalsIgnoreCase(Text.removeTags(swapper.getEntries()[i].getTarget()))) {
if (!swapper.getEntries()[i].getOption().equalsIgnoreCase("remove")) {
swapper.removeIndex(i);
i--;
}
}
}
}
}
if (config.getSwapSmithing()) {
if (option.equalsIgnoreCase("Smith 1")) {
swapper.markForSwap("Smith All", option, target);
} else if (option.equalsIgnoreCase("Smith 1 Set")) {
swapper.markForSwap("Smith All Sets", option, target);
}
}
if (config.getSwapTanning() && option.equalsIgnoreCase("Tan 1")) {
swapper.markForSwap("Tan All", option, target);
}
if (config.getSwapCrafting()) {
switch (option) {
case "Make-1":
swapper.markForSwap("Make-All", option, target);
break;
case "Craft 1":
swapper.markForSwap("Craft All", option, target);
break;
default:
break;
}
}
if (config.getSwapSawmill() && target.equalsIgnoreCase("Sawmill operator")) {
swapper.markForSwap("Buy-plank", option, target);
}
if (config.getSwapSawmillPlanks() && option.equalsIgnoreCase("Buy 1")) {
swapper.markForSwap("Buy All", option, target);
}
if (option.equalsIgnoreCase("Clear-All") && target.equalsIgnoreCase("bank Filler")) {
swapper.markForSwap("Clear", option, target);
}
if (target.toLowerCase().contains("ardougne cloak") && config.getSwapArdougneCape()) {
swapper.markForSwap("Kandarin Monastery", option, target);
swapper.markForSwap("Monastery Teleport", option, target);
}
if (config.getSwapEssencePouch()) {
if (isEssencePouch(target)) {
Widget widgetBankTitleBar = client.getWidget(WidgetInfo.BANK_TITLE_BAR);
switch (config.getEssenceMode()) {
case RUNECRAFTING:
if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) {
swapper.markForSwap("Empty", option, target);
} else {
swapper.markForSwap("Fill", option, target);
}
break;
case ESSENCE_MINING:
if (widgetBankTitleBar == null || widgetBankTitleBar.isHidden()) {
swapper.markForSwap("Fill", option, target);
} else {
swapper.markForSwap("Empty", option, target);
}
break;
default:
break;
}
}
}
if (config.getGamesNecklace()) {
if (target.toLowerCase().contains("games necklace")) {
swapper.markForSwap(config.getGamesNecklaceMode().toString(), option, target);
}
}
if (config.getDuelingRing()) {
if (target.toLowerCase().contains("ring of dueling")) {
swapper.markForSwap(config.getDuelingRingMode().toString(), option, target);
}
}
if (config.getGlory()) {
if (target.toLowerCase().contains("amulet of glory")) {
swapper.markForSwap(config.getGloryMode().toString(), option, target);
}
}
swapper.startSwap();
client.setMenuEntries(swapper.getEntries());
}
private boolean isEssencePouch(String target) {
return (target.equalsIgnoreCase("Small Pouch") || target.equalsIgnoreCase("Medium Pouch") || target.equalsIgnoreCase("Large Pouch") || target.equalsIgnoreCase("Giant Pouch"));
}
@Subscribe
public void onGameObjectSpawned(GameObjectSpawned event)
{
final GameObject gameObject = event.getGameObject();
if (PORTAL_4525 == gameObject.getId())
{
this.inHouse = true;
}
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
if (event.getGameState() == GameState.LOADING)
{
this.inHouse = false;
}
}
private boolean isHouse() {
return this.inHouse;
}
private boolean isPuroPuro() {
Player player = client.getLocalPlayer();
if (player == null) {
return false;
} else {
WorldPoint location = player.getWorldLocation();
return location.getRegionID() == PURO_PURO_REGION_ID;
}
}
}

View File

@@ -0,0 +1,18 @@
package net.runelite.client.plugins.easy.util;
public enum DuelingRingMode {
DUEL_ARENA("Duel Arena"),
CASTLE_WARS("Castle Wars"),
CLAN_WARS("Clan Wars");
private final String name;
DuelingRingMode(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,17 @@
package net.runelite.client.plugins.easy.util;
public enum EssenceMode {
RUNECRAFTING("Runecrafting"),
ESSENCE_MINING("Essence Mining");
private final String name;
EssenceMode(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,20 @@
package net.runelite.client.plugins.easy.util;
public enum GamesNecklaceMode {
BURTHORPE("Burthorpe"),
BARBARIAN_OUTPOST("Barbarian Outpost"),
CORPOREAL_BEAST("Corporeal Beast"),
TEARS_OF_GUTHIX("Tears of Guthix"),
WINTERTODT("Wintertodt Camp");
private final String name;
GamesNecklaceMode(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,19 @@
package net.runelite.client.plugins.easy.util;
public enum GloryMode {
EDGEVILLE("Edgeville"),
KARAMJA("Karamja"),
DRAYNOR_VILLAGE("Draynor Village"),
AL_KHARID("Al Kharid");
private final String name;
GloryMode(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}

View File

@@ -0,0 +1,28 @@
package net.runelite.client.plugins.easy.util;
import lombok.Getter;
import net.runelite.api.Player;
import net.runelite.api.coords.WorldPoint;
public class Markable {
@Getter
private Player player;
@Getter
private WorldPoint location;
@Getter
private long frozenTime;
@Getter
private long frozenUntil;
public Markable(Player player, WorldPoint location, long frozenTime, long frozenLength) {
this.player = player;
this.location = location;
this.frozenTime = frozenTime;
this.frozenUntil = frozenTime + frozenLength + 3000;
}
}

View File

@@ -0,0 +1,38 @@
package net.runelite.client.plugins.easy.util;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.util.Text;
public class Swappable {
@Getter
private String target;
@Getter
private String optionOne;
@Getter
private String optionTwo;
@Getter
@Setter
private int indexOne;
@Getter
@Setter
private int indexTwo;
public Swappable(String target, String optionOne, String optionTwo) {
this.target = Text.removeTags(target.toLowerCase());
this.optionOne = Text.removeTags(optionOne);
this.optionTwo = Text.removeTags(optionTwo);
this.indexOne = -1;
this.indexTwo = -1;
}
public boolean isReady() {
return this.indexOne != -1 && this.indexTwo != -1;
}
}

View File

@@ -0,0 +1,67 @@
package net.runelite.client.plugins.easy.util;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.MenuAction;
import net.runelite.api.MenuEntry;
import net.runelite.client.util.Text;
import org.apache.commons.lang3.ArrayUtils;
import java.util.HashSet;
import java.util.Set;
import static net.runelite.api.MenuAction.MENU_ACTION_DEPRIORITIZE_OFFSET;
public class Swapper {
private Set<Swappable> swapping;
@Getter
@Setter
private MenuEntry[] entries;
public Swapper() {
this.swapping = new HashSet<>();
}
public void deprioritizeWalk() {
MenuEntry menuEntry = entries[entries.length - 1];
menuEntry.setType(MenuAction.WALK.getId() + MENU_ACTION_DEPRIORITIZE_OFFSET);
}
public void removeIndex(int index) {
entries = ArrayUtils.remove(entries, index);
}
public void markForSwap(String optionA, String optionB, String target) {
swapping.add(new Swappable(target, optionA, optionB));
}
public void startSwap() {
int index = 0;
for (MenuEntry entry : entries) {
String target = Text.removeTags(entry.getTarget()).toLowerCase();
String option = Text.removeTags(entry.getOption()).toLowerCase();
for (Swappable swap : swapping) {
if (swap.getTarget().equalsIgnoreCase(target)) {
if (option.equalsIgnoreCase(swap.getOptionOne())) {
swap.setIndexOne(index);
} else if (option.equalsIgnoreCase(swap.getOptionTwo())) {
swap.setIndexTwo(index);
}
}
}
index++;
}
for (Swappable swap : swapping) {
if (swap.isReady()) {
MenuEntry entry = entries[swap.getIndexOne()];
entries[swap.getIndexOne()] = entries[swap.getIndexTwo()];
entries[swap.getIndexTwo()] = entry;
}
}
swapping.clear();
}
}

View File

@@ -0,0 +1,4 @@
package net.runelite.client.plugins.easy.zulrah;
public class EasyZulrahConfig {
}

View File

@@ -0,0 +1,4 @@
package net.runelite.client.plugins.easy.zulrah;
public class EasyZulrahPlugin {
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 2017, Aria <aria@ar1as.space>
* 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.equipmentinspector;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.plugins.grounditems.config.ItemHighlightMode;
import net.runelite.client.plugins.grounditems.config.MenuHighlightMode;
import net.runelite.client.plugins.grounditems.config.PriceDisplayMode;
@ConfigGroup("grounditems")
public interface EquipmentInspectorConfig extends Config
{
@ConfigItem(
keyName = "ShowValue",
name = "Show the total value of the items",
description = "shows the total value of the items",
position = 1
)
default boolean ShowValue()
{
return true;
}
@ConfigItem(
keyName = "protecteditems",
name = "# of protected items",
description = "Limit 4",
position = 2
)
default int protecteditems()
{ return 1; }
@ConfigItem(
keyName = "ExactValue",
name = "Show exact value",
description = "shows the excact gp value",
position = 3
)
default boolean ExactValue()
{ return false; }
}

View File

@@ -0,0 +1,98 @@
package net.runelite.client.plugins.equipmentinspector;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.ItemComposition;
import net.runelite.api.kit.KitType;
import net.runelite.client.game.AsyncBufferedImage;
import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.PluginPanel;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.swing.*;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.util.HashMap;
import java.util.Map;
@Slf4j
@Singleton
public class EquipmentInspectorPanel extends PluginPanel
{
private final static String NO_PLAYER_SELECTED = "No player selected";
private GridBagConstraints c;
private JPanel equipmentPanels;
private JPanel header;
private JLabel nameLabel;
@Inject
private ItemManager itemManager;
public EquipmentInspectorPanel()
{
GroupLayout layout = new GroupLayout(this);
setLayout(layout);
setBorder(new EmptyBorder(10, 10, 10, 10));
setBackground(ColorScheme.DARK_GRAY_COLOR);
equipmentPanels = new JPanel(new GridBagLayout());
c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1;
c.gridx = 0;
c.gridy = 0;
header = new JPanel();
header.setLayout(new BorderLayout());
header.setBorder(new CompoundBorder(
BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(58, 58, 58)),
BorderFactory.createEmptyBorder(0, 0, 10, 0)));
nameLabel = new JLabel(NO_PLAYER_SELECTED);
nameLabel.setForeground(Color.WHITE);
header.add(nameLabel, BorderLayout.CENTER);
layout.setHorizontalGroup(layout.createParallelGroup()
.addComponent(equipmentPanels)
.addComponent(header)
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addComponent(header)
.addGap(10)
.addComponent(equipmentPanels)
);
update(new HashMap<>(), "");
}
public void update(Map<KitType, ItemComposition> playerEquipment, String playerName)
{
if (playerName.isEmpty() || playerName == null)
{
nameLabel.setText(NO_PLAYER_SELECTED);
}
else
{
nameLabel.setText("Player: " + playerName);
}
SwingUtilities.invokeLater(() ->
{
equipmentPanels.removeAll();
playerEquipment.forEach((kitType, itemComposition) ->
{
AsyncBufferedImage itemImage = itemManager.getImage(itemComposition.getId());
equipmentPanels.add(new ItemPanel(itemComposition, kitType, itemImage), c);
c.gridy++;
});
header.revalidate();
header.repaint();
}
);
}
}

View File

@@ -0,0 +1,240 @@
package net.runelite.client.plugins.equipmentinspector;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.*;
import net.runelite.api.events.PlayerMenuOptionClicked;
import net.runelite.api.kit.KitType;
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.game.ItemManager;
import net.runelite.client.menus.MenuManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.Text;
import net.runelite.http.api.item.ItemPrice;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import javax.swing.*;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
@PluginDescriptor(
name = "<font color=\"green\">!Equipment Inspector</font>",
enabledByDefault = false
)
@Slf4j
public class EquipmentInspectorPlugin extends Plugin {
private static final String INSPECT_EQUIPMENT = "Gear";
private static final String KICK_OPTION = "Kick";
@Inject
@Nullable
private Client client;
@Inject
private ItemManager itemManager;
@Inject
private EquipmentInspectorConfig config;
@Inject
private ChatMessageManager chatMessageManager;
@Inject
private MenuManager menuManager;
@Inject
private ScheduledExecutorService executor;
@Inject
private ClientToolbar pluginToolbar;
@Provides
EquipmentInspectorConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(EquipmentInspectorConfig.class);
}
private NavigationButton navButton;
private EquipmentInspectorPanel equipmentInspectorPanel;
private int TotalPrice = 0;
private int Prot1 = 0;
private int Prot2 = 0;
private int Prot3 = 0;
private int Prot4 = 0;
@Override
protected void startUp() throws Exception
{
equipmentInspectorPanel = injector.getInstance(EquipmentInspectorPanel.class);
if(client != null) {
menuManager.addPlayerMenuItem(INSPECT_EQUIPMENT);
}
BufferedImage icon;
synchronized (ImageIO.class)
{
icon = ImageIO.read(getClass().getResourceAsStream("normal.png"));
}
navButton = NavigationButton.builder()
.tooltip("Equipment Inspector")
.icon(icon)
.priority(5)
.panel(equipmentInspectorPanel)
.build();
pluginToolbar.addNavigation(navButton);
}
@Override
protected void shutDown() throws Exception
{
menuManager.removePlayerMenuItem(INSPECT_EQUIPMENT);
}
@Subscribe
public void onPlayerMenuOptionClicked(PlayerMenuOptionClicked event)
{
if (event.getMenuOption().equals(INSPECT_EQUIPMENT))
{
executor.execute(() ->
{
try
{
SwingUtilities.invokeAndWait(() ->
{
if (!navButton.isSelected())
{
navButton.getOnSelect().run();
}
});
}
catch (InterruptedException | InvocationTargetException e)
{
throw new RuntimeException(e);
}
String playerName = Text.removeTags(event.getMenuTarget());
// The player menu uses a non-breaking space in the player name, we need to replace this to compare
// against the playerName in the player cache.
String finalPlayerName = playerName.replace('\u00A0', ' ');
System.out.println(finalPlayerName);
List<Player> players = client.getPlayers();
Optional<Player> targetPlayer = players.stream()
.filter(Objects::nonNull)
.filter(p -> p.getName().equals(finalPlayerName)).findFirst();
if (targetPlayer.isPresent())
{
TotalPrice = 0;
Prot1 = 0;
Prot2 = 0;
Prot3 = 0;
Prot4 = 0;
Player p = targetPlayer.get();
Map<KitType, ItemComposition> playerEquipment = new HashMap<>();
for (KitType kitType : KitType.values())
{
int itemId = p.getPlayerComposition().getEquipmentId(kitType);
if (itemId != -1)
{
ItemComposition itemComposition = client.getItemDefinition(itemId);
playerEquipment.put(kitType, itemComposition);
int ItemPrice = itemManager.getItemPrice(itemId);
TotalPrice += ItemPrice;
if (ItemPrice > Prot1 ) {
Prot4 = Prot3;
Prot3 = Prot2;
Prot2 = Prot1;
Prot1 = ItemPrice;
} else if (ItemPrice > Prot2){
Prot4 = Prot3;
Prot3 = Prot2;
Prot2 = ItemPrice;
} else if (ItemPrice > Prot3){
Prot4 = Prot3;
Prot3 = ItemPrice;
} else if (ItemPrice > Prot4){
Prot4 = ItemPrice;
}
}
}
int IgnoredItems = config.protecteditems();
if (IgnoredItems != 0 && IgnoredItems != 1 && IgnoredItems != 2 && IgnoredItems != 3) {
IgnoredItems = 4;
}
if (config.ShowValue()) {
switch (IgnoredItems) {
case 1:
TotalPrice = TotalPrice - Prot1;
break;
case 2:
TotalPrice = TotalPrice - Prot1;
TotalPrice = TotalPrice - Prot2;
break;
case 3:
TotalPrice = TotalPrice - Prot1;
TotalPrice = TotalPrice - Prot2;
TotalPrice = TotalPrice - Prot3;
break;
case 4:
TotalPrice = TotalPrice - Prot1;
TotalPrice = TotalPrice - Prot2;
TotalPrice = TotalPrice - Prot3;
TotalPrice = TotalPrice - Prot4;
break;
}
String StringPrice = "";
if (!config.ExactValue()) {
TotalPrice = TotalPrice / 1000;
StringPrice = NumberFormat.getIntegerInstance().format(TotalPrice);
StringPrice = StringPrice + 'K';
}
if (config.ExactValue()) {
StringPrice = NumberFormat.getIntegerInstance().format(TotalPrice);
}
chatMessageManager.queue(QueuedMessage.builder()
.type(ChatMessageType.FRIENDSCHATNOTIFICATION)
.runeLiteFormattedMessage(new ChatMessageBuilder()
.append(ChatColorType.HIGHLIGHT)
.append("Risked Value: ")
.append(ChatColorType.NORMAL)
.append(StringPrice)
.build())
.build());
}
equipmentInspectorPanel.update(playerEquipment, playerName);
}
});
}
}
}

View File

@@ -0,0 +1,52 @@
package net.runelite.client.plugins.equipmentinspector;
import net.runelite.api.ItemComposition;
import net.runelite.api.kit.KitType;
import net.runelite.client.game.AsyncBufferedImage;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.FontManager;
import org.apache.commons.lang3.StringUtils;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class ItemPanel extends JPanel
{
ItemPanel(ItemComposition item, KitType kitType, AsyncBufferedImage icon)
{
setBorder(new EmptyBorder(3, 3, 3, 3));
setBackground(ColorScheme.DARK_GRAY_COLOR);
GroupLayout layout = new GroupLayout(this);
this.setLayout(layout);
JLabel name = new JLabel(item.getName());
JLabel location = new JLabel(StringUtils.capitalize(kitType.toString().toLowerCase()));
location.setFont(FontManager.getRunescapeSmallFont());
JLabel imageLabel = new JLabel();
icon.addTo(imageLabel);
layout.setVerticalGroup(layout.createParallelGroup()
.addComponent(imageLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(name)
.addComponent(location)
)
);
layout.setHorizontalGroup(layout.createSequentialGroup()
.addComponent(imageLabel)
.addGap(8)
.addGroup(layout.createParallelGroup()
.addComponent(name)
.addComponent(location)
)
);
// AWT's Z order is weird. This put image at the back of the stack
setComponentZOrder(imageLabel, getComponentCount() - 1);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

View File

@@ -0,0 +1,63 @@
package net.runelite.client.plugins.fightcavejadhelper;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.SpriteID;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class FightCaveJadHelperOverlay extends Overlay
{
private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150);
private final Client client;
private final FightCaveJadHelperPlugin plugin;
private final SpriteManager spriteManager;
private final PanelComponent imagePanelComponent = new PanelComponent();
@Inject
private FightCaveJadHelperOverlay(Client client, FightCaveJadHelperPlugin plugin, SpriteManager spriteManager)
{
setPosition(OverlayPosition.BOTTOM_RIGHT);
setPriority(OverlayPriority.HIGH);
this.client = client;
this.plugin = plugin;
this.spriteManager = spriteManager;
}
@Override
public Dimension render(Graphics2D graphics)
{
final JadAttack attack = plugin.getAttack();
if (attack == null)
{
return null;
}
final BufferedImage prayerImage = getPrayerImage(attack);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(attack.getPrayer())
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
}
private BufferedImage getPrayerImage(JadAttack attack)
{
final int prayerSpriteID = attack == JadAttack.MAGIC ? SpriteID.PRAYER_PROTECT_FROM_MAGIC : SpriteID.PRAYER_PROTECT_FROM_MISSILES;
return spriteManager.getSprite(prayerSpriteID, 0);
}
}

View File

@@ -0,0 +1,89 @@
package net.runelite.client.plugins.fightcavejadhelper;
import javax.annotation.Nullable;
import javax.inject.Inject;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.NPC;
import net.runelite.api.NpcID;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "<font color=\"#4863A0\">!Fight Cave - Jad</font>",
description = "Show what to pray against Jad",
tags = {"bosses", "combat", "minigame", "overlay", "prayer", "pve", "pvm"},
enabledByDefault = false
)
public class FightCaveJadHelperPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private FightCaveJadHelperOverlay overlay;
@Getter(AccessLevel.PACKAGE)
@Nullable
private JadAttack attack;
private NPC jad;
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
jad = null;
attack = null;
}
@Subscribe
public void onNpcSpawned(final NpcSpawned event)
{
final int id = event.getNpc().getId();
if (id == NpcID.TZTOKJAD || id == NpcID.TZTOKJAD_6506)
{
jad = event.getNpc();
}
}
@Subscribe
public void onNpcDespawned(final NpcDespawned event)
{
if (jad == event.getNpc())
{
jad = null;
attack = null;
}
}
@Subscribe
public void onAnimationChanged(final AnimationChanged event)
{
if (event.getActor() != jad)
{
return;
}
if (jad.getAnimation() == JadAttack.MAGIC.getAnimation())
{
attack = JadAttack.MAGIC;
}
else if (jad.getAnimation() == JadAttack.RANGE.getAnimation())
{
attack = JadAttack.RANGE;
}
}
}

View File

@@ -0,0 +1,29 @@
package net.runelite.client.plugins.fightcavejadhelper;
import net.runelite.api.AnimationID;
import net.runelite.api.Prayer;
public enum JadAttack
{
MAGIC(AnimationID.TZTOK_JAD_MAGIC_ATTACK, Prayer.PROTECT_FROM_MAGIC),
RANGE(AnimationID.TZTOK_JAD_RANGE_ATTACK, Prayer.PROTECT_FROM_MISSILES);
private final int animation;
private final Prayer prayer;
JadAttack(int animation, Prayer prayer)
{
this.animation = animation;
this.prayer = prayer;
}
public int getAnimation()
{
return animation;
}
public Prayer getPrayer()
{
return prayer;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("Fight Cave - Wave Helper")
public interface FightCaveWaveHelperConfig extends Config
{
@ConfigItem(
keyName = "waveDisplay",
name = "Wave display",
description = "Shows monsters that will spawn on the selected wave(s)."
)
default WaveDisplayMode waveDisplay()
{
return WaveDisplayMode.BOTH;
}
}

View File

@@ -0,0 +1,173 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import com.google.inject.Provides;
import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import lombok.Getter;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameStateChanged;
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.ui.overlay.OverlayManager;
import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "<font color=\"#4863A0\">!Fight Cave - Waves</font>",
description = "Displays current and upcoming wave monsters in the Fight Caves",
tags = {"bosses", "combat", "minigame", "overlay", "pve", "pvm", "jad", "fire", "cape", "wave"},
enabledByDefault = false
)
public class FightCaveWaveHelperPlugin extends Plugin
{
private static final Pattern WAVE_PATTERN = Pattern.compile(".*Wave: (\\d+).*");
private static final int FIGHT_CAVE_REGION = 9551;
private static final int MAX_MONSTERS_OF_TYPE_PER_WAVE = 2;
static final int MAX_WAVE = 63;
@Getter
static final List<EnumMap<WaveMonster, Integer>> WAVES = new ArrayList<>();
@Getter
private int currentWave = -1;
@Inject
private Client client;
@Inject
private OverlayManager overlayManager;
@Inject
private WaveOverlay waveOverlay;
static
{
final WaveMonster[] waveMonsters = WaveMonster.values();
// Add wave 1, future waves are derived from its contents
final EnumMap<WaveMonster, Integer> waveOne = new EnumMap<>(WaveMonster.class);
waveOne.put(waveMonsters[0], 1);
WAVES.add(waveOne);
for (int wave = 1; wave < MAX_WAVE; wave++)
{
final EnumMap<WaveMonster, Integer> prevWave = WAVES.get(wave - 1).clone();
int maxMonsterOrdinal = -1;
for (int i = 0; i < waveMonsters.length; i++)
{
final int ordinalMonsterQuantity = prevWave.getOrDefault(waveMonsters[i], 0);
if (ordinalMonsterQuantity == MAX_MONSTERS_OF_TYPE_PER_WAVE)
{
maxMonsterOrdinal = i;
break;
}
}
if (maxMonsterOrdinal >= 0)
{
prevWave.remove(waveMonsters[maxMonsterOrdinal]);
}
final int addedMonsterOrdinal = maxMonsterOrdinal >= 0 ? maxMonsterOrdinal + 1 : 0;
final WaveMonster addedMonster = waveMonsters[addedMonsterOrdinal];
final int addedMonsterQuantity = prevWave.getOrDefault(addedMonster, 0);
prevWave.put(addedMonster, addedMonsterQuantity + 1);
WAVES.add(prevWave);
}
}
@Provides
FightCaveWaveHelperConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(FightCaveWaveHelperConfig.class);
}
@Override
public void startUp()
{
overlayManager.add(waveOverlay);
}
@Override
public void shutDown()
{
overlayManager.remove(waveOverlay);
currentWave = -1;
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
if (event.getGameState() != GameState.LOGGED_IN)
{
return;
}
if (!inFightCave())
{
currentWave = -1;
}
}
@Subscribe
public void onChatMessage(ChatMessage event)
{
final Matcher waveMatcher = WAVE_PATTERN.matcher(event.getMessage());
if (event.getType() != ChatMessageType.GAMEMESSAGE
|| !inFightCave()
|| !waveMatcher.matches())
{
return;
}
currentWave = Integer.parseInt(waveMatcher.group(1));
}
boolean inFightCave()
{
return ArrayUtils.contains(client.getMapRegions(), FIGHT_CAVE_REGION);
}
static String formatMonsterQuantity(final WaveMonster monster, final int quantity)
{
return String.format("%dx %s", quantity, monster);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum WaveDisplayMode
{
CURRENT("Current wave"),
NEXT("Next wave"),
BOTH("Both");
private final String name;
@Override
public String toString()
{
return name;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import lombok.AllArgsConstructor;
@AllArgsConstructor
enum WaveMonster
{
TZ_KIH("Tz-Kih", 22),
TZ_KEK("Tz-Kek", 45),
TOK_XIL("Tok-Xil", 90),
YT_MEJKOT("Yt-MejKot", 180),
KET_ZEK("Ket-Zek", 360),
TZKOK_JAD("TzTok-Jad", 702);
private final String name;
private final int level;
@Override
public String toString()
{
return String.format("%s - Level %s", name, level);
}
}

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2018, Jordan Atwood <jordan.atwood423@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.fightcavewavehelper;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
class WaveOverlay extends Overlay
{
private static final Color HEADER_COLOR = ColorScheme.BRAND_ORANGE;
private final FightCaveWaveHelperConfig config;
private final FightCaveWaveHelperPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private WaveOverlay(FightCaveWaveHelperConfig config, FightCaveWaveHelperPlugin plugin)
{
setPosition(OverlayPosition.TOP_RIGHT);
this.config = config;
this.plugin = plugin;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!plugin.inFightCave()
|| plugin.getCurrentWave() < 0)
{
return null;
}
panelComponent.getChildren().clear();
final int currentWave = plugin.getCurrentWave();
final int waveIndex = currentWave - 1;
if (config.waveDisplay() == WaveDisplayMode.CURRENT
|| config.waveDisplay() == WaveDisplayMode.BOTH)
{
final Map<WaveMonster, Integer> waveContents = FightCaveWaveHelperPlugin.getWAVES().get(waveIndex);
addWaveInfo("Wave " + plugin.getCurrentWave(), waveContents);
}
if ((config.waveDisplay() == WaveDisplayMode.NEXT
|| config.waveDisplay() == WaveDisplayMode.BOTH)
&& currentWave != FightCaveWaveHelperPlugin.MAX_WAVE)
{
final Map<WaveMonster, Integer> waveContents = FightCaveWaveHelperPlugin.getWAVES().get(waveIndex + 1);
addWaveInfo("Next wave", waveContents);
}
return panelComponent.render(graphics);
}
private void addWaveInfo(final String headerText, final Map<WaveMonster, Integer> waveContents)
{
panelComponent.getChildren().add(TitleComponent.builder()
.text(headerText)
.color(HEADER_COLOR)
.build());
for (LineComponent line : buildWaveLines(waveContents))
{
panelComponent.getChildren().add(line);
}
}
private static Collection<LineComponent> buildWaveLines(final Map<WaveMonster, Integer> wave)
{
final List<Map.Entry<WaveMonster, Integer>> monsters = new ArrayList<>(wave.entrySet());
monsters.sort(Map.Entry.comparingByKey());
final List<LineComponent> outputLines = new ArrayList<>();
for (Map.Entry<WaveMonster, Integer> monsterEntry : monsters)
{
final WaveMonster monster = monsterEntry.getKey();
final int quantity = monsterEntry.getValue();
final LineComponent line = LineComponent.builder()
.left(FightCaveWaveHelperPlugin.formatMonsterQuantity(monster, quantity))
.build();
outputLines.add(line);
}
return outputLines;
}
}

View File

@@ -0,0 +1,43 @@
package net.runelite.client.plugins.freezetimers;
import net.runelite.api.Actor;
import net.runelite.client.plugins.freezetimers.Spell;
import net.runelite.client.util.Text;
public class Barrage
extends Spell {
public static final long DURATION = 20000L;
private long remainingTime;
private boolean isFinished;
public Barrage(Actor affectedTarget, Actor caster) {
super(affectedTarget, caster);
}
public long getRemainingTime() {
long elapsedTime = System.currentTimeMillis() - this.startTime;
if (Barrage.getDURATION() > elapsedTime) {
return Barrage.getDURATION() - elapsedTime;
}
this.isFinished = true;
return 0L;
}
public boolean equals(Object o) {
if (o instanceof Barrage) {
Barrage barrage = (Barrage)o;
return Text.standardize(this.getAffectedTarget().getName()).equals(Text.standardize(((Barrage)o).getAffectedTarget().getName())) && this.getStartTime() == ((Barrage)o).getStartTime();
}
return false;
}
public static long getDURATION() {
return 20000L;
}
@Override
public boolean isFinished() {
return this.isFinished;
}
}

View File

@@ -0,0 +1,51 @@
package net.runelite.client.plugins.freezetimers;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(value="freezetimers")
public interface FreezeTimersConfig
extends Config {
@ConfigItem(position=0, keyName="freezeenable", name="Enable PvP freeze timers", description="Configures whether or not to show freeze timers.")
default public boolean EnableFreezeTimers() {
return false;
}
@ConfigItem(position=1, keyName="tilehighlight", name="Frozen opponent tile highlighting", description="Configures whether or not to highlight tiles frozen opponents are standing on.")
default public boolean drawTiles() {
return false;
}
@ConfigItem(position=2, keyName="timercolor", name="Freeze Timer Color", description="Color of freeze timer")
default public Color FreezeTimerColor() {
return new Color(0, 184, 212);
}
@ConfigItem(position=3, keyName="spellIcon", name="Show spell icon", description="Shows the spell icon for the freeze spell affecting the target")
default public boolean spellIcon() {
return true;
}
@ConfigItem(position=4, keyName="refreezeTimer", name="Refreeze Timer", description="Show a timer that counts up until the target can be refrozen")
default public boolean refreezeTimer() {
return true;
}
@ConfigItem(position=5, keyName="refreezeTimerColor", name="Refreeze color", description="The color for the timer that counts until the target can be refrozen")
default public Color RefreezeTimerColor() {
return Color.red;
}
@ConfigItem(position = 6, keyName = "tbtimer", name = "Tele Block Timer", description = "Enables tele block timer")
default boolean TBTimer() {
return true;
}
@ConfigItem(position = 7, keyName = "timerpos", name = "Freeze Timer Position", description = "Position of freeze timer")
default int FreezeTimerPos() {
return 80;
}
}

View File

@@ -0,0 +1,157 @@
package net.runelite.client.plugins.freezetimers;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.image.BufferedImage;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.HeadIcon;
import net.runelite.api.Player;
import net.runelite.api.Point;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.freezetimers.FreezeTimersConfig;
import net.runelite.client.plugins.freezetimers.FreezeTimersPlugin;
import net.runelite.client.plugins.freezetimers.FreezeTimersService;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
@Singleton
public class FreezeTimersOverlay
extends Overlay {
private final FreezeTimersService FreezeTimersService;
private final FreezeTimersConfig config;
private final FreezeTimersPlugin plugin;
private final SpriteManager spriteManager;
private final Client client;
@Inject
private FreezeTimersOverlay(FreezeTimersConfig config, FreezeTimersService FreezeTimersService2, FreezeTimersPlugin plugin, Client client, SpriteManager spriteManager) {
this.config = config;
this.FreezeTimersService = FreezeTimersService2;
this.plugin = plugin;
this.client = client;
this.spriteManager = spriteManager;
this.setPosition(OverlayPosition.DYNAMIC);
this.setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics) {
if (!this.config.EnableFreezeTimers()) {
return null;
}
this.FreezeTimersService.forEachPlayer((player, color) -> this.renderPlayerOverlay(graphics, (Player)player, (Color)color));
return null;
}
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color) {
BufferedImage clanchatImage;
int timer = 0;
String name = actor.getName();
int freezetype = this.plugin.freezetype(name);
boolean frozenoverlay = false;
int offset = 5;
long dtime = this.plugin.opponentfreezetime(name);
long tbed = plugin.istbed(name);
Point textLocation = null;
HeadIcon headIcon = actor.getOverheadIcon();
int freezetime = 0;
if (freezetype == 1 || freezetype == 4) {
freezetime = 5000;
} else if (freezetype == 2 || freezetype == 5) {
freezetime = 10000;
} else if (freezetype == 3 || freezetype == 6) {
freezetime = 15000;
} else if (freezetype == 7) {
freezetime = 20000;
} else if (freezetype == 8) {
freezetime = 2500;
} else if (freezetype == 9) {
freezetime = 5000;
} else if (freezetype == 10) {
freezetime = 7500;
}
long currenttime = System.currentTimeMillis();
long timediff = currenttime - dtime;
timer = (freezetime - (int)timediff) / 1000;
if (timediff < (long)freezetime) {
textLocation = actor.getCanvasTextLocation(graphics, String.valueOf(timer), actor.getLogicalHeight() + config.FreezeTimerPos());
textLocation = new Point(textLocation.getX(), textLocation.getY() - config.FreezeTimerPos());
} else if (timediff < (long)(freezetime + 3000)) {
timer = Math.abs(timer);
++timer;
if (this.config.refreezeTimer()) {
textLocation = actor.getCanvasTextLocation(graphics, String.valueOf(timer), actor.getLogicalHeight() + config.FreezeTimerPos());
textLocation = new Point(textLocation.getX(), textLocation.getY() - config.FreezeTimerPos());
graphics.setFont(FontManager.getRunescapeBoldFont());
if (headIcon != null) {
textLocation = new Point(textLocation.getX(), textLocation.getY() - config.FreezeTimerPos());
}
frozenoverlay = true;
OverlayUtil.renderTextLocation(graphics, textLocation, String.valueOf(timer), this.config.RefreezeTimerColor());
return;
}
} else {
this.plugin.deleteopponent(name);
}
if (textLocation != null && (clanchatImage = this.plugin.GetFreezeIcon(freezetype - 1)) != null) {
int width = clanchatImage.getWidth();
int textHeight = graphics.getFontMetrics().getHeight() - graphics.getFontMetrics().getMaxDescent();
Point imageLocation = new Point(textLocation.getX(), textLocation.getY() - (config.FreezeTimerPos() / 2));
graphics.setFont(FontManager.getRunescapeFont());
graphics.setStroke(new BasicStroke(3.0f));
if (this.config.spellIcon()) {
frozenoverlay = true;
graphics.drawOval(imageLocation.getX(), imageLocation.getY(), clanchatImage.getWidth(), clanchatImage.getHeight());
OverlayUtil.renderImageLocation(graphics, imageLocation, clanchatImage);
OverlayUtil.renderTextLocation(graphics, textLocation, String.valueOf(timer), color);
} else {
graphics.setColor(Color.cyan);
graphics.drawOval(textLocation.getX() - 3, textLocation.getY() - 15, clanchatImage.getWidth(), graphics.getFontMetrics().getHeight());
graphics.setColor(Color.blue);
graphics.fillOval(textLocation.getX() - 3, textLocation.getY() - 15, clanchatImage.getWidth(), graphics.getFontMetrics().getHeight());
OverlayUtil.renderTextLocation(graphics, textLocation, String.valueOf(timer), Color.WHITE);
}
}
if (config.TBTimer()) {
if (tbed > 0) {
int type = plugin.tbtype(name);
int tbexpiry;
if (type > 0) {
if (type == 1) {
tbexpiry = 300000;
} else if (type == 2) {
tbexpiry = 150000;
} else {
return;
}
long tbtime = currenttime - tbed;
int tbtimer = (tbexpiry - (int) tbtime) / 1000;
if (tbtime < tbexpiry) {
textLocation = actor.getCanvasTextLocation(graphics, Integer.toString(tbtimer), actor.getLogicalHeight() + config.FreezeTimerPos());
if (frozenoverlay) {
textLocation = new Point(textLocation.getX() + 40, textLocation.getY() - config.FreezeTimerPos());
} else {
textLocation = new Point(textLocation.getX(), textLocation.getY() - config.FreezeTimerPos());
}
} else {
plugin.deletetb(name);
}
}
}
}
}
}

View File

@@ -0,0 +1,402 @@
package net.runelite.client.plugins.freezetimers;
import com.google.inject.Provides;
import java.awt.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.*;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.ImageObserver;
import java.awt.image.IndexColorModel;
import java.awt.image.WritableRaster;
import java.util.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.events.*;
import net.runelite.api.GameState;
import net.runelite.api.HeadIcon;
import net.runelite.api.IndexedSprite;
import net.runelite.api.Player;
import net.runelite.api.Skill;
import net.runelite.api.coords.WorldPoint;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.ExperienceChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.freezetimers.Barrage;
import net.runelite.client.plugins.freezetimers.FreezeTimersConfig;
import net.runelite.client.plugins.freezetimers.FreezeTimersOverlay;
import net.runelite.client.plugins.freezetimers.FreezeTimersTileOverlay;
import net.runelite.client.plugins.freezetimers.Spell;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ImageUtil;
import org.slf4j.Logger;
@PluginDescriptor(
name = "<font color=\"aqua\">!Freeze Timers</font>",
description = "PVP Freeze Timers",
tags = {"PvP", "Freeze", "Timers"}
)
public class FreezeTimersPlugin
extends Plugin {
@Inject
private OverlayManager overlayManager;
@Inject
private FreezeTimersConfig config;
@Inject
private FreezeTimersOverlay FreezeTimersOverlay;
@Inject
private FreezeTimersTileOverlay FreezeTimersTileOverlay;
@Inject
private Client client;
@Inject
private SpriteManager spriteManager;
private static final int[] FREEZE_ICONS = {
SpriteID.SPELL_BIND,
SpriteID.SPELL_SNARE,
SpriteID.SPELL_ENTANGLE,
SpriteID.SPELL_ICE_RUSH,
SpriteID.SPELL_ICE_BURST,
SpriteID.SPELL_ICE_BLITZ,
SpriteID.SPELL_ICE_BARRAGE,
SpriteID.SPELL_BIND,
SpriteID.SPELL_SNARE,
SpriteID.SPELL_ENTANGLE,
SpriteID.SPELL_TELE_BLOCK
};
private static final Dimension FREEZE_ICON_DIMENSION = new Dimension(25, 25);
private static final Color FREEZE_ICON_OUTLINE_COLOR = new Color(33, 33, 33);
private final BufferedImage[] FreezeIcons = new BufferedImage[FREEZE_ICONS.length];
private final int SPLASH_ID = 85;
Map<String, Long> tbedthings = new HashMap<>();
Map<String, Integer> tbtypes = new HashMap<>();
Map<String, Spell> testMap = new HashMap<String, Spell>();
Map<String, Long> frozenthings = new HashMap<String, Long>();
Map<String, WorldPoint> frozenthingpoints = new HashMap<String, WorldPoint>();
Map<String, Integer> freezetype = new HashMap<String, Integer>();
Map<Integer, Integer> magexp = new HashMap<Integer, Integer>();
int lastxp;
int ticks;
int currticks;
String currtarget;
String spell;
@Provides
FreezeTimersConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(FreezeTimersConfig.class);
}
@Subscribe
public void onGameStateChanged(GameStateChanged gameStateChanged) {
if (gameStateChanged.getGameState() == GameState.LOGGED_IN) {
this.loadFreezeIcons();
}
}
@Override
protected void startUp() throws Exception {
this.overlayManager.add(this.FreezeTimersOverlay);
this.overlayManager.add(this.FreezeTimersTileOverlay);
}
@Override
protected void shutDown() throws Exception {
this.overlayManager.remove(this.FreezeTimersOverlay);
this.overlayManager.remove(this.FreezeTimersTileOverlay);
this.frozenthings.clear();
this.frozenthingpoints.clear();
this.tbedthings.clear();
this.tbtypes.clear();
}
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event) {
if (event.getMenuTarget().contains("->")) {
Pattern spattern = Pattern.compile(">(.+?)</col>");
Pattern ppattern = Pattern.compile("> <col=ffffff>(.+?)<col=");
Matcher smatch = spattern.matcher(event.getMenuTarget());
Matcher pmatch = ppattern.matcher(event.getMenuTarget());
smatch.find();
pmatch.find();
if (smatch.group(1) != null && pmatch.group(1) != null) {
this.currticks = this.ticks;
this.spell = smatch.group(1);
this.currtarget = pmatch.group(1).replace("\u00a0", " ");
}
}
}
@Subscribe
public void onExperienceChanged(ExperienceChanged event) {
if (event.getSkill() == Skill.MAGIC) {
int xp = this.client.getSkillExperience(Skill.MAGIC);
int gains = xp - this.lastxp;
this.lastxp = xp;
if (!this.magexp.containsKey(this.ticks)) {
this.magexp.clear();
this.magexp.put(this.ticks, gains);
}
}
}
@Subscribe
private void onAnimationChanged(AnimationChanged event) {
Logger l = this.client.getLogger();
Actor subject = event.getActor();
Actor target = subject.getInteracting();
if (subject.getAnimation() == 1979) {
try {
if (target.getGraphic() == 85 || target.getGraphic() != -1) {
return;
}
if (this.frozenthings.containsKey(target.getName())) {
return;
}
this.testMap.put(target.getName(), new Barrage(target, subject));
this.freezetype.put(target.getName(), 7);
this.frozenthings.put(target.getName(), System.currentTimeMillis());
this.frozenthingpoints.put(target.getName(), target.getWorldLocation());
}
catch (NullPointerException nullPointerException) {
// empty catch block
}
}
}
@Subscribe
public void onGameTick(GameTick event) {
int xp = 0;
boolean praymage = false;
if (this.magexp.containsKey(this.ticks)) {
xp = this.magexp.get(this.ticks);
}
if (xp > 0 && this.currtarget != null) {
if (this.frozenthings.containsKey(this.currtarget)) {
this.currtarget = null;
return;
}
WorldPoint targetPosition = null;
for (Player player : this.client.getPlayers()) {
String playerName;
if (player == null || !(playerName = player.getName()).equals(this.currtarget)) continue;
if (player.getOverheadIcon() != null && player.getOverheadIcon().equals((Object)HeadIcon.MAGIC)) {
praymage = true;
}
targetPosition = player.getWorldLocation();
break;
}
if (targetPosition != null) {
if (this.spell.equals("Bind") && xp > 30) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
if (praymage) {
this.freezetype.put(this.currtarget, 8);
} else {
this.freezetype.put(this.currtarget, 1);
}
} else if (this.spell.equals("Snare") && xp > 60) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
if (praymage) {
this.freezetype.put(this.currtarget, 9);
} else {
this.freezetype.put(this.currtarget, 2);
}
} else if (this.spell.equals("Entangle") && xp >= 89) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
if (praymage) {
this.freezetype.put(this.currtarget, 10);
} else {
this.freezetype.put(this.currtarget, 3);
}
} else if (this.spell.equals("Ice Rush") && xp > 34) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
this.freezetype.put(this.currtarget, 4);
} else if (this.spell.equals("Ice Burst") && xp > 40) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
this.freezetype.put(this.currtarget, 5);
} else if (this.spell.equals("Ice Blitz") && xp > 46) {
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
this.freezetype.put(this.currtarget, 6);
} else if (this.spell.equals("Ice Barrage") && xp > 52) {
Barrage barrage = new Barrage(this.client.getLocalPlayer().getInteracting(), this.client.getLocalPlayer());
this.testMap.put(this.currtarget, barrage);
this.frozenthings.put(this.currtarget, System.currentTimeMillis());
this.frozenthingpoints.put(this.currtarget, targetPosition);
this.freezetype.put(this.currtarget, 7);
} else if (spell.equals("Tele Block") && xp == 95) {
if (config.TBTimer()) {
if (praymage) {
this.tbtypes.put(this.currtarget, 2);
} else {
this.tbtypes.put(this.currtarget, 1);
}
this.tbedthings.put(this.currtarget, System.currentTimeMillis());
}
}
}
}
if (this.currtarget != null && this.ticks > this.currticks + 1) {
Player local = this.client.getLocalPlayer();
Actor interacting = local.getInteracting();
if (interacting != null) {
if (!interacting.getName().equals(this.currtarget)) {
this.currtarget = null;
}
} else {
this.currtarget = null;
}
}
++this.ticks;
}
public long opponentfreezetime(String name) {
if (this.frozenthings.containsKey(name)) {
return this.frozenthings.get(name);
}
return 0L;
}
public WorldPoint playerpos(String name) {
if (this.frozenthingpoints.containsKey(name)) {
return this.frozenthingpoints.get(name);
}
return null;
}
public void updatePosition(String name, WorldPoint point) {
if (this.frozenthingpoints.containsKey(name)) {
this.frozenthingpoints.remove(name);
this.frozenthingpoints.put(name, point);
}
}
public int freezetype(String name) {
if (this.freezetype.containsKey(name)) {
return this.freezetype.get(name);
}
return 0;
}
public long istbed(String name) {
if (this.tbedthings.containsKey(name)) {
return this.tbedthings.get(name);
}
return 0;
}
public int tbtype(String name) {
if (this.tbtypes.containsKey(name)) {
return this.tbtypes.get(name);
}
return 0;
}
public void deleteopponent(String name) {
if (this.frozenthings.containsKey(name)) {
this.frozenthings.remove(name);
}
if (this.frozenthingpoints.containsKey(name)) {
this.frozenthingpoints.remove(name);
}
if (this.freezetype.containsKey(name)) {
this.freezetype.remove(name);
}
}
public void deletetb(String name) {
if (this.tbedthings.containsKey(name)) {
this.tbedthings.remove(name);
}
if (this.tbtypes.containsKey(name)) {
this.tbtypes.remove(name);
}
}
private void loadFreezeIcons() {
IndexedSprite[] freezeIcons = new IndexedSprite[]{};
IndexedSprite[] newfreezeIcons = Arrays.copyOf(freezeIcons, FREEZE_ICONS.length);
int curPosition = 0;
int i = 0;
while (i < FREEZE_ICONS.length) {
int resource = FREEZE_ICONS[i];
this.FreezeIcons[i] = FreezeTimersPlugin.rgbaToIndexedBufferedImage(FreezeTimersPlugin.FreezeIconFromSprite(this.spriteManager.getSprite(resource, 0)));
newfreezeIcons[curPosition] = FreezeTimersPlugin.createIndexedSprite(this.client, this.FreezeIcons[i]);
++i;
++curPosition;
}
}
private static IndexedSprite createIndexedSprite(Client client, BufferedImage bufferedImage) {
IndexColorModel indexedCM = (IndexColorModel)bufferedImage.getColorModel();
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
byte[] pixels = ((DataBufferByte)bufferedImage.getRaster().getDataBuffer()).getData();
int[] palette = new int[indexedCM.getMapSize()];
indexedCM.getRGBs(palette);
IndexedSprite newIndexedSprite = client.createIndexedSprite();
newIndexedSprite.setPixels(pixels);
newIndexedSprite.setPalette(palette);
newIndexedSprite.setWidth(width);
newIndexedSprite.setHeight(height);
newIndexedSprite.setOriginalWidth(width);
newIndexedSprite.setOriginalHeight(height);
newIndexedSprite.setOffsetX(0);
newIndexedSprite.setOffsetY(0);
return newIndexedSprite;
}
private static BufferedImage rgbaToIndexedBufferedImage(BufferedImage sourceBufferedImage) {
BufferedImage indexedImage = new BufferedImage(sourceBufferedImage.getWidth(), sourceBufferedImage.getHeight(), 13);
ColorModel cm = indexedImage.getColorModel();
IndexColorModel icm = (IndexColorModel)cm;
int size = icm.getMapSize();
byte[] reds = new byte[size];
byte[] greens = new byte[size];
byte[] blues = new byte[size];
icm.getReds(reds);
icm.getGreens(greens);
icm.getBlues(blues);
WritableRaster raster = indexedImage.getRaster();
int pixel = raster.getSample(0, 0, 0);
IndexColorModel resultIcm = new IndexColorModel(8, size, reds, greens, blues, pixel);
BufferedImage resultIndexedImage = new BufferedImage(resultIcm, raster, sourceBufferedImage.isAlphaPremultiplied(), null);
resultIndexedImage.getGraphics().drawImage(sourceBufferedImage, 0, 0, null);
return resultIndexedImage;
}
private static BufferedImage FreezeIconFromSprite(BufferedImage freezeSprite) {
BufferedImage freezeCanvas = ImageUtil.resizeCanvas(freezeSprite, FreezeTimersPlugin.FREEZE_ICON_DIMENSION.width, FreezeTimersPlugin.FREEZE_ICON_DIMENSION.height);
return ImageUtil.outlineImage(freezeCanvas, FREEZE_ICON_OUTLINE_COLOR);
}
BufferedImage GetFreezeIcon(int id) {
return this.FreezeIcons[id];
}
}

View File

@@ -0,0 +1,81 @@
package net.runelite.client.plugins.freezetimers;
import java.awt.Color;
import java.util.List;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import javax.inject.Singleton;
import net.runelite.api.Client;
import net.runelite.api.Player;
import net.runelite.api.coords.WorldPoint;
import net.runelite.client.plugins.freezetimers.FreezeTimersConfig;
import net.runelite.client.plugins.freezetimers.FreezeTimersPlugin;
@Singleton
public class FreezeTimersService {
private final Client client;
private final FreezeTimersConfig config;
private final FreezeTimersPlugin plugin;
@Inject
private FreezeTimersService(Client client, FreezeTimersConfig config, FreezeTimersPlugin plugin) {
this.config = config;
this.plugin = plugin;
this.client = client;
}
public void forEachPlayer(BiConsumer<Player, Color> consumer) {
for (Player player : this.client.getPlayers()) {
if (player == null || player.getName() == null) continue;
String name = player.getName();
int freezetype = this.plugin.freezetype(name);
long tbed = plugin.istbed(name);
long dtime = this.plugin.opponentfreezetime(name);
int freezetime = 0;
if (freezetype == 1 || freezetype == 4) {
freezetime = 5000;
} else if (freezetype == 2 || freezetype == 5) {
freezetime = 10000;
} else if (freezetype == 3 || freezetype == 6) {
freezetime = 15000;
} else if (freezetype == 7) {
freezetime = 20000;
} else if (freezetype == 8) {
freezetime = 2500;
} else if (freezetype == 9) {
freezetime = 5000;
} else if (freezetype == 10) {
freezetime = 7500;
}
if (dtime <= 0L) continue;
long currenttime = System.currentTimeMillis();
long timediff = currenttime - dtime;
if (timediff < (long)freezetime) {
WorldPoint lastWorldPoint;
WorldPoint currentWorldPoint = player.getWorldLocation();
if (currentWorldPoint.equals(lastWorldPoint = this.plugin.playerpos(name))) {
consumer.accept(player, this.config.FreezeTimerColor());
continue;
}
if (timediff < 605L) {
this.plugin.updatePosition(name, currentWorldPoint);
consumer.accept(player, this.config.FreezeTimerColor());
continue;
}
this.plugin.deleteopponent(name);
continue;
}
if (timediff < (long)(freezetime + 3000)) {
consumer.accept(player, Color.YELLOW);
continue;
} else {
this.plugin.deleteopponent(name);
}
if (tbed > 0) {
consumer.accept(player, config.FreezeTimerColor());
return;
}
}
}
}

View File

@@ -0,0 +1,46 @@
package net.runelite.client.plugins.freezetimers;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.util.function.BiConsumer;
import javax.inject.Inject;
import net.runelite.api.Player;
import net.runelite.client.plugins.freezetimers.FreezeTimersConfig;
import net.runelite.client.plugins.freezetimers.FreezeTimersService;
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;
public class FreezeTimersTileOverlay
extends Overlay {
private final FreezeTimersService FreezeTimersService;
private final FreezeTimersConfig config;
@Inject
private FreezeTimersTileOverlay(FreezeTimersConfig config, FreezeTimersService FreezeTimersService2) {
this.config = config;
this.FreezeTimersService = FreezeTimersService2;
this.setLayer(OverlayLayer.ABOVE_SCENE);
this.setPosition(OverlayPosition.DYNAMIC);
this.setPriority(OverlayPriority.MED);
}
@Override
public Dimension render(Graphics2D graphics) {
if (!this.config.drawTiles()) {
return null;
}
this.FreezeTimersService.forEachPlayer((player, color) -> {
Polygon poly = player.getCanvasTilePoly();
if (poly != null) {
OverlayUtil.renderPolygon(graphics, poly, color);
}
});
return null;
}
}

View File

@@ -0,0 +1,35 @@
package net.runelite.client.plugins.freezetimers;
public enum PlayerSpellEffect {
BARRAGE("Ice Barrage", 20000, false),
BLITZ("Ice Blitz", 15000, false);
private final String SPELL_NAME;
private long startTime;
private int duration;
private boolean halvable;
private PlayerSpellEffect(String name, int duration, boolean halvable) {
this.SPELL_NAME = name;
this.duration = duration;
this.halvable = halvable;
this.startTime = System.currentTimeMillis();
}
public String getSPELL_NAME() {
return this.SPELL_NAME;
}
public long getStartTime() {
return this.startTime;
}
public int getDuration() {
return this.duration;
}
public boolean isHalvable() {
return this.halvable;
}
}

View File

@@ -0,0 +1,34 @@
package net.runelite.client.plugins.freezetimers;
import net.runelite.api.Actor;
public abstract class Spell {
private final Actor affectedTarget;
private final Actor caster;
public final long startTime;
private long remainingTime;
private boolean isFinished;
protected Spell(Actor affectedTarget, Actor caster) {
this.affectedTarget = affectedTarget;
this.caster = caster;
this.startTime = System.currentTimeMillis();
}
public Actor getAffectedTarget() {
return this.affectedTarget;
}
public Actor getCaster() {
return this.caster;
}
public long getStartTime() {
return this.startTime;
}
public boolean isFinished() {
return this.isFinished;
}
}

View File

@@ -0,0 +1,162 @@
package net.runelite.client.plugins.friendtagging;
import com.google.common.base.Strings;
import com.google.common.collect.ObjectArrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import javax.inject.Inject;
import lombok.NonNull;
import net.runelite.api.Client;
import net.runelite.api.Friend;
import net.runelite.api.MenuAction;
import net.runelite.api.MenuEntry;
import net.runelite.api.Nameable;
import net.runelite.api.events.MenuEntryAdded;
import net.runelite.api.events.MenuOptionClicked;
import net.runelite.api.events.NameableNameChanged;
import net.runelite.api.events.RemovedFriend;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.chatbox.ChatboxPanelManager;
import net.runelite.client.game.chatbox.ChatboxTextInput;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.util.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@PluginDescriptor(
name="Friend Tagging",
description="Tag people on your friends list."
)
public class FriendTaggingPlugin extends Plugin
{
private static final Logger log = LoggerFactory.getLogger(FriendTaggingPlugin.class);
public static ConcurrentHashMap<String, String> taggedFriends = new ConcurrentHashMap();
private static final String CONFIG_GROUP = "friendtagging";
private static final int CHARACTER_LIMIT = 30;
private static final String KEY_PREFIX = "tag_";
private static final String ADD_TAG = "Add Tag";
private static final String DELETE_TAG = "Delete Tag";
@Inject
private Client client;
@Inject
private ConfigManager configManager;
@Inject
private ChatboxPanelManager chatboxPanelManager;
@Override
protected void startUp() throws Exception {
this.loadFriendTags();
}
@Override
protected void shutDown() throws Exception {
super.shutDown();
}
@Subscribe
public void onMenuEntryAdded(MenuEntryAdded event) {
int groupId = WidgetInfo.TO_GROUP(event.getActionParam1());
if (groupId == WidgetInfo.FRIENDS_LIST.getGroupId() && event.getOption().equals("Message")) {
String friendName = Text.removeTags(event.getTarget());
MenuEntry entry = new MenuEntry();
entry.setOption(friendName == null || this.getTag(friendName) == null ? ADD_TAG : DELETE_TAG);
entry.setType(MenuAction.RUNELITE.getId());
entry.setTarget(event.getTarget());
entry.setParam0(event.getActionParam0());
entry.setParam1(event.getActionParam1());
MenuEntry[] menuEntries = ObjectArrays.concat(this.client.getMenuEntries(), entry);
this.client.setMenuEntries(menuEntries);
}
}
@Subscribe
public void onRemovedFriend(RemovedFriend event) {
String displayName = event.getName().trim().toLowerCase();
this.deleteTag(displayName);
}
@Subscribe
public void onNameableNameChanged(NameableNameChanged event) {
Friend friend;
Nameable nameable = event.getNameable();
if (nameable instanceof Friend && (friend = (Friend)nameable).getName() != null && friend.getPrevName() != null) {
this.migrateFriendTag(friend.getName(), friend.getPrevName());
}
}
@Subscribe
public void onMenuOptionClicked(MenuOptionClicked event) {
if (WidgetInfo.TO_GROUP(event.getWidgetId()) == WidgetInfo.FRIENDS_LIST.getGroupId()) {
if (Strings.isNullOrEmpty(event.getMenuTarget())) {
return;
}
String sanitizedTarget = Text.removeTags(event.getMenuTarget());
if (event.getMenuOption().equals(ADD_TAG)) {
event.consume();
ChatboxTextInput chatboxTextInput = this.chatboxPanelManager.openTextInput("Enter the tag").value("").onDone(content -> {
if (content == null) {
return;
}
content = Text.removeTags(content).trim();
this.setTag(sanitizedTarget, (String)content);
}).build();
}
if (event.getMenuOption().equals(DELETE_TAG)) {
event.consume();
this.client.getLogger().info(sanitizedTarget);
taggedFriends.forEach((k, v) -> this.client.getLogger().info(k + ": ", v));
this.deleteTag(sanitizedTarget);
}
}
}
@NonNull
private String getTag(String name) {
name = name.trim().toLowerCase();
String keyName = KEY_PREFIX + name;
return taggedFriends.get(keyName);
}
private void setTag(String name, String tag) {
this.client.getLogger().info("SETTING " + name + ": " + tag);
name = name.trim().toLowerCase();
String keyName = KEY_PREFIX + name;
if (tag.length() <= 30) {
taggedFriends.put(keyName, tag);
this.configManager.setConfiguration(CONFIG_GROUP, keyName, tag);
}
}
private void deleteTag(String name) {
name = name.trim().toLowerCase();
String keyName = KEY_PREFIX + name;
this.configManager.unsetConfiguration(CONFIG_GROUP, keyName);
taggedFriends.remove(keyName);
}
private void loadFriendTags() {
String prefix = "friendtagging.tag_";
for (String key : this.configManager.getConfigurationKeys(prefix)) {
String result = this.configManager.getConfiguration(CONFIG_GROUP, key = key.replace("friendtagging.", ""));
if (!Objects.nonNull(result) || result.equals("")) continue;
taggedFriends.put(key, this.configManager.getConfiguration(CONFIG_GROUP, key));
}
}
private void migrateFriendTag(String currentDisplayName, String prevDisplayName) {
String prevTag;
String currentTag = this.getTag(currentDisplayName);
if (currentTag == null && (prevTag = this.getTag(prevDisplayName)) != null) {
this.setTag(prevDisplayName, "");
this.setTag(currentDisplayName, prevTag);
}
}
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2018, Damen <https://github.com/basicDamen>
* 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.grotesqueguardians;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Polygon;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.GraphicsObject;
import net.runelite.api.Perspective;
import net.runelite.api.coords.LocalPoint;
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;
class GrotesqueGuardiansOverlay extends Overlay
{
private static final int GROTESQUE_GUARDIANS_REGION_ID = 6727;
private final Client client;
private static final int GROTESQUE_GUARDIANS_LIGHTNING_START = 1416;
private static final int GROTESQUE_GUARDIANS_LIGHTNING_END = 1431;
private static final int GROTESQUE_GUARDIANS_FALLING_ROCKS = 1436;
private static final int GROTESQUE_GUARDIANS_STONE_ORB = 160;
@Inject
private GrotesqueGuardiansOverlay(Client client)
{
this.client = client;
setPosition(OverlayPosition.DYNAMIC);
setLayer(OverlayLayer.ABOVE_SCENE);
setPriority(OverlayPriority.LOW);
}
@Override
public Dimension render(Graphics2D graphics)
{
if (!client.isInInstancedRegion() || client.getMapRegions()[0] != GROTESQUE_GUARDIANS_REGION_ID)
{
return null;
}
// TODO: Awaiting GraphicsObjectDespawn event to be tracked to make this more efficient.
for (GraphicsObject graphicsObject : client.getGraphicsObjects())
{
Color color = null;
if (graphicsObject.getId() >= GROTESQUE_GUARDIANS_LIGHTNING_START && graphicsObject.getId() <= GROTESQUE_GUARDIANS_LIGHTNING_END)
{
color = Color.ORANGE;
}
else if (graphicsObject.getId() == GROTESQUE_GUARDIANS_STONE_ORB)
{
color = Color.GRAY;
}
else if (graphicsObject.getId() == GROTESQUE_GUARDIANS_FALLING_ROCKS)
{
color = Color.YELLOW;
}
else
{
continue;
}
LocalPoint lp = graphicsObject.getLocation();
Polygon poly = Perspective.getCanvasTilePoly(client, lp);
if (poly != null)
{
OverlayUtil.renderPolygon(graphics, poly, color);
}
}
return null;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018, Damen <https://github.com/basicDamen>
* 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.grotesqueguardians;
import javax.inject.Inject;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "<font color=\"#4863A0\">!Grotesque Guardians</font>",
description = "Display tile indicators for the Grotesque Guardian special attacks",
tags = {"grotesque", "guardians", "gargoyle", "garg"}
)
public class GrotesqueGuardiansPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private GrotesqueGuardiansOverlay overlay;
@Override
protected void startUp() throws Exception
{
overlayManager.add(overlay);
}
@Override
protected void shutDown() throws Exception
{
overlayManager.remove(overlay);
}
}

View File

@@ -0,0 +1,35 @@
package net.runelite.client.plugins.hideprayers;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("hideprayers")
public interface HidePrayersConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "pk prayers",
name = "Hides none pk prayers",
description = "Hides widget icons."
)
default boolean showPrayers() { return false; }
@ConfigItem(
position = 1,
keyName = "eagle/mystic",
name = "Shows eagle and mystic prayers",
description = "Hides widget icons."
)
default boolean showEagleMystic() { return false; }
@ConfigItem(
position = 1,
keyName = "ultstr",
name = "Shows ultimate strength",
description = "Hides widget icons."
)
default boolean showUltStrength() { return false; }
}

View File

@@ -0,0 +1,169 @@
package net.runelite.client.plugins.hideprayers;
import com.google.common.collect.ImmutableList;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import net.runelite.api.*;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameStateChanged;
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.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import javax.inject.Inject;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@PluginDescriptor(
name = "<font color=\"green\">!Hide Prayers</font>",
description = "Hides specific Prayers in the Prayer tab."
)
public class HidePrayersPlugin extends Plugin {
private static final int PRAYER_COUNT = Prayer.values().length;
private static final List<WidgetInfo> PRAYER_WIDGET_INFO_LIST = ImmutableList.of(WidgetInfo.PRAYER_THICK_SKIN,
WidgetInfo.PRAYER_BURST_OF_STRENGTH, WidgetInfo.PRAYER_CLARITY_OF_THOUGHT, WidgetInfo.PRAYER_SHARP_EYE,
WidgetInfo.PRAYER_MYSTIC_WILL, WidgetInfo.PRAYER_ROCK_SKIN, WidgetInfo.PRAYER_SUPERHUMAN_STRENGTH,
WidgetInfo.PRAYER_IMPROVED_REFLEXES, WidgetInfo.PRAYER_RAPID_RESTORE, WidgetInfo.PRAYER_RAPID_HEAL,
WidgetInfo.PRAYER_PROTECT_ITEM, WidgetInfo.PRAYER_HAWK_EYE, WidgetInfo.PRAYER_MYSTIC_LORE,
WidgetInfo.PRAYER_STEEL_SKIN, WidgetInfo.PRAYER_ULTIMATE_STRENGTH, WidgetInfo.PRAYER_INCREDIBLE_REFLEXES,
WidgetInfo.PRAYER_PROTECT_FROM_MAGIC, WidgetInfo.PRAYER_PROTECT_FROM_MISSILES,
WidgetInfo.PRAYER_PROTECT_FROM_MELEE, WidgetInfo.PRAYER_EAGLE_EYE, WidgetInfo.PRAYER_MYSTIC_MIGHT,
WidgetInfo.PRAYER_RETRIBUTION, WidgetInfo.PRAYER_REDEMPTION, WidgetInfo.PRAYER_SMITE,
WidgetInfo.PRAYER_PRESERVE, WidgetInfo.PRAYER_CHIVALRY, WidgetInfo.PRAYER_PIETY, WidgetInfo.PRAYER_RIGOUR,
WidgetInfo.PRAYER_AUGURY);
@Inject
private Client client;
@Inject
private HidePrayersConfig config;
@Provides
HidePrayersConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(HidePrayersConfig.class);
}
@Override
protected void startUp() throws Exception {
hidePrayers();
}
@Override
protected void shutDown() throws Exception {
restorePrayers();
}
@Subscribe
public void onGameStateChanged(GameStateChanged event) {
if (event.getGameState() == GameState.LOGGED_IN) {
hidePrayers();
}
}
@Subscribe
public void onConfigChanged(ConfigChanged event) {
if (event.getGroup().equals("hideprayers")) {
hidePrayers();
}
}
@Subscribe
public void onWidgetLoaded(WidgetLoaded event) {
if (event.getGroupId() == WidgetID.PRAYER_GROUP_ID || event.getGroupId() == WidgetID.QUICK_PRAYERS_GROUP_ID) {
hidePrayers();
}
}
private PrayerTabState getPrayerTabState() {
HashTable<WidgetNode> componentTable = client.getComponentTable();
for (WidgetNode widgetNode : componentTable.getNodes()) {
if (widgetNode.getId() == WidgetID.PRAYER_GROUP_ID) {
return PrayerTabState.PRAYERS;
} else if (widgetNode.getId() == WidgetID.QUICK_PRAYERS_GROUP_ID) {
return PrayerTabState.QUICK_PRAYERS;
}
}
return PrayerTabState.NONE;
}
private void restorePrayers() {
if (client.getGameState() != GameState.LOGGED_IN)
return;
PrayerTabState prayerTabState = getPrayerTabState();
if (prayerTabState == PrayerTabState.PRAYERS) {
List<Widget> prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget)
.filter(Objects::nonNull).collect(Collectors.toList());
if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size())
return;
for (int index = 0; index < PRAYER_COUNT; index++)
prayerWidgets.get(Prayer.values()[index].ordinal()).setHidden(false);
}
}
private void hidePrayers() {
if (client.getGameState() != GameState.LOGGED_IN)
return;
PrayerTabState prayerTabState = getPrayerTabState();
if (prayerTabState == PrayerTabState.PRAYERS) {
List<Widget> prayerWidgets = PRAYER_WIDGET_INFO_LIST.stream().map(client::getWidget)
.filter(Objects::nonNull).collect(Collectors.toList());
if (prayerWidgets.size() != PRAYER_WIDGET_INFO_LIST.size())
return;
for (int index = 0; index < PRAYER_COUNT; index++) {
Prayer prayer = Prayer.values()[index];
Widget prayerWidget = prayerWidgets.get(prayer.ordinal());
if (!config.showPrayers() && !config.showEagleMystic())
prayerWidget.setHidden(false);
if (config.showPrayers()) {
prayerWidget.setHidden(true);
prayerWidgets.get(Prayer.values()[10].ordinal()).setHidden(false);// protect item
prayerWidgets.get(Prayer.values()[16].ordinal()).setHidden(false);// mage
prayerWidgets.get(Prayer.values()[17].ordinal()).setHidden(false);// range
prayerWidgets.get(Prayer.values()[18].ordinal()).setHidden(false);// melee
prayerWidgets.get(Prayer.values()[23].ordinal()).setHidden(false);// smite
if (config.showEagleMystic()) {
prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(true);// rigour
prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(true);// augury
} else {
prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(false);// rigour
prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(false);// augury
}
if (config.showUltStrength()) {
prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(true);// piety
} else {
prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(false);// piety
}
}
if (config.showEagleMystic()) {
prayerWidget.setHidden(true);
prayerWidgets.get(Prayer.values()[19].ordinal()).setHidden(false);// eagle
prayerWidgets.get(Prayer.values()[20].ordinal()).setHidden(false);// mystic
prayerWidgets.get(Prayer.values()[27].ordinal()).setHidden(true);// rigour
prayerWidgets.get(Prayer.values()[28].ordinal()).setHidden(true);// augury
}
if (config.showUltStrength()) {
prayerWidget.setHidden(true);
prayerWidgets.get(Prayer.values()[14].ordinal()).setHidden(false);// Ult Strength
prayerWidgets.get(Prayer.values()[26].ordinal()).setHidden(true);// piety
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
package net.runelite.client.plugins.hideprayers;
public enum PrayerTabState
{
NONE,
PRAYERS,
QUICK_PRAYERS
}

View File

@@ -0,0 +1,41 @@
package net.runelite.client.plugins.hydra;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup("hydra")
public interface HydraConfig extends Config {
@ConfigItem(
position = 0,
keyName = "hydraenable",
name = "Enable Hydra (194 cb) Helper",
description = "Configures whether or not to enable Hydra Helper. (For use on regular hydra's only, will not work with Alchemical Hydra)."
)
default boolean EnableHydra() { return true; }
@ConfigItem(
position = 1,
keyName = "textindicators",
name = "Text Indicator",
description = "Configures if text indicator is shown above hydra's or not."
)
default boolean TextIndicator() { return true; }
@ConfigItem(
position = 2,
keyName = "countersize",
name = "Bold indicator",
description = "Configures if text indicator is bold or not."
)
default boolean BoldText() { return false; }
@ConfigItem(
position = 3,
keyName = "prayerhelper",
name = "Prayer Helper",
description = "Configures if prayer helper is shown or not."
)
default boolean PrayerHelper() { return true; }
}

View File

@@ -0,0 +1,52 @@
package net.runelite.client.plugins.hydra;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.Point;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.*;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.LineComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
public class HydraIndicatorOverlay extends Overlay {
private final HydraConfig config;
private final HydraPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private HydraIndicatorOverlay(HydraConfig config, HydraPlugin plugin) {
this.config = config;
this.plugin = plugin;
setPosition(OverlayPosition.BOTTOM_RIGHT);
setPriority(OverlayPriority.MED);
panelComponent.setPreferredSize(new Dimension(14, 0));
}
@Override
public Dimension render(Graphics2D graphics) {
if (!config.PrayerHelper()) {
return null;
}
if (plugin.Hydra != null) {
if (plugin.hydras.containsKey(plugin.Hydra.getIndex())) {
int val = plugin.hydras.get(plugin.Hydra.getIndex());
if (val != 0) {
panelComponent.getChildren().clear();
panelComponent.getChildren().add(LineComponent.builder().right(Integer.toString(val)).build());
return panelComponent.render(graphics);
}
}
}
return null;
}
}

View File

@@ -0,0 +1,76 @@
package net.runelite.client.plugins.hydra;
import java.awt.*;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.Point;
import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.*;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class HydraOverlay extends Overlay {
private final HydraConfig config;
private final HydraPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private Client client;
@Inject
private HydraOverlay(HydraConfig config, HydraPlugin plugin) {
this.config = config;
this.plugin = plugin;
setLayer(OverlayLayer.ABOVE_SCENE);
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.MED);
panelComponent.setPreferredSize(new Dimension(150, 0));
}
@Override
public Dimension render(Graphics2D graphics) {
if (!config.TextIndicator()) {
return null;
}
for (NPC hydra : client.getNpcs()) {
if (hydra == null || hydra.getName() == null) {
continue;
}
if (hydra.getName().equalsIgnoreCase("Hydra")) {
if (plugin.hydras.containsKey(hydra.getIndex())) {
int val = plugin.hydras.get(hydra.getIndex());
if (val != 0) {
if (config.BoldText()) {
graphics.setFont(FontManager.getRunescapeBoldFont());
}
if (plugin.hydraattacks.containsKey(hydra.getIndex())) {
int attack = plugin.hydraattacks.get(hydra.getIndex());
if (attack == 8261) {
if (val == 3) {
OverlayUtil.renderTextLocation(graphics, hydra.getCanvasTextLocation(graphics, "MAGE", hydra.getLogicalHeight() + 100), "MAGE", Color.BLUE);
} else {
OverlayUtil.renderTextLocation(graphics, hydra.getCanvasTextLocation(graphics, "RANGE", hydra.getLogicalHeight() + 100), "RANGE", Color.GREEN);
}
} else if (attack == 8262) {
if (val == 3) {
OverlayUtil.renderTextLocation(graphics, hydra.getCanvasTextLocation(graphics, "RANGE", hydra.getLogicalHeight() + 100), "RANGE", Color.GREEN);
} else {
OverlayUtil.renderTextLocation(graphics, hydra.getCanvasTextLocation(graphics, "MAGE", hydra.getLogicalHeight() + 100), "MAGE", Color.BLUE);
}
}
}
Point runelitepleaseexplainwhyineedtocheckthisfornullinsteadoftheentirehydravariablethisshitcostmelikeanhourofmylifeandiblameyouadam = hydra.getCanvasTextLocation(graphics, Integer.toString(val), hydra.getLogicalHeight() + 40);
if (runelitepleaseexplainwhyineedtocheckthisfornullinsteadoftheentirehydravariablethisshitcostmelikeanhourofmylifeandiblameyouadam != null) {
OverlayUtil.renderTextLocation(graphics, runelitepleaseexplainwhyineedtocheckthisfornullinsteadoftheentirehydravariablethisshitcostmelikeanhourofmylifeandiblameyouadam, Integer.toString(val), Color.WHITE);
}
}
}
}
}
graphics.setFont(FontManager.getRunescapeFont());
return null;
}
}

View File

@@ -0,0 +1,145 @@
package net.runelite.client.plugins.hydra;
import net.runelite.api.events.*;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
import java.util.HashMap;
import java.util.Map;
@PluginDescriptor(
name = "Hydra",
description = "Hydra Helper",
tags = {"Hydra", "Helper"}
)
public class HydraPlugin extends Plugin
{
@Inject
private OverlayManager overlayManager;
@Inject
private HydraConfig config;
@Inject
private HydraOverlay HydraOverlay;
@Inject
private HydraPrayOverlay HydraPrayOverlay;
@Inject
private HydraIndicatorOverlay HydraIndicatorOverlay;
@Inject
private Client client;
@Inject
private SpriteManager spriteManager;
@Provides
HydraConfig provideConfig(ConfigManager configManager) {
return configManager.getConfig(HydraConfig.class);
}
Map<Integer, Integer> hydras = new HashMap<>();
Map<Integer, Integer> hydraattacks = new HashMap<>();
NPC Hydra;
@Override
protected void startUp() throws Exception {
overlayManager.add(HydraOverlay);
overlayManager.add(HydraPrayOverlay);
overlayManager.add(HydraIndicatorOverlay);
}
@Override
protected void shutDown() throws Exception {
overlayManager.remove(HydraOverlay);
overlayManager.remove(HydraPrayOverlay);
overlayManager.remove(HydraIndicatorOverlay);
hydras.clear();
hydraattacks.clear();
}
@Subscribe
public void onNpcSpawned(NpcSpawned event) {
if (!config.EnableHydra()) {
return;
}
NPC hydra = event.getNpc();
if (hydra.getCombatLevel() != 0 && hydra.getName() != null) {
if (hydra.getName().equalsIgnoreCase("Hydra")) {
if (!hydras.containsKey(hydra.getIndex())) {
hydras.put(hydra.getIndex(), 3);
}
}
}
}
@Subscribe
public void onNpcDespawned(NpcDespawned event) {
if (!config.EnableHydra()) {
return;
}
NPC hydra = event.getNpc();
if (hydra.getCombatLevel() != 0 && hydra.getName() != null) {
if (hydra.getName().equalsIgnoreCase("Hydra")) {
if (hydras.containsKey(hydra.getIndex())) {
hydras.remove(hydra.getIndex());
}
if (hydraattacks.containsKey(hydra.getIndex())) {
hydraattacks.remove(hydra.getIndex());
}
}
}
}
@Subscribe
public void onAnimationChanged(AnimationChanged event) {
Actor monster = event.getActor();
Actor local = client.getLocalPlayer();
if (monster instanceof NPC) {
NPC hydra = (NPC) monster;
if (hydra.getCombatLevel() != 0 && hydra.getName() != null) {
if (hydra.getName().equalsIgnoreCase("Hydra")) {
if (hydras.containsKey(hydra.getIndex())) {
if (hydra.getAnimation() == 8261 || hydra.getAnimation() == 8262) {
if (hydra.getInteracting().equals(local)) {
Hydra = hydra;
}
if (hydraattacks.containsKey(hydra.getIndex())) {
int lastattack = hydraattacks.get(hydra.getIndex());
hydraattacks.replace(hydra.getIndex(), hydra.getAnimation());
if (lastattack != hydra.getAnimation()) {
hydras.replace(hydra.getIndex(), 2);
} else {
int currval = hydras.get(hydra.getIndex());
if (currval == 1) {
hydras.replace(hydra.getIndex(), 3);
} else {
hydras.replace(hydra.getIndex(), currval - 1);
}
}
} else {
hydraattacks.put(hydra.getIndex(), hydra.getAnimation());
int currval = hydras.get(hydra.getIndex());
if (currval == 1) {
hydras.replace(hydra.getIndex(), 3);
} else {
hydras.replace(hydra.getIndex(), currval - 1);
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,100 @@
package net.runelite.client.plugins.hydra;
import java.awt.*;
import java.awt.image.BufferedImage;
import javax.inject.Inject;
import net.runelite.api.*;
import net.runelite.api.Point;
import net.runelite.client.game.SpriteManager;
import net.runelite.client.ui.overlay.*;
import net.runelite.client.ui.overlay.components.ComponentConstants;
import net.runelite.client.ui.overlay.components.ImageComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
public class HydraPrayOverlay extends Overlay {
private final HydraConfig config;
private final HydraPlugin plugin;
private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150);
private final SpriteManager spriteManager;
private final PanelComponent imagePanelComponent = new PanelComponent();
@Inject
private Client client;
@Inject
private HydraPrayOverlay(HydraConfig config, HydraPlugin plugin, SpriteManager spriteManager) {
this.config = config;
this.plugin = plugin;
setPosition(OverlayPosition.BOTTOM_RIGHT);
setPriority(OverlayPriority.HIGH);
this.spriteManager = spriteManager;
}
@Override
public Dimension render(Graphics2D graphics) {
if (!config.PrayerHelper()) {
return null;
}
if (plugin.Hydra != null) {
if (plugin.hydras.containsKey(plugin.Hydra.getIndex())) {
int val = plugin.hydras.get(plugin.Hydra.getIndex());
if (val != 0) {
if (plugin.hydraattacks.containsKey(plugin.Hydra.getIndex())) {
int attack = plugin.hydraattacks.get(plugin.Hydra.getIndex());
if (attack == 8261) {
if (val == 3) {
final BufferedImage prayerImage = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
} else {
final BufferedImage prayerImage = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
}
} else if (attack == 8262) {
if (val == 3) {
final BufferedImage prayerImage = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
} else {
final BufferedImage prayerImage = spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0);
imagePanelComponent.getChildren().clear();
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
imagePanelComponent.setBackgroundColor(client.isPrayerActive(Prayer.PROTECT_FROM_MAGIC)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
return imagePanelComponent.render(graphics);
}
}
}
}
}
}
return null;
}
}

View File

@@ -0,0 +1,15 @@
package net.runelite.client.plugins.inventorysetups;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.ArrayList;
@AllArgsConstructor
public class InventorySetup
{
@Getter
private ArrayList<InventorySetupItem> inventory;
@Getter
private ArrayList<InventorySetupItem> equipment;
}

View File

@@ -0,0 +1,113 @@
package net.runelite.client.plugins.inventorysetups;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Point;
import net.runelite.api.Query;
import net.runelite.api.SpritePixels;
import net.runelite.api.queries.BankItemQuery;
import net.runelite.api.widgets.Widget;
import net.runelite.api.widgets.WidgetInfo;
import net.runelite.api.widgets.WidgetItem;
import net.runelite.client.ui.FontManager;
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.util.QueryRunner;
import javax.inject.Inject;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Objects;
@Slf4j
public class InventorySetupBankOverlay extends Overlay
{
private final Client client;
private final QueryRunner queryRunner;
private final InventorySetupPlugin plugin;
private final InventorySetupConfig config;
@Inject
public InventorySetupBankOverlay(Client client, QueryRunner queryRunner, InventorySetupPlugin plugin, InventorySetupConfig config)
{
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.LOW);
setLayer(OverlayLayer.ABOVE_WIDGETS);
this.client = client;
this.queryRunner = queryRunner;
this.plugin = plugin;
this.config = config;
}
@Override
public Dimension render(Graphics2D graphics)
{
if (config.getBankHighlight())
{
int[] ids = plugin.getCurrentInventorySetupIds();
if (ids == null)
{
return null;
}
ids = Arrays.stream(ids)
.filter(Objects::nonNull)
.filter(id -> id != -1)
.toArray();
final Query query = new BankItemQuery().idEquals(ids);
final WidgetItem[] widgetItems = queryRunner.runQuery(query);
final Widget bankContainer = client.getWidget(WidgetInfo.BANK_CONTAINER);
for (final WidgetItem item : widgetItems)
{
Point canvasLocation = item.getCanvasLocation();
Rectangle canvasBounds = item.getCanvasBounds();
Point windowLocation = bankContainer.getCanvasLocation();
if (canvasLocation == null || windowLocation == null)
{
return null;
}
if (!(canvasLocation.getY() + 60 >= windowLocation.getY() + bankContainer.getHeight()) && !(canvasLocation.getY() + canvasBounds.getHeight() <= windowLocation.getY() + 90))
{
final Color color = config.getBankHighlightColor();
if (color != null)
{
final BufferedImage outline = loadItemOutline(item.getId(), item.getQuantity(), color);
graphics.drawImage(outline, item.getCanvasLocation().getX() + 1, item.getCanvasLocation().getY() + 1, null);
if (item.getQuantity() > 1)
{
drawQuantity(graphics, item, Color.YELLOW);
}
else if (item.getQuantity() == 0)
{
drawQuantity(graphics, item, Color.YELLOW.darker());
}
}
}
}
}
return null;
}
private void drawQuantity(Graphics2D graphics, WidgetItem item, Color darker)
{
graphics.setColor(Color.BLACK);
graphics.drawString(String.valueOf(item.getQuantity()), item.getCanvasLocation().getX() + 2, item.getCanvasLocation().getY() + 11);
graphics.setColor(darker);
graphics.setFont(FontManager.getRunescapeSmallFont());
graphics.drawString(String.valueOf(item.getQuantity()), item.getCanvasLocation().getX() + 1, item.getCanvasLocation().getY() + 10);
}
private BufferedImage loadItemOutline(final int itemId, final int itemQuantity, final Color outlineColor)
{
final SpritePixels itemSprite = client.createItemSprite(itemId, itemQuantity, 2, 0, 0, true, 710);
return itemSprite.toBufferedOutline(outlineColor);
}
}

View File

@@ -0,0 +1,84 @@
package net.runelite.client.plugins.inventorysetups;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import java.awt.Color;
@ConfigGroup("inventorysetups")
public interface InventorySetupConfig extends Config
{
@ConfigItem(
keyName = "highlightDifferences",
name = "Highlight Differences",
description = "Highlight slots that don't match the selected setup",
position = 0
)
default boolean getHighlightDifferences()
{
return false;
}
@ConfigItem(
keyName = "highlightDifferenceColor",
name = "Highlight Color",
description = "The color used to highlight differences between setups",
position = 1
)
default Color getHighlightColor()
{
return Color.RED;
}
@ConfigItem(
keyName = "stackDifference",
name = "Stack Difference",
description = "Differences between setups will be highlighted if the stack size is different",
position = 2
)
default boolean getStackDifference()
{
return false;
}
@ConfigItem(
keyName = "variationDifference",
name = "Variation Difference",
description = "Variations of items (E.g., charged jewellery) will be counted as different",
position = 2
)
default boolean getVariationDifference()
{
return false;
}
@ConfigItem(
keyName = "bankHighlight",
name = "Bank Highlight",
description = "Highlight setup items in bank",
position = 4
)
default boolean getBankHighlight()
{
return false;
}
@ConfigItem(
keyName = "bankHighlightColor",
name = "Bank Highlight Color",
description = "The color used to highlight setup items in bank",
position = 5
)
default Color getBankHighlightColor()
{
return Color.RED;
}
}

View File

@@ -0,0 +1,15 @@
package net.runelite.client.plugins.inventorysetups;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public class InventorySetupItem
{
@Getter
private final int id;
@Getter
private final String name;
@Getter
private final int quantity;
}

View File

@@ -0,0 +1,402 @@
package net.runelite.client.plugins.inventorysetups;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Provides;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.GameState;
import net.runelite.api.InventoryID;
import net.runelite.api.Item;
import net.runelite.api.ItemComposition;
import net.runelite.api.ItemContainer;
import net.runelite.api.events.ConfigChanged;
import net.runelite.api.events.GameStateChanged;
import net.runelite.api.events.ItemContainerChanged;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.game.ItemManager;
import net.runelite.client.game.ItemVariationMapping;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.inventorysetups.ui.InventorySetupPluginPanel;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.ImageUtil;
import javax.inject.Inject;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import java.awt.image.BufferedImage;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
@PluginDescriptor(
name = "Inventory Setups",
description = "Save inventory setups",
tags = { "items", "inventory", "setups"},
enabledByDefault = false
)
@Slf4j
public class InventorySetupPlugin extends Plugin
{
private static final String CONFIG_GROUP = "inventorysetups";
private static final String CONFIG_KEY = "setups";
private static final int NUM_INVENTORY_ITEMS = 28;
private static final int NUM_EQUIPMENT_ITEMS = 14;
@Inject
private Client client;
@Inject
private ItemManager itemManager;
@Inject
private InventorySetupBankOverlay overlay;
@Inject
private ClientToolbar clientToolbar;
@Inject
private InventorySetupConfig config;
@Inject
private OverlayManager overlayManager;
@Inject
private ClientThread clientThread;
@Inject
private ConfigManager configManager;
private InventorySetupPluginPanel panel;
private HashMap<String, InventorySetup> inventorySetups;
private NavigationButton navButton;
private boolean highlightDifference;
@Override
public void startUp()
{
overlayManager.add(overlay);
panel = new InventorySetupPluginPanel(this, itemManager);
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "inventorysetups_icon.png");
navButton = NavigationButton.builder()
.tooltip("Inventory Setups")
.icon(icon)
.priority(9)
.panel(panel)
.build();
clientToolbar.addNavigation(navButton);
// load all the inventory setups from the config file
clientThread.invokeLater(() ->
{
if (client.getGameState() != GameState.LOGIN_SCREEN)
{
return false;
}
loadConfig();
panel.showNoSetupsPanel();
return true;
});
}
public void addInventorySetup()
{
final String name = JOptionPane.showInputDialog(panel,
"Enter the name of this setup.",
"Add New Setup",
JOptionPane.PLAIN_MESSAGE);
// cancel button was clicked
if (name == null)
{
return;
}
if (name.isEmpty())
{
JOptionPane.showMessageDialog(panel,
"Invalid Setup Name",
"Names must not be empty.",
JOptionPane.PLAIN_MESSAGE);
return;
}
if (inventorySetups.containsKey(name))
{
String builder = "The setup " + name + " already exists. " +
"Would you like to replace it with the current setup?";
int confirm = JOptionPane.showConfirmDialog(panel,
builder,
"Warning",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
if (confirm == JOptionPane.CANCEL_OPTION)
{
return;
}
// delete the old setup, no need to ask for confirmation
// because the user confirmed above
removeInventorySetup(name, false);
}
clientThread.invoke(() ->
{
ArrayList<InventorySetupItem> inv = getNormalizedContainer(InventoryID.INVENTORY);
ArrayList<InventorySetupItem> eqp = getNormalizedContainer(InventoryID.EQUIPMENT);
final InventorySetup invSetup = new InventorySetup(inv, eqp);
SwingUtilities.invokeLater(() ->
{
inventorySetups.put(name, invSetup);
panel.addInventorySetup(name);
panel.setCurrentInventorySetup(name);
updateConfig();
});
});
}
public void removeInventorySetup(final String name, boolean askForConfirmation)
{
if (inventorySetups.containsKey(name))
{
int confirm = JOptionPane.YES_OPTION;
if (askForConfirmation)
{
confirm = JOptionPane.showConfirmDialog(panel,
"Are you sure you want to remove this setup?",
"Warning",
JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE);
}
if (confirm == JOptionPane.YES_OPTION)
{
inventorySetups.remove(name);
panel.removeInventorySetup(name);
}
updateConfig();
}
}
public final InventorySetup getInventorySetup(final String name)
{
return inventorySetups.get(name);
}
@Provides
InventorySetupConfig provideConfig(ConfigManager configManager)
{
return configManager.getConfig(InventorySetupConfig.class);
}
@Subscribe
public void onConfigChanged(ConfigChanged event)
{
if (event.getGroup().equals(CONFIG_GROUP))
{
// only allow highlighting if the config is enabled and the player is logged in
highlightDifference = config.getHighlightDifferences() && client.getGameState() == GameState.LOGGED_IN;
final String setupName = panel.getSelectedInventorySetup();
if (highlightDifference && !setupName.isEmpty())
{
panel.setCurrentInventorySetup(setupName);
}
}
}
private void updateConfig()
{
if (inventorySetups.isEmpty())
{
configManager.unsetConfiguration(CONFIG_GROUP, CONFIG_KEY);
return;
}
final Gson gson = new Gson();
final String json = gson.toJson(inventorySetups);
configManager.setConfiguration(CONFIG_GROUP, CONFIG_KEY, json);
}
private void loadConfig()
{
// serialize the internal data structure from the json in the configuration
final String json = configManager.getConfiguration(CONFIG_GROUP, CONFIG_KEY);
if (json == null || json.isEmpty())
{
inventorySetups = new HashMap<>();
}
else
{
// TODO add last resort?, serialize exception just make empty map
final Gson gson = new Gson();
Type type = new TypeToken<HashMap<String, InventorySetup>>()
{
}.getType();
inventorySetups = gson.fromJson(json, type);
}
for (final String key : inventorySetups.keySet())
{
panel.addInventorySetup(key);
}
highlightDifference = false;
}
@Subscribe
public void onItemContainerChanged(ItemContainerChanged event)
{
if (!highlightDifference || client.getGameState() != GameState.LOGGED_IN)
{
return;
}
// empty entry, no need to compare anything
final String selectedInventorySetup = panel.getSelectedInventorySetup();
if (selectedInventorySetup.isEmpty())
{
return;
}
// check to see that the container is the equipment or inventory
ItemContainer container = event.getItemContainer();
if (container == client.getItemContainer(InventoryID.INVENTORY))
{
ArrayList<InventorySetupItem> normContainer = getNormalizedContainer(InventoryID.INVENTORY);
final InventorySetup setup = inventorySetups.get(selectedInventorySetup);
panel.highlightDifferences(normContainer, setup, InventoryID.INVENTORY);
}
else if (container == client.getItemContainer(InventoryID.EQUIPMENT))
{
ArrayList<InventorySetupItem> normContainer = getNormalizedContainer(InventoryID.EQUIPMENT);
final InventorySetup setup = inventorySetups.get(selectedInventorySetup);
panel.highlightDifferences(normContainer, setup, InventoryID.EQUIPMENT);
}
}
@Subscribe
public void onGameStateChanged(GameStateChanged event)
{
switch (event.getGameState())
{
// set the highlighting off if login screen shows up
case LOGIN_SCREEN:
highlightDifference = false;
final String setupName = panel.getSelectedInventorySetup();
if (!setupName.isEmpty())
{
panel.setCurrentInventorySetup(setupName);
}
break;
// set highlighting
case LOGGED_IN:
highlightDifference = config.getHighlightDifferences();
break;
}
}
public ArrayList<InventorySetupItem> getNormalizedContainer(final InventoryID id)
{
assert id == InventoryID.INVENTORY || id == InventoryID.EQUIPMENT : "invalid inventory ID";
final ItemContainer container = client.getItemContainer(id);
ArrayList<InventorySetupItem> newContainer = new ArrayList<>();
Item[] items = null;
if (container != null)
{
items = container.getItems();
}
int size = id == InventoryID.INVENTORY ? NUM_INVENTORY_ITEMS : NUM_EQUIPMENT_ITEMS;
for (int i = 0; i < size; i++)
{
if (items == null || i >= items.length)
{
newContainer.add(new InventorySetupItem(-1, "", 0));
}
else
{
final Item item = items[i];
String itemName = "";
if (client.isClientThread())
{
itemName = itemManager.getItemComposition(item.getId()).getName();
}
newContainer.add(new InventorySetupItem(item.getId(), itemName, item.getQuantity()));
}
}
return newContainer;
}
public final InventorySetupConfig getConfig()
{
return config;
}
public boolean getHighlightDifference()
{
return highlightDifference;
}
@Override
public void shutDown()
{
overlayManager.remove(overlay);
clientToolbar.removeNavigation(navButton);
}
final int[] getCurrentInventorySetupIds()
{
InventorySetup setup = inventorySetups.get(panel.getSelectedInventorySetup());
if (setup == null)
{
return null;
}
ArrayList<InventorySetupItem> items = new ArrayList<>();
items.addAll(setup.getEquipment());
items.addAll(setup.getInventory());
ArrayList<Integer> itemIds = new ArrayList<>();
for (InventorySetupItem item : items)
{
int id = item.getId();
ItemComposition itemComposition = itemManager.getItemComposition(id);
if (id > 0)
{
itemIds.add(ItemVariationMapping.map(id));
itemIds.add(itemComposition.getPlaceholderId());
}
}
return itemIds.stream().mapToInt(i -> i).toArray();
}
}

View File

@@ -0,0 +1,109 @@
package net.runelite.client.plugins.inventorysetups.ui;
import net.runelite.client.game.AsyncBufferedImage;
import net.runelite.client.game.ItemManager;
import net.runelite.client.game.ItemVariationMapping;
import net.runelite.client.plugins.inventorysetups.InventorySetupConfig;
import net.runelite.client.plugins.inventorysetups.InventorySetupItem;
import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin;
import net.runelite.client.ui.ColorScheme;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.Color;
import java.util.ArrayList;
public abstract class InventorySetupContainerPanel extends JPanel
{
protected ItemManager itemManager;
private final InventorySetupPlugin plugin;
InventorySetupContainerPanel(final ItemManager itemManager, final InventorySetupPlugin plugin, String captionText)
{
this.itemManager = itemManager;
this.plugin = plugin;
JPanel containerPanel = new JPanel();
final JPanel containerSlotsPanel = new JPanel();
setupContainerPanel(containerSlotsPanel);
// caption
final JLabel caption = new JLabel(captionText);
caption.setHorizontalAlignment(JLabel.CENTER);
caption.setVerticalAlignment(JLabel.CENTER);
// panel that holds the caption and any other graphics
final JPanel captionPanel = new JPanel();
captionPanel.add(caption);
containerPanel.setLayout(new BorderLayout());
containerPanel.add(captionPanel, BorderLayout.NORTH);
containerPanel.add(containerSlotsPanel, BorderLayout.CENTER);
add(containerPanel);
}
void setContainerSlot(int index,
final InventorySetupSlot containerSlot,
final ArrayList<InventorySetupItem> items)
{
if (index >= items.size() || items.get(index).getId() == -1)
{
containerSlot.setImageLabel(null, null);
return;
}
int itemId = items.get(index).getId();
int quantity = items.get(index).getQuantity();
final String itemName = items.get(index).getName();
AsyncBufferedImage itemImg = itemManager.getImage(itemId, quantity, quantity > 1);
String toolTip = itemName;
if (quantity > 1)
{
toolTip += " (" + quantity + ")";
}
containerSlot.setImageLabel(toolTip, itemImg);
}
void highlightDifferentSlotColor(InventorySetupItem savedItem,
InventorySetupItem currItem,
final InventorySetupSlot containerSlot)
{
// important note: do not use item names for comparisons
// they are all empty to avoid clientThread usage when highlighting
final InventorySetupConfig config = plugin.getConfig();
final Color highlightColor = config.getHighlightColor();
if (config.getStackDifference() && currItem.getQuantity() != savedItem.getQuantity())
{
containerSlot.setBackground(highlightColor);
return;
}
int currId = currItem.getId();
int checkId = savedItem.getId();
if (!config.getVariationDifference())
{
currId = ItemVariationMapping.map(currId);
checkId = ItemVariationMapping.map(checkId);
}
if (currId != checkId)
{
containerSlot.setBackground(highlightColor);
return;
}
// set the color back to the original, because they match
containerSlot.setBackground(ColorScheme.DARKER_GRAY_COLOR);
}
abstract public void setupContainerPanel(final JPanel containerSlotsPanel);
}

View File

@@ -0,0 +1,91 @@
package net.runelite.client.plugins.inventorysetups.ui;
import net.runelite.api.EquipmentInventorySlot;
import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.inventorysetups.InventorySetup;
import net.runelite.client.plugins.inventorysetups.InventorySetupItem;
import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin;
import net.runelite.client.ui.ColorScheme;
import javax.swing.JPanel;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.HashMap;
public class InventorySetupEquipmentPanel extends InventorySetupContainerPanel
{
private HashMap<EquipmentInventorySlot, InventorySetupSlot> equipmentSlots;
InventorySetupEquipmentPanel(final ItemManager itemManager, final InventorySetupPlugin plugin)
{
super(itemManager, plugin, "Equipment");
}
@Override
public void setupContainerPanel(final JPanel containerSlotsPanel)
{
this.equipmentSlots = new HashMap<>();
for (EquipmentInventorySlot slot : EquipmentInventorySlot.values())
{
equipmentSlots.put(slot, new InventorySetupSlot(ColorScheme.DARKER_GRAY_COLOR));
}
final GridLayout gridLayout = new GridLayout(5, 3, 1, 1);
containerSlotsPanel.setLayout(gridLayout);
// add the grid layouts, including invisible ones
containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.HEAD));
containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.CAPE));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.AMULET));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.AMMO));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.WEAPON));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.BODY));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.SHIELD));
containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.LEGS));
containerSlotsPanel.add(new InventorySetupSlot(ColorScheme.DARK_GRAY_COLOR));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.GLOVES));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.BOOTS));
containerSlotsPanel.add(equipmentSlots.get(EquipmentInventorySlot.RING));
}
void setEquipmentSetupSlots(final InventorySetup setup)
{
final ArrayList<InventorySetupItem> equipment = setup.getEquipment();
for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values())
{
int i = slot.getSlotIdx();
super.setContainerSlot(i, equipmentSlots.get(slot), equipment);
}
validate();
repaint();
}
void highlightDifferences(final ArrayList<InventorySetupItem> currEquipment, final InventorySetup inventorySetup)
{
final ArrayList<InventorySetupItem> equipToCheck = inventorySetup.getEquipment();
assert currEquipment.size() == equipToCheck.size() : "size mismatch";
for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values())
{
int slotIdx = slot.getSlotIdx();
super.highlightDifferentSlotColor(equipToCheck.get(slotIdx), currEquipment.get(slotIdx), equipmentSlots.get(slot));
}
}
void resetEquipmentSlotsColor()
{
for (final EquipmentInventorySlot slot : EquipmentInventorySlot.values())
{
equipmentSlots.get(slot).setBackground(ColorScheme.DARKER_GRAY_COLOR);
}
}
}

View File

@@ -0,0 +1,78 @@
package net.runelite.client.plugins.inventorysetups.ui;
import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.inventorysetups.InventorySetup;
import net.runelite.client.plugins.inventorysetups.InventorySetupItem;
import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin;
import net.runelite.client.ui.ColorScheme;
import javax.swing.JPanel;
import java.awt.GridLayout;
import java.util.ArrayList;
public class InventorySetupInventoryPanel extends InventorySetupContainerPanel
{
private static final int ITEMS_PER_ROW = 4;
private static final int NUM_INVENTORY_ITEMS = 28;
private ArrayList<InventorySetupSlot> inventorySlots;
InventorySetupInventoryPanel(final ItemManager itemManager, final InventorySetupPlugin plugin)
{
super(itemManager, plugin, "Inventory");
}
@Override
public void setupContainerPanel(final JPanel containerSlotsPanel)
{
this.inventorySlots = new ArrayList<>();
for (int i = 0; i < NUM_INVENTORY_ITEMS; i++)
{
inventorySlots.add(new InventorySetupSlot(ColorScheme.DARKER_GRAY_COLOR));
}
int numRows = (NUM_INVENTORY_ITEMS + ITEMS_PER_ROW - 1) / ITEMS_PER_ROW;
containerSlotsPanel.setLayout(new GridLayout(numRows, ITEMS_PER_ROW, 1, 1));
for (int i = 0; i < NUM_INVENTORY_ITEMS; i++)
{
containerSlotsPanel.add(inventorySlots.get(i));
}
}
void setInventorySetupSlots(final InventorySetup setup)
{
ArrayList<InventorySetupItem> inventory = setup.getInventory();
for (int i = 0; i < NUM_INVENTORY_ITEMS; i++)
{
super.setContainerSlot(i, inventorySlots.get(i), inventory);
}
validate();
repaint();
}
void highlightDifferentSlots(final ArrayList<InventorySetupItem> currInventory, final InventorySetup inventorySetup)
{
final ArrayList<InventorySetupItem> inventoryToCheck = inventorySetup.getInventory();
assert currInventory.size() == inventoryToCheck.size() : "size mismatch";
for (int i = 0; i < NUM_INVENTORY_ITEMS; i++)
{
super.highlightDifferentSlotColor(inventoryToCheck.get(i), currInventory.get(i), inventorySlots.get(i));
}
}
void resetInventorySlotsColor()
{
for (InventorySetupSlot inventorySlot : inventorySlots)
{
inventorySlot.setBackground(ColorScheme.DARKER_GRAY_COLOR);
}
}
}

View File

@@ -0,0 +1,287 @@
package net.runelite.client.plugins.inventorysetups.ui;
import net.runelite.api.InventoryID;
import net.runelite.client.game.ItemManager;
import net.runelite.client.plugins.inventorysetups.InventorySetup;
import net.runelite.client.plugins.inventorysetups.InventorySetupItem;
import net.runelite.client.plugins.inventorysetups.InventorySetupPlugin;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.ui.components.PluginErrorPanel;
import net.runelite.client.util.ImageUtil;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.border.EmptyBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public class InventorySetupPluginPanel extends PluginPanel
{
private static ImageIcon ADD_ICON;
private static ImageIcon ADD_HOVER_ICON;
private static ImageIcon REMOVE_ICON;
private static ImageIcon REMOVE_HOVER_ICON;
private final JPanel noSetupsPanel;
private final JPanel invEqPanel;
private final InventorySetupInventoryPanel invPanel;
private final InventorySetupEquipmentPanel eqpPanel;
private final JComboBox<String> setupComboBox;
private final JLabel removeMarker;
private final InventorySetupPlugin plugin;
static
{
final BufferedImage addIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "add_icon.png");
ADD_ICON = new ImageIcon(addIcon);
ADD_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(addIcon, 0.53f));
final BufferedImage removeIcon = ImageUtil.getResourceStreamFromClass(InventorySetupPlugin.class, "remove_icon.png");
REMOVE_ICON = new ImageIcon(removeIcon);
REMOVE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(removeIcon, 0.53f));
}
public InventorySetupPluginPanel(final InventorySetupPlugin plugin, final ItemManager itemManager)
{
super(false);
this.plugin = plugin;
this.removeMarker = new JLabel(REMOVE_ICON);
this.invPanel = new InventorySetupInventoryPanel(itemManager, plugin);
this.eqpPanel = new InventorySetupEquipmentPanel(itemManager, plugin);
this.noSetupsPanel = new JPanel();
this.invEqPanel = new JPanel();
this.setupComboBox = new JComboBox<>();
// setup the title
final JLabel addMarker = new JLabel(ADD_ICON);
final JLabel title = new JLabel();
title.setText("Inventory Setups");
title.setForeground(Color.WHITE);
// setup the add marker (+ sign in the top right)
addMarker.setToolTipText("Add a new inventory setup");
addMarker.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
plugin.addInventorySetup();
}
@Override
public void mouseEntered(MouseEvent e)
{
addMarker.setIcon(ADD_HOVER_ICON);
}
@Override
public void mouseExited(MouseEvent e)
{
addMarker.setIcon(ADD_ICON);
}
});
// setup the remove marker (X sign in the top right)
removeMarker.setToolTipText("Remove the current inventory setup");
removeMarker.addMouseListener(new MouseAdapter()
{
@Override
public void mouseClicked(MouseEvent e)
{
final String name = (String)setupComboBox.getSelectedItem();
plugin.removeInventorySetup(name, true);
}
@Override
public void mouseEntered(MouseEvent e)
{
if (removeMarker.isEnabled())
{
removeMarker.setIcon(REMOVE_HOVER_ICON);
}
}
@Override
public void mouseExited(MouseEvent e)
{
removeMarker.setIcon(REMOVE_ICON);
}
});
// setup the combo box for selection switching
// add empty to indicate the empty position
setupComboBox.addItem("");
setupComboBox.setSelectedIndex(0);
setupComboBox.addItemListener(e ->
{
if (e.getStateChange() == ItemEvent.SELECTED)
{
String selection = (String)e.getItem();
setCurrentInventorySetup(selection);
}
});
// the panel on the top right that holds the add and delete buttons
final JPanel markersPanel = new JPanel();
markersPanel.setLayout(new FlowLayout(FlowLayout.RIGHT, 10, 0));
markersPanel.add(removeMarker);
markersPanel.add(addMarker);
// the top panel that has the title and the buttons
final JPanel titleAndMarkersPanel = new JPanel();
titleAndMarkersPanel.setLayout(new BorderLayout());
titleAndMarkersPanel.add(title, BorderLayout.WEST);
titleAndMarkersPanel.add(markersPanel, BorderLayout.EAST);
// the panel that stays at the top and doesn't scroll
// contains the title, buttons, and the combo box
final JPanel northAnchoredPanel = new JPanel();
northAnchoredPanel.setLayout(new BoxLayout(northAnchoredPanel, BoxLayout.Y_AXIS));
northAnchoredPanel.setBorder(new EmptyBorder(0, 0, 10, 0));
northAnchoredPanel.add(titleAndMarkersPanel);
northAnchoredPanel.add(Box.createRigidArea(new Dimension(0, 10)));
northAnchoredPanel.add(setupComboBox);
// the panel that holds the inventory and equipment panels
final BoxLayout invEqLayout = new BoxLayout(invEqPanel, BoxLayout.Y_AXIS);
invEqPanel.setLayout(invEqLayout);
invEqPanel.add(invPanel);
invEqPanel.add(Box.createRigidArea(new Dimension(0, 10)));
invEqPanel.add(eqpPanel);
// setup the error panel. It's wrapped around a normal panel
// so it doesn't stretch to fill the parent panel
final PluginErrorPanel errorPanel = new PluginErrorPanel();
errorPanel.setContent("Inventory Setups", "Select or create an inventory setup.");
noSetupsPanel.add(errorPanel);
// the panel that holds the inventory panels, and the error panel
final JPanel contentPanel = new JPanel();
final BoxLayout contentLayout = new BoxLayout(contentPanel, BoxLayout.Y_AXIS);
contentPanel.setLayout(contentLayout);
contentPanel.add(invEqPanel);
contentPanel.add(noSetupsPanel);
// wrapper for the main content panel to keep it from stretching
final JPanel contentWrapper = new JPanel(new BorderLayout());
contentWrapper.add(Box.createGlue(), BorderLayout.CENTER);
contentWrapper.add(contentPanel, BorderLayout.NORTH);
final JScrollPane contentWrapperPane = new JScrollPane(contentWrapper);
contentWrapperPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
setLayout(new BorderLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
add(northAnchoredPanel, BorderLayout.NORTH);
add(contentWrapperPane, BorderLayout.CENTER);
// show the no setups panel on startup
showNoSetupsPanel();
}
public void showNoSetupsPanel()
{
setupComboBox.setSelectedIndex(0);
removeMarker.setEnabled(false);
noSetupsPanel.setVisible(true);
invEqPanel.setVisible(false);
}
private void showHasSetupPanel(final String name)
{
setupComboBox.setSelectedItem(name);
removeMarker.setEnabled(true);
noSetupsPanel.setVisible(false);
invEqPanel.setVisible(true);
}
public void setCurrentInventorySetup(final String name)
{
if (name.isEmpty())
{
showNoSetupsPanel();
return;
}
showHasSetupPanel(name);
final InventorySetup inventorySetup = plugin.getInventorySetup(name);
invPanel.setInventorySetupSlots(inventorySetup);
eqpPanel.setEquipmentSetupSlots(inventorySetup);
if (plugin.getHighlightDifference())
{
final ArrayList<InventorySetupItem> normInv = plugin.getNormalizedContainer(InventoryID.INVENTORY);
final ArrayList<InventorySetupItem> normEqp = plugin.getNormalizedContainer(InventoryID.EQUIPMENT);
highlightDifferences(normInv, inventorySetup, InventoryID.INVENTORY);
highlightDifferences(normEqp, inventorySetup, InventoryID.EQUIPMENT);
}
else
{
invPanel.resetInventorySlotsColor();
eqpPanel.resetEquipmentSlotsColor();
}
validate();
repaint();
}
public void addInventorySetup(final String name)
{
setupComboBox.addItem(name);
}
public void removeInventorySetup(final String name)
{
setupComboBox.removeItem(name);
showNoSetupsPanel();
invPanel.resetInventorySlotsColor();
eqpPanel.resetEquipmentSlotsColor();
validate();
repaint();
}
public void highlightDifferences(final ArrayList<InventorySetupItem> container,
final InventorySetup setupToCheck,
final InventoryID type)
{
switch (type)
{
case INVENTORY:
invPanel.highlightDifferentSlots(container, setupToCheck);
break;
case EQUIPMENT:
eqpPanel.highlightDifferences(container, setupToCheck);
break;
}
}
public final String getSelectedInventorySetup()
{
return (String)setupComboBox.getSelectedItem();
}
}

View File

@@ -0,0 +1,45 @@
package net.runelite.client.plugins.inventorysetups.ui;
import net.runelite.client.game.AsyncBufferedImage;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import java.awt.Color;
import java.awt.Dimension;
public class InventorySetupSlot extends JPanel
{
private final JLabel imageLabel;
public InventorySetupSlot(Color color)
{
imageLabel = new JLabel();
imageLabel.setVerticalAlignment(SwingConstants.CENTER);
setPreferredSize(new Dimension(46, 42));
setBackground(color);
add(imageLabel);
}
public void setImageLabel(String toolTip, AsyncBufferedImage itemImage)
{
if (itemImage == null || toolTip == null)
{
imageLabel.setToolTipText("");
imageLabel.setIcon(null);
imageLabel.revalidate();
return;
}
imageLabel.setToolTipText(toolTip);
itemImage.addTo(imageLabel);
validate();
repaint();
}
}

Some files were not shown because too many files have changed in this diff Show More