Plugins Bringup
Adds all? non broken widget plugins: AoeWarnings BATools ClanmanMode Equipment Inspector Fight Cave Wave Helper Fight Cave Jad Helper Freeze Timers Grotesque Guardians Hide Prayers Hydra Lizardmen Shaman Menu Modifier Music Modifier Next Hit Notifier PK Vision Plank make helper Pray against player Profiles Pyramid Plunder Screen markers Shayzien Infirmary Shift Walker Slayermusiq Spellbook fixer Supplies tracker Temple Trek Time Tracking Theatre of Blood damage counter Vetion Vorkath Wilderness Locations Zone Indicators ZTOB Zulrah
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 |
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.runelite.client.plugins.hideprayers;
|
||||
|
||||
public enum PrayerTabState
|
||||
{
|
||||
NONE,
|
||||
PRAYERS,
|
||||
QUICK_PRAYERS
|
||||
}
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package net.runelite.client.plugins.kittennotifier;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("kittennotifier")
|
||||
public interface KittenNotifierConfig extends Config{
|
||||
@ConfigItem(
|
||||
keyName = "absolutelyNeeded",
|
||||
name = "Notify only on Absolute Need",
|
||||
description = "Only notify when kitten absolutely needs food or attention."
|
||||
)
|
||||
default boolean absolutelyNeeded() { return false; }
|
||||
@ConfigItem(
|
||||
keyName = "catOwned",
|
||||
name = "",
|
||||
description = "",
|
||||
hidden = true
|
||||
)
|
||||
default boolean catOwned() { return false; }
|
||||
@ConfigItem(
|
||||
keyName = "catOwned",
|
||||
name = "",
|
||||
description = ""
|
||||
)
|
||||
void catOwned(Boolean bool);
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package net.runelite.client.plugins.kittennotifier;
|
||||
import com.google.inject.Provides;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.NpcActionChanged;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
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.api.NPC;
|
||||
import net.runelite.api.Client;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "!Kitten Notifier",
|
||||
description = "Sends a notification when your kitten needs food, attention, or is grown.",
|
||||
tags = {"kitten, notifications"}
|
||||
)
|
||||
public class KittenNotifierPlugin extends Plugin{
|
||||
@Inject
|
||||
private Notifier notifier;
|
||||
@Inject
|
||||
private KittenNotifierConfig config;
|
||||
@Inject
|
||||
private Client client;
|
||||
@Provides
|
||||
KittenNotifierConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(KittenNotifierConfig.class);
|
||||
}
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event) {
|
||||
if (event.getType() == ChatMessageType.ENGINE && !config.catOwned()) {
|
||||
if (!config.absolutelyNeeded()) {
|
||||
if (event.getMessage().contentEquals("<col=ef1020>Your kitten is hungry.</col>")) {
|
||||
notifier.notify("Your kitten is hungry.");
|
||||
}
|
||||
if (event.getMessage().contentEquals("<col=ef1020>Your kitten wants attention.</col>")) {
|
||||
notifier.notify("Your kitten wants attention.");
|
||||
}
|
||||
}
|
||||
if (event.getMessage().contentEquals("<col=ef1020>Your kitten is very hungry.</col>")) {
|
||||
notifier.notify("Your kitten is very hungry.");
|
||||
}
|
||||
if (event.getMessage().contentEquals("<col=ef1020>Your kitten really wants attention.</col>")) {
|
||||
notifier.notify("Your kitten really wants attention.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@Subscribe
|
||||
public void onNpcActionChanged(NpcActionChanged event) {
|
||||
if (!config.catOwned()) {
|
||||
for (NPC npc : client.getNpcs()) {
|
||||
if (npc.getInteracting() != null) {
|
||||
if (npc.getName().contentEquals("Cat") && !config.catOwned()) {
|
||||
// If this if statement is included in previous it could null.
|
||||
if (npc.getInteracting().getName().contentEquals(client.getLocalPlayer().getName())) {
|
||||
config.catOwned(true);
|
||||
notifier.notify("Your kitten has grown into a cat.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Subscribe
|
||||
public void onNpcSpawned(NpcSpawned event) {
|
||||
NPC cat = event.getNpc();
|
||||
if (cat.getName() != null) {
|
||||
if (cat.getName().equalsIgnoreCase("Kitten")) {
|
||||
if (cat.getInteracting().getName().contentEquals(client.getLocalPlayer().getName())) {
|
||||
config.catOwned(false);
|
||||
}
|
||||
}
|
||||
else if (cat.getName().contentEquals("Cat")) {
|
||||
if (cat.getInteracting().getName().equalsIgnoreCase(client.getLocalPlayer().getName())) {
|
||||
config.catOwned(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package net.runelite.client.plugins.lizardmenshaman;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("shaman")
|
||||
public interface LizardmenShamanConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "showTimer",
|
||||
name = "Show timer",
|
||||
description = "Display timer till for lizardman shaman spawns."
|
||||
)
|
||||
default boolean showTimer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "notifyOnSpawn",
|
||||
name = "Notify on spawn",
|
||||
description = "Notify user when lizardman summons spawns."
|
||||
)
|
||||
default boolean notifyOnSpawn()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package net.runelite.client.plugins.lizardmenshaman;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "<font color=\"#4863A0\">!Lizard Shamans</font>",
|
||||
description = "Configures timer for lizardmen shaman spawns.",
|
||||
enabledByDefault = false,
|
||||
tags = {"shaman", "lizard", "lizardmen"}
|
||||
)
|
||||
@Slf4j
|
||||
public class LizardmenShamanPlugin extends Plugin
|
||||
{
|
||||
private static final String SHAMAN = "Lizardman shaman";
|
||||
private static final String MESSAGE = "A Lizardman shaman has summoned his spawn!";
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Map<LocalPoint, LizardmenShamanSpawn> spawns = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private ShamanSpawnOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private LizardmenShamanConfig config;
|
||||
|
||||
@Inject
|
||||
private Notifier notifier;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Provides
|
||||
LizardmenShamanConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(LizardmenShamanConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
spawns.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onAnimationChanged(AnimationChanged event)
|
||||
{
|
||||
Actor actor = event.getActor();
|
||||
if (actor == null || actor.getName() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (actor.getName().equals(SHAMAN) && actor.getAnimation() == 7157)
|
||||
{
|
||||
if (config.showTimer())
|
||||
{
|
||||
spawns.put(event.getActor().getLocalLocation(), new LizardmenShamanSpawn(8.4, null));
|
||||
}
|
||||
|
||||
if (config.notifyOnSpawn())
|
||||
{
|
||||
notifier.notify(MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package net.runelite.client.plugins.lizardmenshaman;
|
||||
|
||||
import java.time.Instant;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@RequiredArgsConstructor
|
||||
@AllArgsConstructor
|
||||
class LizardmenShamanSpawn
|
||||
{
|
||||
private final Instant start = Instant.now();
|
||||
private double countdownTimer;
|
||||
private Instant end;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package net.runelite.client.plugins.lizardmenshaman;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.ProgressPieComponent;
|
||||
|
||||
class ShamanSpawnOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final LizardmenShamanPlugin plugin;
|
||||
|
||||
@Inject
|
||||
private ShamanSpawnOverlay(Client client, LizardmenShamanPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
plugin.getSpawns().forEach((localPoint, spawn) ->
|
||||
{
|
||||
final Instant now = Instant.now();
|
||||
final long startCountdown = Duration.between(spawn.getStart(), now).getSeconds();
|
||||
final double certainSec = spawn.getCountdownTimer() - startCountdown;
|
||||
|
||||
if (certainSec <= 0)
|
||||
{
|
||||
if (spawn.getEnd() == null)
|
||||
{
|
||||
spawn.setEnd(Instant.now());
|
||||
}
|
||||
}
|
||||
|
||||
final ProgressPieComponent pieComponent = new ProgressPieComponent();
|
||||
final Point loc = Perspective.localToCanvas(client, localPoint, client.getPlane());
|
||||
|
||||
if (loc == null || certainSec < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pieComponent.setPosition(loc);
|
||||
pieComponent.setProgress(certainSec / spawn.getCountdownTimer());
|
||||
if (certainSec > 4.8)
|
||||
{
|
||||
pieComponent.setFill(Color.GREEN);
|
||||
pieComponent.setBorderColor(Color.GREEN);
|
||||
pieComponent.render(graphics);
|
||||
}
|
||||
else if (certainSec > 3.6)
|
||||
{
|
||||
pieComponent.setFill(Color.YELLOW);
|
||||
pieComponent.setBorderColor(Color.YELLOW);
|
||||
pieComponent.render(graphics);
|
||||
}
|
||||
else if (certainSec > 2.4)
|
||||
{
|
||||
pieComponent.setFill(Color.ORANGE);
|
||||
pieComponent.setBorderColor(Color.ORANGE);
|
||||
pieComponent.render(graphics);
|
||||
}
|
||||
else if (certainSec > 1.2)
|
||||
{
|
||||
pieComponent.setFill(new Color(255, 140, 0));
|
||||
pieComponent.setBorderColor(new Color(255, 140, 0));
|
||||
pieComponent.render(graphics);
|
||||
}
|
||||
else
|
||||
{
|
||||
pieComponent.setFill(Color.RED);
|
||||
pieComponent.setBorderColor(Color.RED);
|
||||
pieComponent.render(graphics);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.runelite.client.plugins.menumodifier;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("menumodifier")
|
||||
public interface MenuModifierConfig extends Config
|
||||
{
|
||||
@ConfigItem(position = 0, keyName = "hideCancel", name = "Hide Cancel", description = "Hides the 'cancel' option from the right click menu")
|
||||
default boolean hideCancel() { return true; }
|
||||
|
||||
@ConfigItem(position = 1, keyName = "hideExamine", name = "Hide Examine", description = "Hides the 'examine' option from the right click menu")
|
||||
default boolean hideExamine() { return true; }
|
||||
|
||||
@ConfigItem(position = 2, keyName = "hideTradeWith", name = "Hide Trade With", description = "Hides the 'trade with' option from the right click menu")
|
||||
default boolean hideTradeWith() { return true; }
|
||||
|
||||
@ConfigItem(position = 3, keyName = "hideReport", name = "Hide Report", description = "Hides the 'report' option from the right click menu")
|
||||
default boolean hideReport() { return true; }
|
||||
|
||||
@ConfigItem(position = 4, keyName = "hideLookup", name = "Hide Lookup", description = "Hides the 'lookup' option from the right click menu")
|
||||
default boolean hideLookup() { return true; }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package net.runelite.client.plugins.menumodifier;
|
||||
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.MouseAdapter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public class MenuModifierInputListener extends MouseAdapter implements KeyListener
|
||||
{
|
||||
private static final int HOTKEY = KeyEvent.VK_CONTROL;
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Inject
|
||||
private MenuModifierPlugin plugin;
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (e.getKeyCode() == HOTKEY)
|
||||
{
|
||||
plugin.setHotKeyPressed(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
if (e.getKeyCode() == HOTKEY)
|
||||
{
|
||||
plugin.setHotKeyPressed(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package net.runelite.client.plugins.menumodifier;
|
||||
|
||||
import net.runelite.api.events.MenuOpened;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.MiscUtils;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "<font color=\"green\">!Menu Modifier</font>",
|
||||
description = "Changes right click menu for players",
|
||||
tags = { "menu", "modifier", "right", "click", "pk", "bogla" },
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class MenuModifierPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private MenuModifierConfig config;
|
||||
|
||||
@Inject
|
||||
private MenuModifierInputListener inputListener;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
@Provides
|
||||
MenuModifierConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(MenuModifierConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
keyManager.registerKeyListener(inputListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
keyManager.unregisterKeyListener(inputListener);
|
||||
}
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private boolean hotKeyPressed;
|
||||
|
||||
@Subscribe
|
||||
public void onMenuOpened(MenuOpened event)
|
||||
{
|
||||
Player localPlayer = client.getLocalPlayer();
|
||||
|
||||
if (localPlayer == null)
|
||||
return;
|
||||
|
||||
if (!(MiscUtils.getWildernessLevelFrom(client, localPlayer.getWorldLocation()) >= 0))
|
||||
return;
|
||||
|
||||
if (hotKeyPressed)
|
||||
return;
|
||||
|
||||
List<MenuEntry> menu_entries = new ArrayList<MenuEntry>();
|
||||
|
||||
for (MenuEntry entry : event.getMenuEntries())
|
||||
{
|
||||
String option = Text.removeTags(entry.getOption()).toLowerCase();
|
||||
|
||||
if (option.contains("trade with") && config.hideTradeWith())
|
||||
continue;
|
||||
|
||||
if (option.contains("lookup") && config.hideLookup())
|
||||
continue;
|
||||
|
||||
if (option.contains("report") && config.hideReport())
|
||||
continue;
|
||||
|
||||
if (option.contains("examine") && config.hideExamine())
|
||||
continue;
|
||||
|
||||
int identifier = entry.getIdentifier();
|
||||
|
||||
Player[] players = client.getCachedPlayers();
|
||||
Player player = null;
|
||||
|
||||
if (identifier >= 0 && identifier < players.length)
|
||||
player = players[identifier];
|
||||
|
||||
if (player == null)
|
||||
{
|
||||
menu_entries.add(entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((option.contains("attack") || option.contains("cast")) && (player.isFriend() || player.isClanMember()))
|
||||
continue;
|
||||
|
||||
menu_entries.add(entry);
|
||||
}
|
||||
|
||||
MenuEntry[] updated_menu_entries = new MenuEntry[menu_entries.size()];
|
||||
updated_menu_entries = menu_entries.toArray(updated_menu_entries);
|
||||
|
||||
client.setMenuEntries(updated_menu_entries);
|
||||
}
|
||||
|
||||
/*@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded)
|
||||
{
|
||||
if (true)
|
||||
return;
|
||||
|
||||
if (!inWilderness)
|
||||
return;
|
||||
|
||||
if (hotKeyPressed)
|
||||
return;
|
||||
|
||||
String option = Text.removeTags(menuEntryAdded.getOption()).toLowerCase();
|
||||
|
||||
if ((option.contains("trade with") && config.hideTradeWith())
|
||||
|| (option.contains("lookup") && config.hideLookup())
|
||||
|| (option.contains("report") && config.hideReport())
|
||||
|| (option.contains("examine") && config.hideExamine())
|
||||
|| (option.contains("cancel") && config.hideCancel()))
|
||||
{
|
||||
int identifier = menuEntryAdded.getIdentifier();
|
||||
|
||||
Player[] players = client.getCachedPlayers();
|
||||
Player player = null;
|
||||
|
||||
if (identifier >= 0 && identifier < players.length)
|
||||
player = players[identifier];
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
//allow trading with friends/clanmates
|
||||
if (option.contains("trade with") && (player.isFriend() || player.isClanMember()))
|
||||
return;
|
||||
|
||||
MenuEntry[] menuEntries = client.getMenuEntries();
|
||||
|
||||
if (menuEntries.length > 0)
|
||||
client.setMenuEntries(Arrays.copyOf(menuEntries, menuEntries.length - 1));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Rodolfo Ruiz-Velasco <https://github.com/lequietriot/>
|
||||
* 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.musicmodifier;
|
||||
|
||||
import javax.sound.midi.*;
|
||||
import java.io.IOException;
|
||||
|
||||
public class MidiFileAdjuster {
|
||||
|
||||
private int bankLSBValue;
|
||||
private int chPosition = -1;
|
||||
|
||||
private boolean customBank = false;
|
||||
|
||||
public Sequence reorderTracks(Sequence sequence) throws InvalidMidiDataException, IOException {
|
||||
for (Track track : sequence.getTracks()) {
|
||||
for (int i = 0; i < track.size(); i++) {
|
||||
MidiEvent midiEvent = track.get(i);
|
||||
MidiMessage midiMessage = midiEvent.getMessage();
|
||||
|
||||
if (midiMessage instanceof ShortMessage) {
|
||||
ShortMessage sm = (ShortMessage) midiMessage;
|
||||
|
||||
if (sm.getChannel() < 16) {
|
||||
getBankLSB(sm);
|
||||
|
||||
if (i == 0 & bankLSBValue != 1) {
|
||||
chPosition++;
|
||||
if (chPosition == 9) {
|
||||
chPosition = 10;
|
||||
}
|
||||
}
|
||||
|
||||
if (!customBank) {
|
||||
|
||||
if (sm.getChannel() == 9) {
|
||||
bankLSBValue = 1;
|
||||
}
|
||||
|
||||
if (sm.getChannel() != 9) {
|
||||
bankLSBValue = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bankLSBValue == 1) {
|
||||
|
||||
int drumChannel = 9;
|
||||
if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) {
|
||||
sm.setMessage(ShortMessage.PROGRAM_CHANGE, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) {
|
||||
sm.setMessage(ShortMessage.CONTROL_CHANGE, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.NOTE_OFF) {
|
||||
sm.setMessage(ShortMessage.NOTE_OFF, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.NOTE_ON) {
|
||||
sm.setMessage(ShortMessage.NOTE_ON, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) {
|
||||
sm.setMessage(ShortMessage.PROGRAM_CHANGE, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) {
|
||||
sm.setMessage(ShortMessage.CONTROL_CHANGE, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.PITCH_BEND) {
|
||||
sm.setMessage(ShortMessage.PITCH_BEND, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.CHANNEL_PRESSURE) {
|
||||
sm.setMessage(ShortMessage.CHANNEL_PRESSURE, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.POLY_PRESSURE) {
|
||||
sm.setMessage(ShortMessage.POLY_PRESSURE, drumChannel, sm.getData1(), sm.getData2());
|
||||
}
|
||||
} else {
|
||||
|
||||
if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) {
|
||||
sm.setMessage(ShortMessage.PROGRAM_CHANGE, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) {
|
||||
sm.setMessage(ShortMessage.CONTROL_CHANGE, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.NOTE_OFF) {
|
||||
sm.setMessage(ShortMessage.NOTE_OFF, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.NOTE_ON) {
|
||||
sm.setMessage(ShortMessage.NOTE_ON, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.PROGRAM_CHANGE) {
|
||||
sm.setMessage(ShortMessage.PROGRAM_CHANGE, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE) {
|
||||
sm.setMessage(ShortMessage.CONTROL_CHANGE, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.PITCH_BEND) {
|
||||
sm.setMessage(ShortMessage.PITCH_BEND, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.CHANNEL_PRESSURE) {
|
||||
sm.setMessage(ShortMessage.CHANNEL_PRESSURE, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
|
||||
if (sm.getCommand() == ShortMessage.POLY_PRESSURE) {
|
||||
sm.setMessage(ShortMessage.POLY_PRESSURE, chPosition, sm.getData1(), sm.getData2());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sequence;
|
||||
}
|
||||
|
||||
private void getBankLSB(ShortMessage sm) throws InvalidMidiDataException
|
||||
{
|
||||
if (sm.getCommand() == ShortMessage.CONTROL_CHANGE)
|
||||
{
|
||||
if (sm.getData1() == 32)
|
||||
{
|
||||
bankLSBValue = sm.getData2();
|
||||
customBank = true;
|
||||
}
|
||||
if (sm.getData1() == 0)
|
||||
{
|
||||
sm.setMessage(sm.getCommand(), sm.getChannel(), sm.getData1(), bankLSBValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Rodolfo Ruiz-Velasco <https://github.com/lequietriot/>
|
||||
* 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.musicmodifier;
|
||||
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.*;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
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 javax.inject.Inject;
|
||||
import java.io.File;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Music Track Customizer",
|
||||
description = "Customize what track plays and how it sounds, with local files",
|
||||
tags = {"music", "sound"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
|
||||
public class MusicCustomizerPlugin extends Plugin
|
||||
{
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ChatboxPanelManager chatboxPanelManager;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
private RealTimeMIDIPlayer realTimeMIDIPlayer = new RealTimeMIDIPlayer();
|
||||
|
||||
private String songName = "Scape Main";
|
||||
|
||||
private ChatboxTextInput songInput;
|
||||
|
||||
private Widget playlistModeButton;
|
||||
|
||||
private Widget playlistBox;
|
||||
|
||||
private Widget hidePlaylistButton;
|
||||
|
||||
private Widget addPlaylistSongButton;
|
||||
|
||||
private Widget playlistText;
|
||||
|
||||
private Widget playlistSong;
|
||||
|
||||
private String defaultUnlockedSongs;
|
||||
|
||||
private boolean isLooping = true;
|
||||
|
||||
private boolean playlistMode = false;
|
||||
|
||||
private int newSongY = 34;
|
||||
|
||||
private int playlistCount = 0;
|
||||
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
playSong(songName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
if (realTimeMIDIPlayer != null)
|
||||
{
|
||||
realTimeMIDIPlayer.stopSong();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!playlistMode)
|
||||
{
|
||||
String newSong = client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).getText();
|
||||
|
||||
if (!newSong.equals(songName))
|
||||
{
|
||||
songName = newSong;
|
||||
playSongFromList(songName);
|
||||
}
|
||||
}
|
||||
} catch (NullPointerException ignored)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void playSong(String song)
|
||||
{
|
||||
File midiMusicFile = new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" +
|
||||
"Music/" + song + ".mid/");
|
||||
if (realTimeMIDIPlayer.midi == null)
|
||||
{
|
||||
realTimeMIDIPlayer.midi = midiMusicFile;
|
||||
realTimeMIDIPlayer.run();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (realTimeMIDIPlayer.isPlaying())
|
||||
{
|
||||
realTimeMIDIPlayer.stopSong();
|
||||
}
|
||||
realTimeMIDIPlayer.midi = midiMusicFile;
|
||||
realTimeMIDIPlayer.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onWidgetLoaded(WidgetLoaded widgetLoaded)
|
||||
{
|
||||
if (widgetLoaded.getGroupId() == WidgetID.MUSICTAB_GROUP_ID)
|
||||
{
|
||||
Widget musicPlayerSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS);
|
||||
if (musicPlayerSongs != null)
|
||||
{
|
||||
playlistModeButton = musicPlayerSongs.createChild(-1, WidgetType.GRAPHIC);
|
||||
playlistModeButton.setSpriteId(SpriteID.RS2_TAB_MUSIC);
|
||||
playlistModeButton.setOriginalWidth(32);
|
||||
playlistModeButton.setOriginalHeight(32);
|
||||
playlistModeButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
playlistModeButton.setOriginalX(0);
|
||||
playlistModeButton.setOriginalY(0);
|
||||
playlistModeButton.setHasListener(true);
|
||||
playlistModeButton.setAction(1, "Open");
|
||||
playlistModeButton.setOnOpListener((JavaScriptCallback) e -> openPlaylist());
|
||||
playlistModeButton.setName("Playlist");
|
||||
playlistModeButton.setHidden(true); //Playlist is not enabled for this release (Unfinished).
|
||||
playlistModeButton.revalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void openPlaylist()
|
||||
{
|
||||
playlistMode = true;
|
||||
|
||||
Widget currentPlayingSong = client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME);
|
||||
Widget allInGameSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS);
|
||||
Widget musicScrollbar = client.getWidget(WidgetInfo.MUSICTAB_SCROLLBAR);
|
||||
allInGameSongs.setHidden(true);
|
||||
musicScrollbar.setHidden(true);
|
||||
|
||||
defaultUnlockedSongs = client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).getText();
|
||||
|
||||
client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(playlistCount + " / 10");
|
||||
|
||||
playlistBox = client.getWidget(WidgetInfo.MUSICTAB_INTERFACE);
|
||||
|
||||
playlistText = playlistBox.createChild(-1, WidgetType.TEXT);
|
||||
playlistText.setText("Music Playlist");
|
||||
playlistText.setFontId(497);
|
||||
playlistText.setXPositionMode(WidgetPositionMode.ABSOLUTE_TOP);
|
||||
playlistText.setOriginalX(40);
|
||||
playlistText.setOriginalY(14);
|
||||
playlistText.setOriginalHeight(1);
|
||||
playlistText.setOriginalWidth(1);
|
||||
playlistText.setTextColor(currentPlayingSong.getTextColor());
|
||||
playlistText.revalidate();
|
||||
|
||||
hidePlaylistButton = playlistBox.createChild(-1, WidgetType.GRAPHIC);
|
||||
hidePlaylistButton.setSpriteId(SpriteID.RS2_TAB_MUSIC);
|
||||
hidePlaylistButton.setOriginalWidth(32);
|
||||
hidePlaylistButton.setOriginalHeight(32);
|
||||
hidePlaylistButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_RIGHT);
|
||||
hidePlaylistButton.setOriginalX(0);
|
||||
hidePlaylistButton.setOriginalY(6);
|
||||
hidePlaylistButton.setHasListener(true);
|
||||
hidePlaylistButton.setAction(1, "Close");
|
||||
hidePlaylistButton.setOnOpListener((JavaScriptCallback) e -> closePlaylist());
|
||||
hidePlaylistButton.setName("Playlist");
|
||||
hidePlaylistButton.revalidate();
|
||||
|
||||
addPlaylistSongButton = playlistBox.createChild(-1, WidgetType.GRAPHIC);
|
||||
addPlaylistSongButton.setSpriteId(SpriteID.BANK_ADD_TAB_ICON);
|
||||
addPlaylistSongButton.setOriginalWidth(36);
|
||||
addPlaylistSongButton.setOriginalHeight(32);
|
||||
addPlaylistSongButton.setXPositionMode(WidgetPositionMode.ABSOLUTE_LEFT);
|
||||
addPlaylistSongButton.setOriginalX(0);
|
||||
addPlaylistSongButton.setOriginalY(6);
|
||||
addPlaylistSongButton.setHasListener(true);
|
||||
addPlaylistSongButton.setAction(1, "Add to");
|
||||
addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> addSongFromInput());
|
||||
addPlaylistSongButton.setName("Playlist");
|
||||
addPlaylistSongButton.revalidate();
|
||||
|
||||
if (playlistSong != null)
|
||||
{
|
||||
playlistSong.setHidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void closePlaylist()
|
||||
{
|
||||
playlistMode = false;
|
||||
|
||||
Widget allInGameSongs = client.getWidget(WidgetInfo.MUSICTAB_ALL_SONGS);
|
||||
Widget musicScrollbar = client.getWidget(WidgetInfo.MUSICTAB_SCROLLBAR);
|
||||
allInGameSongs.setHidden(false);
|
||||
musicScrollbar.setHidden(false);
|
||||
|
||||
client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(defaultUnlockedSongs);
|
||||
playlistText.setHidden(true);
|
||||
addPlaylistSongButton.setHidden(true);
|
||||
hidePlaylistButton.setHidden(true);
|
||||
|
||||
if (playlistSong != null)
|
||||
{
|
||||
playlistSong.setHidden(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSongFromInput()
|
||||
{
|
||||
addPlaylistSongButton.setAction(1, "Close search");
|
||||
addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> closeInput());
|
||||
songInput = chatboxPanelManager.openTextInput("Please type a valid song name")
|
||||
.onChanged(s -> clientThread.invokeLater(() -> updateSongs(s)))
|
||||
.onClose(() ->
|
||||
{
|
||||
clientThread.invokeLater(() -> updateSongs(songInput.getValue()));
|
||||
addPlaylistSongButton.setOnOpListener((JavaScriptCallback) e -> addSongFromInput());
|
||||
addPlaylistSongButton.setAction(1, "Add to");
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
private void updateSongs()
|
||||
{
|
||||
String song = "";
|
||||
if (chatboxIsOpen())
|
||||
{
|
||||
song = songInput.getValue();
|
||||
}
|
||||
updateSongs(song);
|
||||
}
|
||||
|
||||
private void updateSongs(String song)
|
||||
{
|
||||
if (playlistBox == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" +
|
||||
"Music/" + song + ".mid/").exists())
|
||||
{
|
||||
playListSongPlayer(song);
|
||||
}
|
||||
}
|
||||
|
||||
private void playListSongPlayer(String song)
|
||||
{
|
||||
if (!song.equals(songName) && !chatboxIsOpen() && playlistCount < 10)
|
||||
{
|
||||
Widget playlistWidget = client.getWidget(WidgetInfo.MUSICTAB_INTERFACE);
|
||||
playlistSong = playlistWidget.createChild(-1, WidgetType.TEXT);
|
||||
playlistSong.setText(song);
|
||||
playlistSong.setFontId(495);
|
||||
playlistSong.setOriginalX(12);
|
||||
playlistSong.setOriginalY(newSongY);
|
||||
playlistSong.setOriginalWidth(120);
|
||||
playlistSong.setOriginalHeight(16);
|
||||
playlistSong.setTextColor(client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).getTextColor());
|
||||
playlistSong.setHasListener(true);
|
||||
playlistSong.setAction(1, "Play");
|
||||
playlistSong.setOnOpListener((JavaScriptCallback) e -> playSongFromList(song));
|
||||
playlistSong.setName(song);
|
||||
playlistSong.revalidate();
|
||||
|
||||
newSongY = newSongY + 15;
|
||||
|
||||
songName = song;
|
||||
|
||||
playlistCount++;
|
||||
client.getWidget(WidgetInfo.MUSICTAB_UNLOCKED_SONGS).setText(playlistCount + " / 10");
|
||||
|
||||
if (playlistCount == 10)
|
||||
{
|
||||
addPlaylistSongButton.setHidden(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean chatboxIsOpen()
|
||||
{
|
||||
return songInput != null && chatboxPanelManager.getCurrentInput() == songInput;
|
||||
}
|
||||
|
||||
private void closeInput()
|
||||
{
|
||||
updateSongs();
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
|
||||
private void playSongFromList(String song)
|
||||
{
|
||||
client.getWidget(WidgetInfo.MUSICTAB_CURRENT_SONG_NAME).setName(song);
|
||||
File midiMusicFile = new File(System.getProperty("user.home") + "/RuneLiteAudio/MIDI Files/" +
|
||||
"Music/" + song + ".mid/");
|
||||
|
||||
if (realTimeMIDIPlayer.midi == null)
|
||||
{
|
||||
realTimeMIDIPlayer.midi = midiMusicFile;
|
||||
realTimeMIDIPlayer.run();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (realTimeMIDIPlayer.isPlaying())
|
||||
{
|
||||
realTimeMIDIPlayer.stopSong();
|
||||
}
|
||||
realTimeMIDIPlayer.midi = midiMusicFile;
|
||||
realTimeMIDIPlayer.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Rodolfo Ruiz-Velasco <https://github.com/lequietriot/>
|
||||
* 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.musicmodifier;
|
||||
|
||||
import com.sun.media.sound.AudioSynthesizer;
|
||||
|
||||
import javax.sound.midi.*;
|
||||
import javax.sound.sampled.*;
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RealTimeMIDIPlayer implements Runnable
|
||||
{
|
||||
private AudioFormat format;
|
||||
|
||||
private Sequence midiSequence;
|
||||
|
||||
private Soundbank soundbank;
|
||||
|
||||
private SourceDataLine sdl;
|
||||
|
||||
private MusicCustomizerPlugin customMusicPlugin;
|
||||
|
||||
private MidiFileAdjuster adjuster;
|
||||
|
||||
private Clip clip;
|
||||
|
||||
public boolean looping = true;
|
||||
|
||||
public File soundFont = new File(System.getProperty("user.home") + "/RuneLiteAudio/SoundFonts/" +
|
||||
"RuneScape 2.sf2/");
|
||||
|
||||
public File midi;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
|
||||
adjuster = new MidiFileAdjuster(); //Unfinished class
|
||||
|
||||
midiSequence = MidiSystem.getSequence(midi);
|
||||
soundbank = MidiSystem.getSoundbank(soundFont);
|
||||
init();
|
||||
}
|
||||
catch (IOException | InvalidMidiDataException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void stopSong()
|
||||
{
|
||||
if (sdl.isRunning())
|
||||
{
|
||||
sdl.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public static AudioSynthesizer findAudioSynthesizer() throws MidiUnavailableException
|
||||
{
|
||||
Synthesizer synth = MidiSystem.getSynthesizer();
|
||||
if (synth instanceof AudioSynthesizer)
|
||||
return (AudioSynthesizer) synth;
|
||||
|
||||
double gain = 0.8D;
|
||||
|
||||
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
|
||||
MidiChannel[] channels = synth.getChannels();
|
||||
|
||||
for (int i = 0; i < channels.length; i++)
|
||||
{
|
||||
channels[i].controlChange(7, ((int) (channels[i].getController(7) * gain)));
|
||||
}
|
||||
|
||||
for (int i = 0; i < infos.length; i++)
|
||||
{
|
||||
MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
|
||||
|
||||
if (device instanceof AudioSynthesizer)
|
||||
return (AudioSynthesizer) device;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isPlaying()
|
||||
{
|
||||
return sdl.isActive();
|
||||
}
|
||||
|
||||
public static double send(Sequence sequence, Receiver receiver) {
|
||||
float divtype = sequence.getDivisionType();
|
||||
assert (sequence.getDivisionType() == Sequence.PPQ);
|
||||
Track[] tracks = sequence.getTracks();
|
||||
int[] trackspos = new int[tracks.length];
|
||||
int mpq = 500000;
|
||||
int seqres = sequence.getResolution();
|
||||
long lasttick = 0;
|
||||
long curtime = 0;
|
||||
while (true) {
|
||||
MidiEvent selevent = null;
|
||||
int seltrack = -1;
|
||||
for (int i = 0; i < tracks.length; i++) {
|
||||
int trackpos = trackspos[i];
|
||||
Track track = tracks[i];
|
||||
if (trackpos < track.size()) {
|
||||
MidiEvent event = track.get(trackpos);
|
||||
if (selevent == null
|
||||
|| event.getTick() < selevent.getTick()) {
|
||||
selevent = event;
|
||||
seltrack = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (seltrack == -1)
|
||||
break;
|
||||
trackspos[seltrack]++;
|
||||
long tick = selevent.getTick();
|
||||
if (divtype == Sequence.PPQ)
|
||||
curtime += ((tick - lasttick) * mpq) / seqres;
|
||||
else
|
||||
curtime = (long) ((tick * 1000000.0 * divtype) / seqres);
|
||||
lasttick = tick;
|
||||
MidiMessage msg = selevent.getMessage();
|
||||
if (msg instanceof MetaMessage) {
|
||||
if (divtype == Sequence.PPQ)
|
||||
if (((MetaMessage) msg).getType() == 0x51) {
|
||||
byte[] data = ((MetaMessage) msg).getData();
|
||||
mpq = ((data[0] & 0xff) << 16)
|
||||
| ((data[1] & 0xff) << 8) | (data[2] & 0xff);
|
||||
}
|
||||
} else {
|
||||
if (receiver != null)
|
||||
receiver.send(msg, curtime);
|
||||
}
|
||||
}
|
||||
return curtime / 1000000.0;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
AudioSynthesizer synth = null;
|
||||
try {
|
||||
synth = findAudioSynthesizer();
|
||||
format = new AudioFormat(44100, 16, 2, true, false);
|
||||
|
||||
Map<String, Object> info = new HashMap<String, Object>();
|
||||
info.put("resamplerType", "sinc");
|
||||
info.put("maxPolyphony", "8192");
|
||||
AudioInputStream ais = synth.openStream(format, info);
|
||||
synth.unloadAllInstruments(synth.getDefaultSoundbank());
|
||||
synth.loadAllInstruments(soundbank);
|
||||
double total = send(midiSequence, synth.getReceiver());
|
||||
long length = (long) (ais.getFormat().getFrameRate() * (total + 4));
|
||||
AudioInputStream stream = new AudioInputStream(ais, format, length);
|
||||
sdl = AudioSystem.getSourceDataLine(format);
|
||||
sdl.open(format);
|
||||
sdl.start();
|
||||
writeAudio(sdl, stream);
|
||||
} catch (LineUnavailableException | MidiUnavailableException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public void writeAudio(SourceDataLine sdl, AudioInputStream stream)
|
||||
{
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
byte[] sampledAudio = new byte[1024];
|
||||
|
||||
int numBytesRead = 0;
|
||||
|
||||
while (numBytesRead != -1) {
|
||||
try
|
||||
{
|
||||
numBytesRead = stream.read(sampledAudio, 0, sampledAudio.length);
|
||||
|
||||
if (numBytesRead >= 0) {
|
||||
sdl.write(sampledAudio, 0, numBytesRead);
|
||||
}
|
||||
}
|
||||
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
finally {
|
||||
|
||||
if (!isPlaying() && looping)
|
||||
{
|
||||
this.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package net.runelite.client.plugins.nexthitnotifier;
|
||||
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
|
||||
@ConfigGroup("nexthitnotifier")
|
||||
public interface NextHitNotifierConfig extends Config
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package net.runelite.client.plugins.nexthitnotifier;
|
||||
|
||||
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.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
import net.runelite.client.util.MiscUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.*;
|
||||
|
||||
public class NextHitNotifierOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final NextHitNotifierPlugin plugin;
|
||||
private final NextHitNotifierConfig config;
|
||||
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
private final Dimension panelSize = new Dimension(48, 0);
|
||||
|
||||
@Inject
|
||||
private NextHitNotifierOverlay(Client client, NextHitNotifierPlugin plugin, NextHitNotifierConfig config)
|
||||
{
|
||||
setPosition(OverlayPosition.BOTTOM_LEFT);
|
||||
//setPosition(OverlayPosition.DYNAMIC);
|
||||
//setPosition(OverlayPosition.DETACHED);
|
||||
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
panelComponent.getChildren().clear();
|
||||
panelComponent.setPreferredSize(panelSize);
|
||||
|
||||
String lastHitText = Integer.toString(plugin.lastHit);
|
||||
int lastHit = plugin.lastHit;
|
||||
|
||||
if (plugin.showTime < 0)
|
||||
{
|
||||
lastHitText = "0";
|
||||
lastHit = 0;
|
||||
}
|
||||
|
||||
int g = (int)MiscUtils.clamp((float)Math.floor(lastHit / 30.f) * 255.f, 0.f, 255.f);
|
||||
int r = 255 - g;
|
||||
|
||||
Color textColor = Color.getHSBColor(Color.RGBtoHSB(r, g, 0, null)[0], 1.f, 1.f);
|
||||
|
||||
panelComponent.getChildren().add(TitleComponent.builder().text("Next hit:").color(Color.YELLOW).build());
|
||||
panelComponent.getChildren().add(TitleComponent.builder().text(lastHitText).color(textColor).build());
|
||||
|
||||
return panelComponent.render(graphics);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package net.runelite.client.plugins.nexthitnotifier;
|
||||
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.events.ExperienceChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "<font color=\"green\">!Next Hit Notifier</font>",
|
||||
description = "Shows estimated next hit based on xp drop.",
|
||||
tags = { "experience", "damage", "overlay", "pking", "bogla" },
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class NextHitNotifierPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private NextHitNotifierOverlay overlay;
|
||||
|
||||
private int lastHpXp = 0;
|
||||
int lastHit = 0;
|
||||
int showTime = 0;
|
||||
|
||||
@Provides
|
||||
NextHitNotifierConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(NextHitNotifierConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
lastHpXp = client.getSkillExperience(Skill.HITPOINTS);
|
||||
lastHit = 0;
|
||||
showTime = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastHpXp = 0;
|
||||
lastHit = 0;
|
||||
showTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
if (showTime > 0)
|
||||
showTime--;
|
||||
else
|
||||
lastHit = 0;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onExperienceChanged(ExperienceChanged event)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
lastHpXp = 0;
|
||||
lastHit = 0;
|
||||
showTime = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
final Skill skill = event.getSkill();
|
||||
|
||||
if (skill != Skill.HITPOINTS)
|
||||
return;
|
||||
|
||||
final int currentXp = client.getSkillExperience(skill);
|
||||
|
||||
int gainedXp = currentXp - lastHpXp;
|
||||
|
||||
//filter out big xp drops (such as login)
|
||||
if (gainedXp > 1000)
|
||||
{
|
||||
lastHpXp = client.getSkillExperience(skill);
|
||||
return;
|
||||
}
|
||||
|
||||
lastHit = (int)Math.rint(gainedXp / 1.33f);
|
||||
lastHpXp = currentXp;
|
||||
showTime = 3;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package net.runelite.client.plugins.pkvision;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("pkvision")
|
||||
public interface PKVisionConfig extends Config
|
||||
{
|
||||
@ConfigItem(position = 0, keyName = "drawOwnName", name = "Highlight own player", description = "Configures whether or not your own player should be highlighted")
|
||||
default boolean highlightOwnPlayer()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(position = 1, keyName = "ownNameColor", name = "Own player color", description = "Color of your own player")
|
||||
default Color getOwnPlayerColor()
|
||||
{
|
||||
return new Color(0, 184, 212);
|
||||
}
|
||||
|
||||
@ConfigItem(position = 2, keyName = "drawFriendNames", name = "Highlight friends", description = "Configures whether or not friends should be highlighted")
|
||||
default boolean highlightFriends()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(position = 3, keyName = "friendNameColor", name = "Friend color", description = "Color of friend names" )
|
||||
default Color getFriendColor()
|
||||
{
|
||||
return new Color(0, 200, 80);
|
||||
}
|
||||
|
||||
@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 = "drawPlayerNames", name = "Draw names above players", description = "Configures whether or not player names should be drawn above players")
|
||||
default boolean drawPlayerNames() { return true; }
|
||||
|
||||
@ConfigItem(position = 6, keyName = "drawPlayerLevels", name = "Draw levels above players", description = "Configures whether or not player levels should be drawn above players")
|
||||
default boolean drawPlayerLevels()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//@ConfigItem(position = 7, keyName = "drawPlayerHealth", name = "Draw health above players", description = "Configures whether or not player levels should be drawn above players")
|
||||
//default boolean drawPlayerHealth()
|
||||
//{
|
||||
// return true;
|
||||
//}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package net.runelite.client.plugins.pkvision;
|
||||
|
||||
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 PKVisionMinimapOverlay extends Overlay
|
||||
{
|
||||
private final PKVisionService pkVisionService;
|
||||
|
||||
@Inject
|
||||
private PKVisionMinimapOverlay(PKVisionService pkVisionService)
|
||||
{
|
||||
this.pkVisionService = pkVisionService;
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
pkVisionService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
|
||||
{
|
||||
final net.runelite.api.Point minimapLocation = actor.getMinimapLocation();
|
||||
|
||||
if (minimapLocation != null)
|
||||
OverlayUtil.renderTextLocation(graphics, minimapLocation, Integer.toString(actor.getCombatLevel()), color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package net.runelite.client.plugins.pkvision;
|
||||
|
||||
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.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;
|
||||
|
||||
@Singleton
|
||||
public class PKVisionOverlay extends Overlay
|
||||
{
|
||||
private final PKVisionService pkVisionService;
|
||||
private final PKVisionConfig config;
|
||||
|
||||
@Inject
|
||||
private PKVisionOverlay(PKVisionConfig config, PKVisionService pkVisionService, PKVisionPlugin pkVisionPlugin)
|
||||
{
|
||||
this.config = config;
|
||||
this.pkVisionService = pkVisionService;
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setPriority(OverlayPriority.MED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
pkVisionService.forEachPlayer((player, color) -> renderPlayerOverlay(graphics, player, color));
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderPlayerOverlay(Graphics2D graphics, Player actor, Color color)
|
||||
{
|
||||
if (!config.drawPlayerNames() && !config.drawPlayerLevels())
|
||||
return;
|
||||
|
||||
String text = "";
|
||||
if (config.drawPlayerLevels())
|
||||
text += "(" + actor.getCombatLevel() + ") ";
|
||||
|
||||
if (config.drawPlayerNames())
|
||||
text += actor.getName().replace('\u00A0', ' ');
|
||||
|
||||
Point textLocation = actor.getCanvasTextLocation(graphics, text, actor.getLogicalHeight() + 40);
|
||||
|
||||
if (textLocation != null)
|
||||
OverlayUtil.renderTextLocation(graphics, textLocation, text, color);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package net.runelite.client.plugins.pkvision;
|
||||
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.MenuAction.*;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.client.util.MiscUtils;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "<font color=\"aqua\">!PK Vision</font>",
|
||||
description = "Highlight players on-screen and/or on the minimap",
|
||||
tags = {"highlight", "minimap", "overlay", "players", "pk", "helper", "vision", "bogla"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class PKVisionPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private PKVisionConfig config;
|
||||
|
||||
@Inject
|
||||
private PKVisionOverlay pkVisionOverlay;
|
||||
|
||||
@Inject
|
||||
private PKVisionTileOverlay pkVisionTileOverlay;
|
||||
|
||||
@Inject
|
||||
private PKVisionMinimapOverlay pkVisionMinimapOverlay;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Provides
|
||||
PKVisionConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(PKVisionConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(pkVisionOverlay);
|
||||
overlayManager.add(pkVisionTileOverlay);
|
||||
overlayManager.add(pkVisionMinimapOverlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(pkVisionOverlay);
|
||||
overlayManager.remove(pkVisionTileOverlay);
|
||||
overlayManager.remove(pkVisionMinimapOverlay);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded menuEntryAdded)
|
||||
{
|
||||
int type = menuEntryAdded.getType();
|
||||
String option = Text.removeTags(menuEntryAdded.getOption()).toLowerCase();
|
||||
|
||||
if (type >= 2000)
|
||||
type -= 2000;
|
||||
|
||||
int identifier = menuEntryAdded.getIdentifier();
|
||||
if (type == FOLLOW.getId() || type == TRADE.getId()
|
||||
|| type == ITEM_USE_ON_PLAYER.getId() || type == PLAYER_FIRST_OPTION.getId()
|
||||
|| type == PLAYER_SECOND_OPTION.getId() || type == PLAYER_THIRD_OPTION.getId()
|
||||
|| type == PLAYER_FOURTH_OPTION.getId() || type == PLAYER_FIFTH_OPTION.getId()
|
||||
|| type == PLAYER_SIXTH_OPTION.getId() || type == PLAYER_SEVENTH_OPTION.getId()
|
||||
|| type == PLAYER_EIGTH_OPTION.getId() || type == SPELL_CAST_ON_PLAYER.getId()
|
||||
|| type == RUNELITE.getId())
|
||||
{
|
||||
final Player localPlayer = client.getLocalPlayer();
|
||||
Player[] players = client.getCachedPlayers();
|
||||
Player player = null;
|
||||
|
||||
if (identifier >= 0 && identifier < players.length)
|
||||
player = players[identifier];
|
||||
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
Color color = null;
|
||||
|
||||
if (config.highlightFriends() && (player.isFriend() || player.isClanMember()))
|
||||
{
|
||||
color = config.getFriendColor();
|
||||
}
|
||||
else if (!player.isFriend() && !player.isClanMember())
|
||||
{
|
||||
int lvlDelta = player.getCombatLevel() - localPlayer.getCombatLevel();
|
||||
int wildyLvl = MiscUtils.getWildernessLevelFrom(client, player.getWorldLocation());
|
||||
|
||||
if (wildyLvl <= 0)
|
||||
return;
|
||||
|
||||
int R = MiscUtils.clamp((int)(((float)(lvlDelta + wildyLvl) / (float)(wildyLvl * 2)) * 255.f), 0, 255);
|
||||
int G = MiscUtils.clamp(255 - R, 0, 255);
|
||||
|
||||
if (Math.abs(lvlDelta) <= wildyLvl)
|
||||
color = Color.getHSBColor(Color.RGBtoHSB(R, G, 0, null)[0], 1.f, 1.f);
|
||||
}
|
||||
|
||||
if (color != null)
|
||||
{
|
||||
MenuEntry[] menuEntries = client.getMenuEntries();
|
||||
MenuEntry lastEntry = menuEntries[menuEntries.length - 1];
|
||||
|
||||
// strip out existing <col...
|
||||
String target = lastEntry.getTarget();
|
||||
int idx = target.indexOf('>');
|
||||
if (idx != -1)
|
||||
target = target.substring(idx + 1);
|
||||
|
||||
lastEntry.setTarget(ColorUtil.prependColorTag(target, color));
|
||||
|
||||
|
||||
client.setMenuEntries(menuEntries);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package net.runelite.client.plugins.pkvision;
|
||||
|
||||
import java.awt.Color;
|
||||
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.client.util.MiscUtils;
|
||||
|
||||
@Singleton
|
||||
public class PKVisionService
|
||||
{
|
||||
private final Client client;
|
||||
private final PKVisionConfig config;
|
||||
|
||||
@Inject
|
||||
private PKVisionService(Client client, PKVisionConfig config)
|
||||
{
|
||||
this.config = config;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public void forEachPlayer(final BiConsumer<Player, Color> consumer)
|
||||
{
|
||||
final Player localPlayer = client.getLocalPlayer();
|
||||
|
||||
for (Player player : client.getPlayers())
|
||||
{
|
||||
if (player == null || player.getName() == null)
|
||||
continue;
|
||||
|
||||
if (player == localPlayer)
|
||||
{
|
||||
if (config.highlightOwnPlayer())
|
||||
consumer.accept(player, config.getOwnPlayerColor());
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (config.highlightFriends() && (player.isFriend() || player.isClanMember()))
|
||||
{
|
||||
consumer.accept(player, config.getFriendColor());
|
||||
}
|
||||
else if (player != localPlayer && !player.isFriend() && !player.isClanMember())
|
||||
{
|
||||
int lvlDelta = player.getCombatLevel() - localPlayer.getCombatLevel();
|
||||
int wildyLvl = MiscUtils.getWildernessLevelFrom(client, player.getWorldLocation());
|
||||
|
||||
if (wildyLvl <= 0)
|
||||
continue;
|
||||
|
||||
if (Math.abs(lvlDelta) > wildyLvl)
|
||||
continue;
|
||||
|
||||
int R = MiscUtils.clamp((int)(((float)(lvlDelta + wildyLvl) / (float)(wildyLvl * 2)) * 255.f), 0, 255);
|
||||
int G = MiscUtils.clamp(255 - R, 0, 255);
|
||||
|
||||
consumer.accept(player, Color.getHSBColor(Color.RGBtoHSB(R, G, 0, null)[0], 1.f, 1.f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package net.runelite.client.plugins.pkvision;
|
||||
|
||||
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 PKVisionTileOverlay extends Overlay
|
||||
{
|
||||
private final PKVisionService pkVisionService;
|
||||
private final PKVisionConfig config;
|
||||
|
||||
@Inject
|
||||
private PKVisionTileOverlay(PKVisionConfig config, PKVisionService pkVisionService)
|
||||
{
|
||||
this.config = config;
|
||||
this.pkVisionService = pkVisionService;
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setPriority(OverlayPriority.MED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!config.drawTiles())
|
||||
return null;
|
||||
|
||||
pkVisionService.forEachPlayer((player, color) ->
|
||||
{
|
||||
final Polygon poly = player.getCanvasTilePoly();
|
||||
|
||||
if (poly != null)
|
||||
OverlayUtil.renderPolygon(graphics, poly, color);
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package net.runelite.client.plugins.plankmakehelper;
|
||||
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.ui.overlay.*;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.*;
|
||||
|
||||
public class PlankMakeOverlay extends Overlay {
|
||||
|
||||
private final PlankMakePlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
public PlankMakeOverlay(final PlankMakePlugin plugin, final Client client) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
|
||||
setPosition(OverlayPosition.DETACHED);
|
||||
setLayer(OverlayLayer.ALWAYS_ON_TOP);
|
||||
setPriority(OverlayPriority.MED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics) {
|
||||
if (hasPlankableItems()) {
|
||||
renderInventory(graphics);
|
||||
renderPlankMakeSpell(graphics);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderInventory(Graphics2D graphics) {
|
||||
Widget inventory = client.getWidget(WidgetInfo.INVENTORY);
|
||||
|
||||
int firstItemSeenIndex = -1;
|
||||
|
||||
if (inventory != null) {
|
||||
for (WidgetItem item : inventory.getWidgetItems()) {
|
||||
if (PlankMakePlugin.isLogAndPlankable(item.getId())) {
|
||||
if (firstItemSeenIndex == -1) {
|
||||
firstItemSeenIndex = item.getIndex();
|
||||
}
|
||||
if (!inventory.isHidden()) {
|
||||
if (item.getIndex() != firstItemSeenIndex) {
|
||||
OverlayUtil.renderPolygon(graphics, RectangleToPolygon(item.getCanvasBounds()), Color.BLUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (firstItemSeenIndex != -1) {
|
||||
OverlayUtil.renderPolygon(graphics, RectangleToPolygon(inventory.getWidgetItem(firstItemSeenIndex).getCanvasBounds()), Color.CYAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderPlankMakeSpell(Graphics2D graphics) {
|
||||
Widget plankMakeSpell = client.getWidget(218,128);
|
||||
if (plankMakeSpell != null && (plankMakeSpell.getCanvasLocation().getX() != 29 & plankMakeSpell.getCanvasLocation().getY() != 32)) {
|
||||
OverlayUtil.renderPolygon(graphics, RectangleToPolygon(plankMakeSpell.getBounds()), Color.CYAN);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasPlankableItems() {
|
||||
ItemContainer invo = client.getItemContainer(InventoryID.INVENTORY);
|
||||
if (invo != null) {
|
||||
if (invo.getItems().length > 0) {
|
||||
for (Item item : invo.getItems()) {
|
||||
if (PlankMakePlugin.isLogAndPlankable(item.getId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static Polygon RectangleToPolygon(Rectangle rect) {
|
||||
int[] xpoints = {rect.x, rect.x + rect.width, rect.x + rect.width, rect.x};
|
||||
int[] ypoints = {rect.y, rect.y, rect.y + rect.height, rect.y + rect.height};
|
||||
return new Polygon(xpoints, ypoints, 4);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package net.runelite.client.plugins.plankmakehelper;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Plank Make Helper",
|
||||
description = "Highlights planks and plank make spell",
|
||||
tags = {"overlay", "plankmaking", "lunar", "money", "moneymaking", "gp"}
|
||||
)
|
||||
|
||||
public class PlankMakePlugin extends Plugin {
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private PlankMakeOverlay overlay;
|
||||
|
||||
@Override
|
||||
protected void startUp() {
|
||||
overlayManager.add(overlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() {
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
|
||||
static boolean isLogAndPlankable(int itemID) {
|
||||
switch (itemID) {
|
||||
case 6332: //mahogany
|
||||
case 1521: //oak
|
||||
case 6333: //teak
|
||||
case 1511: //plain
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.runelite.client.plugins.prayagainstplayer;
|
||||
|
||||
import net.runelite.api.Player;
|
||||
|
||||
/**
|
||||
* Contains a player object
|
||||
* When they attacked me
|
||||
* And (in milliseconds) when to expire the overlay around them
|
||||
*/
|
||||
public class PlayerContainer {
|
||||
|
||||
private Player player;
|
||||
private long whenTheyAttackedMe;
|
||||
private int millisToExpireHighlight;
|
||||
|
||||
public PlayerContainer(Player player, long whenTheyAttackedMe, int millisToExpireHighlight) {
|
||||
this.player = player;
|
||||
this.whenTheyAttackedMe = whenTheyAttackedMe;
|
||||
this.millisToExpireHighlight = millisToExpireHighlight;
|
||||
}
|
||||
|
||||
|
||||
//getters
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
public long getWhenTheyAttackedMe() {
|
||||
return whenTheyAttackedMe;
|
||||
}
|
||||
public int getMillisToExpireHighlight() { return millisToExpireHighlight; };
|
||||
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.runelite.client.plugins.prayagainstplayer;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@ConfigGroup("prayagainstplayer")
|
||||
public interface PrayAgainstPlayerConfig extends Config {
|
||||
@ConfigItem(
|
||||
position = 0,
|
||||
keyName = "attackerPlayerColor",
|
||||
name = "Attacker color",
|
||||
description = "This is the color that will be used to highlight attackers."
|
||||
)
|
||||
default Color attackerPlayerColor() { return new Color(0xFF0006); }
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "potentialPlayerColor",
|
||||
name = "Potential Attacker color",
|
||||
description = "This is the color that will be used to highlight potential attackers."
|
||||
)
|
||||
default Color potentialPlayerColor() { return new Color(0xFFFF00); }
|
||||
|
||||
////
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "attackerTargetTimeout",
|
||||
name = "Attacker Timeout",
|
||||
description = "Seconds until attacker is no longer highlighted."
|
||||
)
|
||||
default int attackerTargetTimeout() { return 10; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "potentialTargetTimeout",
|
||||
name = "Potential Attacker Timeout",
|
||||
description = "Seconds until potential attacker is no longer highlighted."
|
||||
)
|
||||
default int potentialTargetTimeout() { return 10; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 4,
|
||||
keyName = "newSpawnTimeout",
|
||||
name = "New Player Timeout",
|
||||
description = "Seconds until logged in/spawned player is no longer highlighted."
|
||||
)
|
||||
default int newSpawnTimeout() { return 5; }
|
||||
////
|
||||
|
||||
////
|
||||
@ConfigItem(
|
||||
position = 5,
|
||||
keyName = "ignoreFriends",
|
||||
name = "Ignore Friends",
|
||||
description = "This lets you decide whether you want friends to be highlighted by this plugin."
|
||||
)
|
||||
default boolean ignoreFriends() { return true; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 6,
|
||||
keyName = "ignoreClanMates",
|
||||
name = "Ignore Clan Mates",
|
||||
description = "This lets you decide whether you want clan mates to be highlighted by this plugin."
|
||||
)
|
||||
default boolean ignoreClanMates() { return true; }
|
||||
////
|
||||
|
||||
@ConfigItem(
|
||||
position = 7,
|
||||
keyName = "markNewPlayer",
|
||||
name = "Mark new player as potential attacker",
|
||||
description = "Marks someone that logged in or teleported as a potential attacker for your safety\nDO NOT RUN THIS IN WORLD 1-2 GRAND EXCHANGE!"
|
||||
)
|
||||
default boolean markNewPlayer() { return false; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
keyName = "drawTargetPrayAgainst",
|
||||
name = "Draw what to pray on attacker",
|
||||
description = "Tells you what to pray from what weapon the attacker is holding"
|
||||
)
|
||||
default boolean drawTargetPrayAgainst() { return true; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 9,
|
||||
keyName = "drawPotentialTargetPrayAgainst",
|
||||
name = "Draw what to pray on potential attacker",
|
||||
description = "Tells you what to pray from what weapon the potential attacker is holding"
|
||||
)
|
||||
default boolean drawPotentialTargetPrayAgainst() { return true; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 10,
|
||||
keyName = "drawTargetPrayAgainstPrayerTab",
|
||||
name = "Draw what to pray from prayer tab",
|
||||
description = "Tells you what to pray from what weapon the attacker is holding from the prayer tab"
|
||||
)
|
||||
default boolean drawTargetPrayAgainstPrayerTab() { return false; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 11,
|
||||
keyName = "drawTargetsName",
|
||||
name = "Draw name on attacker",
|
||||
description = "Configures whether or not the attacker\'s name should be shown"
|
||||
)
|
||||
default boolean drawTargetsName() { return true; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 12,
|
||||
keyName = "drawPotentialTargetsName",
|
||||
name = "Draw name on potential attacker",
|
||||
description = "Configures whether or not the potential attacker\'s name should be shown"
|
||||
)
|
||||
default boolean drawPotentialTargetsName() { return true; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 13,
|
||||
keyName = "drawTargetHighlight",
|
||||
name = "Draw highlight around attacker",
|
||||
description = "Configures whether or not the attacker should be highlighted"
|
||||
)
|
||||
default boolean drawTargetHighlight() { return true; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 14,
|
||||
keyName = "drawPotentialTargetHighlight",
|
||||
name = "Draw highlight around potential attacker",
|
||||
description = "Configures whether or not the potential attacker should be highlighted"
|
||||
)
|
||||
default boolean drawPotentialTargetHighlight() { return true; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 15,
|
||||
keyName = "drawTargetTile",
|
||||
name = "Draw tile under attacker",
|
||||
description = "Configures whether or not the attacker\'s tile be highlighted"
|
||||
)
|
||||
default boolean drawTargetTile() { return false; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 16,
|
||||
keyName = "drawPotentialTargetTile",
|
||||
name = "Draw tile under potential attacker",
|
||||
description = "Configures whether or not the potential attacker\'s tile be highlighted"
|
||||
)
|
||||
default boolean drawPotentialTargetTile() { return false; }
|
||||
|
||||
@ConfigItem(
|
||||
position = 17,
|
||||
keyName = "drawUnknownWeapons",
|
||||
name = "Draw unknown weapons",
|
||||
description = "Configures whether or not the unknown weapons should be shown when a player equips one"
|
||||
)
|
||||
default boolean drawUnknownWeapons() { return false; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.runelite.client.plugins.prayagainstplayer;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.kit.KitType;
|
||||
import net.runelite.client.ui.overlay.*;
|
||||
import net.runelite.client.util.Text;
|
||||
import net.runelite.api.Point;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ConcurrentModificationException;
|
||||
|
||||
class PrayAgainstPlayerOverlay extends Overlay {
|
||||
|
||||
private final PrayAgainstPlayerPlugin plugin;
|
||||
private final PrayAgainstPlayerConfig config;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
private PrayAgainstPlayerOverlay(PrayAgainstPlayerPlugin plugin, PrayAgainstPlayerConfig config, Client client) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.client = client;
|
||||
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics) {
|
||||
renderPotentialPlayers(graphics);
|
||||
renderAttackingPlayers(graphics);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderPotentialPlayers(Graphics2D graphics) {
|
||||
if (plugin.getPotentialPlayersAttackingMe() == null || !plugin.getPotentialPlayersAttackingMe().isEmpty()) {
|
||||
try {
|
||||
for (PlayerContainer container : plugin.getPotentialPlayersAttackingMe()) {
|
||||
if ((System.currentTimeMillis() > (container.getWhenTheyAttackedMe() + container.getMillisToExpireHighlight())) && (container.getPlayer().getInteracting() != client.getLocalPlayer())) {
|
||||
plugin.removePlayerFromPotentialContainer(container);
|
||||
}
|
||||
if (config.drawPotentialTargetsName()) renderNameAboveHead(graphics, container.getPlayer(), config.potentialPlayerColor());
|
||||
if (config.drawPotentialTargetHighlight()) renderHighlightedPlayer(graphics, container.getPlayer(), config.potentialPlayerColor());
|
||||
if (config.drawPotentialTargetTile()) renderTileUnderPlayer(graphics, container.getPlayer(), config.potentialPlayerColor());
|
||||
if (config.drawPotentialTargetPrayAgainst()) renderPrayAgainstOnPlayer(graphics, container.getPlayer(), config.potentialPlayerColor());
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderAttackingPlayers(Graphics2D graphics) {
|
||||
if (plugin.getPlayersAttackingMe() == null || !plugin.getPlayersAttackingMe().isEmpty()) {
|
||||
try {
|
||||
for (PlayerContainer container : plugin.getPlayersAttackingMe()) {
|
||||
if ((System.currentTimeMillis() > (container.getWhenTheyAttackedMe() + container.getMillisToExpireHighlight())) && (container.getPlayer().getInteracting() != client.getLocalPlayer())) {
|
||||
plugin.removePlayerFromAttackerContainer(container);
|
||||
}
|
||||
|
||||
if (config.drawTargetsName()) renderNameAboveHead(graphics, container.getPlayer(), config.attackerPlayerColor());
|
||||
if (config.drawTargetHighlight()) renderHighlightedPlayer(graphics, container.getPlayer(), config.attackerPlayerColor());
|
||||
if (config.drawTargetTile()) renderTileUnderPlayer(graphics, container.getPlayer(), config.attackerPlayerColor());
|
||||
if (config.drawTargetPrayAgainst()) renderPrayAgainstOnPlayer(graphics, container.getPlayer(), config.attackerPlayerColor());
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderNameAboveHead(Graphics2D graphics, Player player, Color color) {
|
||||
final String name = Text.sanitize(player.getName());
|
||||
final int offset = player.getLogicalHeight() + 40;
|
||||
Point textLocation = player.getCanvasTextLocation(graphics, name, offset);
|
||||
if (textLocation != null) {
|
||||
OverlayUtil.renderTextLocation(graphics, textLocation, name, color);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderHighlightedPlayer(Graphics2D graphics, Player player, Color color) {
|
||||
try {
|
||||
OverlayUtil.renderPolygon(graphics, player.getConvexHull(), color);
|
||||
} catch (NullPointerException e) {
|
||||
}
|
||||
}
|
||||
|
||||
private void renderTileUnderPlayer(Graphics2D graphics, Player player, Color color) {
|
||||
Polygon poly = player.getCanvasTilePoly();
|
||||
OverlayUtil.renderPolygon(graphics, poly, color);
|
||||
}
|
||||
|
||||
private void renderPrayAgainstOnPlayer(Graphics2D graphics, Player player, Color color) {
|
||||
final int offset = (player.getLogicalHeight() / 2) + 75;
|
||||
BufferedImage icon;
|
||||
|
||||
switch (WeaponType.checkWeaponOnPlayer(client, player)) {
|
||||
case WEAPON_MELEE:
|
||||
icon = plugin.getProtectionIcon(WeaponType.WEAPON_MELEE);
|
||||
break;
|
||||
case WEAPON_MAGIC:
|
||||
icon = plugin.getProtectionIcon(WeaponType.WEAPON_MAGIC);
|
||||
break;
|
||||
case WEAPON_RANGED:
|
||||
icon = plugin.getProtectionIcon(WeaponType.WEAPON_RANGED);
|
||||
break;
|
||||
default:
|
||||
icon = null;
|
||||
break;
|
||||
}
|
||||
try {
|
||||
if (icon != null) {
|
||||
Point point = player.getCanvasImageLocation(icon, offset);
|
||||
OverlayUtil.renderImageLocation(graphics, point, icon);
|
||||
} else {
|
||||
if (config.drawUnknownWeapons()) {
|
||||
int itemId = player.getPlayerComposition().getEquipmentId(KitType.WEAPON);
|
||||
ItemComposition itemComposition = client.getItemDefinition(itemId);
|
||||
|
||||
final String str = itemComposition.getName().toUpperCase();
|
||||
Point point = player.getCanvasTextLocation(graphics, str, offset);
|
||||
OverlayUtil.renderTextLocation(graphics, point, str, color);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.runelite.client.plugins.prayagainstplayer;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.ui.overlay.*;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.*;
|
||||
import java.util.ConcurrentModificationException;
|
||||
|
||||
class PrayAgainstPlayerOverlayPrayerTab extends Overlay {
|
||||
|
||||
private final PrayAgainstPlayerPlugin plugin;
|
||||
private final PrayAgainstPlayerConfig config;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
private PrayAgainstPlayerOverlayPrayerTab (PrayAgainstPlayerPlugin plugin, PrayAgainstPlayerConfig config, Client client) {
|
||||
super(plugin);
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.client = client;
|
||||
|
||||
setPosition(OverlayPosition.DETACHED);
|
||||
setLayer(OverlayLayer.ALWAYS_ON_TOP);
|
||||
setPriority(OverlayPriority.MED);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics) {
|
||||
if (plugin.getPlayersAttackingMe() == null || !plugin.getPlayersAttackingMe().isEmpty()) {
|
||||
try {
|
||||
for (PlayerContainer container : plugin.getPlayersAttackingMe()) {
|
||||
if (plugin.getPlayersAttackingMe() != null && plugin.getPlayersAttackingMe().size() > 0) {
|
||||
//no reason to show you what prayers to pray in your prayer tab if multiple people are attacking you
|
||||
if ((plugin.getPlayersAttackingMe().size() == 1) && (config.drawTargetPrayAgainstPrayerTab())) {
|
||||
renderPrayerToClick(graphics, container.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderPrayerToClick(Graphics2D graphics, Player player) {
|
||||
Widget PROTECT_FROM_MAGIC = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MAGIC);
|
||||
Widget PROTECT_FROM_RANGED = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MISSILES);
|
||||
Widget PROTECT_FROM_MELEE = client.getWidget(WidgetInfo.PRAYER_PROTECT_FROM_MELEE);
|
||||
Color color = Color.RED;
|
||||
if (PROTECT_FROM_MELEE.isHidden()) return;
|
||||
switch (WeaponType.checkWeaponOnPlayer(client, player)) {
|
||||
case WEAPON_MAGIC:
|
||||
OverlayUtil.renderPolygon(graphics, rectangleToPolygon(PROTECT_FROM_MAGIC.getBounds()), color);
|
||||
break;
|
||||
case WEAPON_MELEE:
|
||||
OverlayUtil.renderPolygon(graphics, rectangleToPolygon(PROTECT_FROM_MELEE.getBounds()), color);
|
||||
break;
|
||||
case WEAPON_RANGED:
|
||||
OverlayUtil.renderPolygon(graphics, rectangleToPolygon(PROTECT_FROM_RANGED.getBounds()), color);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static Polygon rectangleToPolygon(Rectangle rect) {
|
||||
int[] xpoints = {rect.x, rect.x + rect.width, rect.x + rect.width, rect.x};
|
||||
int[] ypoints = {rect.y, rect.y, rect.y + rect.height, rect.y + rect.height};
|
||||
return new Polygon(xpoints, ypoints, 4);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.runelite.client.plugins.prayagainstplayer;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.events.*;
|
||||
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.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.*;
|
||||
import java.awt.image.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "<font color=\"aqua\">!Pray Against Player</font>",
|
||||
description = "Use plugin in PvP situations for best results!!",
|
||||
tags = {"highlight", "pvp", "overlay", "players"}
|
||||
)
|
||||
|
||||
/**
|
||||
* I am fully aware that there is plenty of overhead and is a MESS!
|
||||
* If you'd like to contribute please do!
|
||||
*/
|
||||
public class PrayAgainstPlayerPlugin extends Plugin {
|
||||
|
||||
private static final int[] PROTECTION_ICONS = {
|
||||
SpriteID.PRAYER_PROTECT_FROM_MISSILES,
|
||||
SpriteID.PRAYER_PROTECT_FROM_MELEE,
|
||||
SpriteID.PRAYER_PROTECT_FROM_MAGIC
|
||||
};
|
||||
private static final Dimension PROTECTION_ICON_DIMENSION = new Dimension(33, 33);
|
||||
private static final Color PROTECTION_ICON_OUTLINE_COLOR = new Color(33, 33, 33);
|
||||
public final BufferedImage[] ProtectionIcons = new BufferedImage[PROTECTION_ICONS.length];
|
||||
|
||||
private ArrayList<PlayerContainer> potentialPlayersAttackingMe;
|
||||
private ArrayList<PlayerContainer> playersAttackingMe;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private SpriteManager spriteManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private PrayAgainstPlayerOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private PrayAgainstPlayerOverlayPrayerTab overlayPrayerTab;
|
||||
|
||||
@Inject
|
||||
private PrayAgainstPlayerConfig config;
|
||||
|
||||
@Provides
|
||||
PrayAgainstPlayerConfig provideConfig(ConfigManager configManager) {
|
||||
return configManager.getConfig(PrayAgainstPlayerConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged) {
|
||||
if (gameStateChanged.getGameState() == GameState.LOGGED_IN) {
|
||||
loadProtectionIcons();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() {
|
||||
potentialPlayersAttackingMe = new ArrayList<>();
|
||||
playersAttackingMe = new ArrayList<>();
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(overlayPrayerTab);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception {
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(overlayPrayerTab);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
protected void onAnimationChanged(AnimationChanged animationChanged) {
|
||||
if ((animationChanged.getActor() instanceof Player) && (animationChanged.getActor().getInteracting() instanceof Player) && (animationChanged.getActor().getInteracting() == client.getLocalPlayer())) {
|
||||
Player sourcePlayer = (Player) animationChanged.getActor();
|
||||
|
||||
//is the client is a friend/clan and the config is set to ignore friends/clan dont add them to list
|
||||
if (client.isFriended(sourcePlayer.getName(), true) && config.ignoreFriends()) return;
|
||||
if (client.isClanMember(sourcePlayer.getName()) && config.ignoreClanMates()) return;
|
||||
|
||||
if ((sourcePlayer.getAnimation() != -1) && (!isBlockAnimation(sourcePlayer.getAnimation()))) {
|
||||
//if attacker attacks again, reset his timer so overlay doesn't go away
|
||||
if (findPlayerInAttackerList(sourcePlayer) != null) {
|
||||
resetPlayerFromAttackerContainerTimer(findPlayerInAttackerList(sourcePlayer));
|
||||
}
|
||||
//if he attacks and he was in the potential attackers list, remove him
|
||||
if (!potentialPlayersAttackingMe.isEmpty() && potentialPlayersAttackingMe.contains(findPlayerInPotentialList(sourcePlayer))) {
|
||||
removePlayerFromPotentialContainer(findPlayerInPotentialList(sourcePlayer));
|
||||
}
|
||||
//if he's not in the attackers list, add him
|
||||
if (findPlayerInAttackerList(sourcePlayer) == null) {
|
||||
PlayerContainer container = new PlayerContainer(sourcePlayer, System.currentTimeMillis(), (config.attackerTargetTimeout() * 1000));
|
||||
playersAttackingMe.add(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
protected void onInteractingChanged(InteractingChanged interactingChanged) {
|
||||
//if someone interacts with you, add them to the potential attackers list
|
||||
if ((interactingChanged.getSource() instanceof Player) && (interactingChanged.getTarget() instanceof Player)) {
|
||||
Player sourcePlayer = (Player) interactingChanged.getSource();
|
||||
Player targetPlayer = (Player) interactingChanged.getTarget();
|
||||
if ((targetPlayer == client.getLocalPlayer()) && (findPlayerInPotentialList(sourcePlayer) == null)) { //we're being interacted with
|
||||
|
||||
//is the client is a friend/clan and the config is set to ignore friends/clan dont add them to list
|
||||
if (client.isFriended(sourcePlayer.getName(), true) && config.ignoreFriends()) return;
|
||||
if (client.isClanMember(sourcePlayer.getName()) && config.ignoreClanMates()) return;
|
||||
|
||||
PlayerContainer container = new PlayerContainer(sourcePlayer, System.currentTimeMillis(), (config.potentialTargetTimeout() * 1000));
|
||||
potentialPlayersAttackingMe.add(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
protected void onPlayerDespawned(PlayerDespawned playerDespawned) {
|
||||
PlayerContainer container = findPlayerInAttackerList(playerDespawned.getPlayer());
|
||||
PlayerContainer container2 = findPlayerInPotentialList(playerDespawned.getPlayer());
|
||||
if (container != null) {
|
||||
playersAttackingMe.remove(container);
|
||||
}
|
||||
if (container2 != null) {
|
||||
potentialPlayersAttackingMe.remove(container2);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
protected void onPlayerSpawned(PlayerSpawned playerSpawned) {
|
||||
if (config.markNewPlayer()) {
|
||||
Player p = playerSpawned.getPlayer();
|
||||
|
||||
if (client.isFriended(p.getName(), true) && config.ignoreFriends()) return;
|
||||
if (client.isClanMember(p.getName()) && config.ignoreClanMates()) return;
|
||||
|
||||
PlayerContainer container = findPlayerInPotentialList(p);
|
||||
if (container == null) {
|
||||
container = new PlayerContainer(p, System.currentTimeMillis(), (config.newSpawnTimeout() * 1000));
|
||||
potentialPlayersAttackingMe.add(container);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayerContainer findPlayerInAttackerList(Player player) {
|
||||
if (playersAttackingMe.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0 ; i < playersAttackingMe.size() ; i++) {
|
||||
PlayerContainer container = playersAttackingMe.get(i);
|
||||
if (container.getPlayer() == player) {
|
||||
return container;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
PlayerContainer findPlayerInPotentialList(Player player) {
|
||||
if (potentialPlayersAttackingMe.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0 ; i < potentialPlayersAttackingMe.size() ; i++) {
|
||||
PlayerContainer container = potentialPlayersAttackingMe.get(i);
|
||||
if (container.getPlayer() == player) {
|
||||
return container;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets player timer in case he attacks again, so his highlight doesn't go away so easily
|
||||
* @param container
|
||||
*/
|
||||
public void resetPlayerFromAttackerContainerTimer(PlayerContainer container) {
|
||||
removePlayerFromAttackerContainer(container);
|
||||
PlayerContainer newContainer = new PlayerContainer(container.getPlayer(), System.currentTimeMillis(), (config.attackerTargetTimeout() * 1000));
|
||||
playersAttackingMe.add(newContainer);
|
||||
}
|
||||
|
||||
|
||||
public void removePlayerFromPotentialContainer(PlayerContainer container) {
|
||||
if ((potentialPlayersAttackingMe != null) && (!potentialPlayersAttackingMe.isEmpty()) && (potentialPlayersAttackingMe.contains(container))) {
|
||||
potentialPlayersAttackingMe.remove(container);
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlayerFromAttackerContainer(PlayerContainer container) {
|
||||
if ((playersAttackingMe != null) && (!playersAttackingMe.isEmpty()) && (playersAttackingMe.contains(container))) {
|
||||
playersAttackingMe.remove(container);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBlockAnimation(int anim) {
|
||||
switch (anim) {
|
||||
case AnimationID.BLOCK_DEFENDER:
|
||||
case AnimationID.BLOCK_NO_SHIELD:
|
||||
case AnimationID.BLOCK_SHIELD:
|
||||
case AnimationID.BLOCK_SWORD:
|
||||
case AnimationID.BLOCK_UNARMED:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<PlayerContainer> getPotentialPlayersAttackingMe() { return potentialPlayersAttackingMe; }
|
||||
public ArrayList<PlayerContainer> getPlayersAttackingMe() { return playersAttackingMe; }
|
||||
|
||||
//All of the methods below are from the Zulrah plugin!!! Credits to it's respective owner
|
||||
private void loadProtectionIcons() {
|
||||
final IndexedSprite[] protectionIcons = {};
|
||||
final IndexedSprite[] newProtectionIcons = Arrays.copyOf(protectionIcons, PROTECTION_ICONS.length);
|
||||
int curPosition = 0;
|
||||
|
||||
for (int i = 0; i < PROTECTION_ICONS.length; i++, curPosition++)
|
||||
{
|
||||
final int resource = PROTECTION_ICONS[i];
|
||||
ProtectionIcons[i] = rgbaToIndexedBufferedImage(ProtectionIconFromSprite(spriteManager.getSprite(resource, 0)));
|
||||
newProtectionIcons[curPosition] = createIndexedSprite(client, ProtectionIcons[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static IndexedSprite createIndexedSprite(final Client client, final BufferedImage bufferedImage) {
|
||||
final IndexColorModel indexedCM = (IndexColorModel) bufferedImage.getColorModel();
|
||||
|
||||
final int width = bufferedImage.getWidth();
|
||||
final int height = bufferedImage.getHeight();
|
||||
final byte[] pixels = ((DataBufferByte) bufferedImage.getRaster().getDataBuffer()).getData();
|
||||
final int[] palette = new int[indexedCM.getMapSize()];
|
||||
indexedCM.getRGBs(palette);
|
||||
|
||||
final 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(final BufferedImage sourceBufferedImage) {
|
||||
final BufferedImage indexedImage = new BufferedImage(
|
||||
sourceBufferedImage.getWidth(),
|
||||
sourceBufferedImage.getHeight(),
|
||||
BufferedImage.TYPE_BYTE_INDEXED);
|
||||
|
||||
final ColorModel cm = indexedImage.getColorModel();
|
||||
final IndexColorModel icm = (IndexColorModel) cm;
|
||||
|
||||
final int size = icm.getMapSize();
|
||||
final byte[] reds = new byte[size];
|
||||
final byte[] greens = new byte[size];
|
||||
final byte[] blues = new byte[size];
|
||||
icm.getReds(reds);
|
||||
icm.getGreens(greens);
|
||||
icm.getBlues(blues);
|
||||
|
||||
final WritableRaster raster = indexedImage.getRaster();
|
||||
final int pixel = raster.getSample(0, 0, 0);
|
||||
final IndexColorModel resultIcm = new IndexColorModel(8, size, reds, greens, blues, pixel);
|
||||
final BufferedImage resultIndexedImage = new BufferedImage(resultIcm, raster, sourceBufferedImage.isAlphaPremultiplied(), null);
|
||||
resultIndexedImage.getGraphics().drawImage(sourceBufferedImage, 0, 0, null);
|
||||
return resultIndexedImage;
|
||||
}
|
||||
|
||||
private static BufferedImage ProtectionIconFromSprite(final BufferedImage freezeSprite) {
|
||||
final BufferedImage freezeCanvas = ImageUtil.resizeCanvas(freezeSprite, PROTECTION_ICON_DIMENSION.width, PROTECTION_ICON_DIMENSION.height);
|
||||
return ImageUtil.outlineImage(freezeCanvas, PROTECTION_ICON_OUTLINE_COLOR);
|
||||
}
|
||||
|
||||
BufferedImage getProtectionIcon(WeaponType weaponType) {
|
||||
switch (weaponType) {
|
||||
case WEAPON_RANGED:
|
||||
return ProtectionIcons[0];
|
||||
case WEAPON_MELEE:
|
||||
return ProtectionIcons[1];
|
||||
case WEAPON_MAGIC:
|
||||
return ProtectionIcons[2];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2019, gazivodag <https://github.com/gazivodag>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package net.runelite.client.plugins.prayagainstplayer;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.kit.KitType;
|
||||
|
||||
enum WeaponType {
|
||||
|
||||
WEAPON_MELEE,
|
||||
WEAPON_RANGED,
|
||||
WEAPON_MAGIC,
|
||||
WEAPON_UNKNOWN;
|
||||
|
||||
/**
|
||||
* im fully aware this could of been done better!!!
|
||||
* @param client
|
||||
* @param attacker
|
||||
* @return
|
||||
*/
|
||||
public static WeaponType checkWeaponOnPlayer (Client client, Player attacker) {
|
||||
int itemId = attacker.getPlayerComposition().getEquipmentId(KitType.WEAPON);
|
||||
ItemComposition itemComposition = client.getItemDefinition(itemId);
|
||||
String weaponNameGivenLowerCase = itemComposition.getName().toLowerCase();
|
||||
|
||||
if (itemId == -1) return WEAPON_MELEE;
|
||||
if (weaponNameGivenLowerCase == null || weaponNameGivenLowerCase.toLowerCase().contains("null")) return WEAPON_MELEE;
|
||||
|
||||
for (String meleeWeaponName : meleeWeaponNames) {
|
||||
if (weaponNameGivenLowerCase.contains(meleeWeaponName) && !weaponNameGivenLowerCase.contains("thrownaxe")) {
|
||||
return WEAPON_MELEE;
|
||||
}
|
||||
}
|
||||
|
||||
for (String rangedWeaponName : rangedWeaponNames) {
|
||||
if (weaponNameGivenLowerCase.contains(rangedWeaponName)) {
|
||||
return WEAPON_RANGED;
|
||||
}
|
||||
}
|
||||
|
||||
for (String magicWeaponName : magicWeaponNames) {
|
||||
if (weaponNameGivenLowerCase.contains(magicWeaponName)) {
|
||||
return WEAPON_MAGIC;
|
||||
}
|
||||
}
|
||||
|
||||
return WEAPON_UNKNOWN;
|
||||
|
||||
}
|
||||
|
||||
private static String[] meleeWeaponNames = {
|
||||
"sword",
|
||||
"scimitar",
|
||||
"dagger",
|
||||
"spear",
|
||||
"mace",
|
||||
"axe",
|
||||
"whip",
|
||||
"tentacle",
|
||||
"-ket-",
|
||||
"-xil-",
|
||||
"warhammer",
|
||||
"halberd",
|
||||
"claws",
|
||||
"hasta",
|
||||
"scythe",
|
||||
"maul",
|
||||
"anchor",
|
||||
"sabre",
|
||||
"excalibur",
|
||||
"machete",
|
||||
"dragon hunter lance",
|
||||
"event rpg",
|
||||
"silverlight",
|
||||
"darklight",
|
||||
"arclight",
|
||||
"flail",
|
||||
"granite hammer",
|
||||
"rapier",
|
||||
"bulwark"
|
||||
};
|
||||
|
||||
private static String[] rangedWeaponNames = {
|
||||
"bow",
|
||||
"blowpipe",
|
||||
"xil-ul",
|
||||
"knife",
|
||||
"dart",
|
||||
"thrownaxe",
|
||||
"chinchompa",
|
||||
"ballista"
|
||||
};
|
||||
|
||||
private static String[] magicWeaponNames = {
|
||||
"staff",
|
||||
"trident",
|
||||
"wand",
|
||||
"dawnbringer"
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.139.
|
||||
*/
|
||||
package net.runelite.client.plugins.profiles;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
class ProfilePanel
|
||||
extends JPanel {
|
||||
private static final Logger log = LoggerFactory.getLogger(ProfilePanel.class);
|
||||
private static final ImageIcon DELETE_ICON;
|
||||
private static final ImageIcon DELETE_HOVER_ICON;
|
||||
private final String loginText;
|
||||
private String password = null;
|
||||
|
||||
ProfilePanel(final Client client, final String data, final ProfilesConfig config) {
|
||||
String[] parts = data.split(":");
|
||||
this.loginText = parts[1];
|
||||
if (parts.length == 3) {
|
||||
this.password = parts[2];
|
||||
}
|
||||
final ProfilePanel panel = this;
|
||||
this.setLayout(new BorderLayout());
|
||||
this.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
JPanel labelWrapper = new JPanel(new BorderLayout());
|
||||
labelWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
labelWrapper.setBorder(new CompoundBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.DARK_GRAY_COLOR), BorderFactory.createLineBorder(ColorScheme.DARKER_GRAY_COLOR)));
|
||||
JPanel panelActions = new JPanel(new BorderLayout(3, 0));
|
||||
panelActions.setBorder(new EmptyBorder(0, 0, 0, 8));
|
||||
panelActions.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
final JLabel delete = new JLabel();
|
||||
delete.setIcon(DELETE_ICON);
|
||||
delete.setToolTipText("Delete account profile");
|
||||
delete.addMouseListener(new MouseAdapter(){
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
panel.getParent().remove(panel);
|
||||
ProfilesPanel.removeProfile(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
delete.setIcon(DELETE_HOVER_ICON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
delete.setIcon(DELETE_ICON);
|
||||
}
|
||||
});
|
||||
panelActions.add((Component)delete, "East");
|
||||
JLabel label = new JLabel();
|
||||
label.setText(parts[0]);
|
||||
label.setBorder(null);
|
||||
label.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
label.setPreferredSize(new Dimension(0, 24));
|
||||
label.setForeground(Color.WHITE);
|
||||
label.setBorder(new EmptyBorder(0, 8, 0, 0));
|
||||
labelWrapper.add((Component)label, "Center");
|
||||
labelWrapper.add((Component)panelActions, "East");
|
||||
label.addMouseListener(new MouseAdapter(){
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (SwingUtilities.isLeftMouseButton(e) && client.getGameState() == GameState.LOGIN_SCREEN) {
|
||||
client.setUsername(ProfilePanel.this.loginText);
|
||||
if (config.rememberPassword() && ProfilePanel.this.password != null) {
|
||||
client.setPassword(ProfilePanel.this.password);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
JPanel bottomContainer = new JPanel(new BorderLayout());
|
||||
bottomContainer.setBorder(new EmptyBorder(8, 0, 8, 0));
|
||||
bottomContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
bottomContainer.addMouseListener(new MouseAdapter(){
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if (SwingUtilities.isLeftMouseButton(e) && client.getGameState() == GameState.LOGIN_SCREEN) {
|
||||
client.setUsername(ProfilePanel.this.loginText);
|
||||
}
|
||||
}
|
||||
});
|
||||
JLabel login = new JLabel();
|
||||
login.setText(config.isStreamerMode() ? "Hidden email" : this.loginText);
|
||||
login.setBorder(null);
|
||||
login.setPreferredSize(new Dimension(0, 24));
|
||||
login.setForeground(Color.WHITE);
|
||||
login.setBorder(new EmptyBorder(0, 8, 0, 0));
|
||||
bottomContainer.add((Component)login, "Center");
|
||||
this.add((Component)labelWrapper, "North");
|
||||
this.add((Component)bottomContainer, "Center");
|
||||
}
|
||||
|
||||
static {
|
||||
BufferedImage deleteImg = ImageUtil.getResourceStreamFromClass(ProfilesPlugin.class, "net/runelite/client/plugins/profiles/delete_icon.png");
|
||||
DELETE_ICON = new ImageIcon(deleteImg);
|
||||
DELETE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(deleteImg, -100));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.139.
|
||||
*/
|
||||
package net.runelite.client.plugins.profiles;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(value="profiles")
|
||||
public interface ProfilesConfig
|
||||
extends Config {
|
||||
@ConfigItem(keyName="profilesData", name="", description="", hidden=true)
|
||||
default public String profilesData() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@ConfigItem(keyName="profilesData", name="", description="")
|
||||
public void profilesData(String var1);
|
||||
|
||||
@ConfigItem(keyName="rememberPassword", name="Remember Password", description="Remembers passwords for accounts")
|
||||
default public boolean rememberPassword() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(keyName="streamerMode", name="Hide email addresses", description="Hides your account emails")
|
||||
default public boolean isStreamerMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(keyName="switchPanel", name="Auto-open Panel", description="Automatically switch to the account switcher panel on the login screen")
|
||||
default public boolean switchPanel() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.139.
|
||||
*/
|
||||
package net.runelite.client.plugins.profiles;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.LayoutManager;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPasswordField;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.client.plugins.profiles.ProfilePanel;
|
||||
import net.runelite.client.plugins.profiles.ProfilesConfig;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
class ProfilesPanel
|
||||
extends PluginPanel {
|
||||
private static final Logger log = LoggerFactory.getLogger(ProfilesPanel.class);
|
||||
private static final String ACCOUNT_USERNAME = "Account Username";
|
||||
private static final String ACCOUNT_LABEL = "Account Label";
|
||||
private static final String PASSWORD_LABEL = "Account Password";
|
||||
private static final Dimension PREFERRED_SIZE = new Dimension(205, 30);
|
||||
private static final Dimension MINIMUM_SIZE = new Dimension(0, 30);
|
||||
private final Client client;
|
||||
private static ProfilesConfig profilesConfig;
|
||||
private final JTextField txtAccountLabel = new JTextField("Account Label");
|
||||
private final JPasswordField txtAccountLogin = new JPasswordField("Account Username");
|
||||
private final JPasswordField txtPasswordLogin = new JPasswordField("Account Password");
|
||||
private final JPanel profilesPanel = new JPanel();
|
||||
private GridBagConstraints c;
|
||||
|
||||
@Inject
|
||||
public ProfilesPanel(Client client, final ProfilesConfig config) {
|
||||
this.client = client;
|
||||
profilesConfig = config;
|
||||
this.setBorder(new EmptyBorder(18, 10, 0, 10));
|
||||
this.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||
this.setLayout(new GridBagLayout());
|
||||
this.c = new GridBagConstraints();
|
||||
this.c.fill = 2;
|
||||
this.c.gridx = 0;
|
||||
this.c.gridy = 0;
|
||||
this.c.weightx = 1.0;
|
||||
this.c.weighty = 0.0;
|
||||
this.c.insets = new Insets(0, 0, 4, 0);
|
||||
this.txtAccountLabel.setPreferredSize(PREFERRED_SIZE);
|
||||
this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtAccountLabel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
this.txtAccountLabel.setMinimumSize(MINIMUM_SIZE);
|
||||
this.txtAccountLabel.addFocusListener(new FocusListener(){
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (ProfilesPanel.this.txtAccountLabel.getText().equals(ProfilesPanel.ACCOUNT_LABEL)) {
|
||||
ProfilesPanel.this.txtAccountLabel.setText("");
|
||||
ProfilesPanel.this.txtAccountLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (ProfilesPanel.this.txtAccountLabel.getText().isEmpty()) {
|
||||
ProfilesPanel.this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
ProfilesPanel.this.txtAccountLabel.setText(ProfilesPanel.ACCOUNT_LABEL);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.add((Component)this.txtAccountLabel, this.c);
|
||||
++this.c.gridy;
|
||||
this.txtAccountLogin.setEchoChar('\u0000');
|
||||
this.txtAccountLogin.setPreferredSize(PREFERRED_SIZE);
|
||||
this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtAccountLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
this.txtAccountLogin.setMinimumSize(MINIMUM_SIZE);
|
||||
this.txtAccountLogin.addFocusListener(new FocusListener(){
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (ProfilesPanel.ACCOUNT_USERNAME.equals(String.valueOf(ProfilesPanel.this.txtAccountLogin.getPassword()))) {
|
||||
ProfilesPanel.this.txtAccountLogin.setText("");
|
||||
if (config.isStreamerMode()) {
|
||||
ProfilesPanel.this.txtAccountLogin.setEchoChar('*');
|
||||
}
|
||||
ProfilesPanel.this.txtAccountLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (ProfilesPanel.this.txtAccountLogin.getPassword().length == 0) {
|
||||
ProfilesPanel.this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
ProfilesPanel.this.txtAccountLogin.setText(ProfilesPanel.ACCOUNT_USERNAME);
|
||||
ProfilesPanel.this.txtAccountLogin.setEchoChar('\u0000');
|
||||
}
|
||||
}
|
||||
});
|
||||
this.add((Component)this.txtAccountLogin, this.c);
|
||||
++this.c.gridy;
|
||||
this.txtPasswordLogin.setEchoChar('\u0000');
|
||||
this.txtPasswordLogin.setPreferredSize(PREFERRED_SIZE);
|
||||
this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtPasswordLogin.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
this.txtPasswordLogin.setToolTipText("Account password");
|
||||
this.txtPasswordLogin.setMinimumSize(MINIMUM_SIZE);
|
||||
this.txtPasswordLogin.addFocusListener(new FocusListener(){
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (ProfilesPanel.PASSWORD_LABEL.equals(String.valueOf(ProfilesPanel.this.txtPasswordLogin.getPassword()))) {
|
||||
ProfilesPanel.this.txtPasswordLogin.setText("");
|
||||
ProfilesPanel.this.txtPasswordLogin.setEchoChar('*');
|
||||
ProfilesPanel.this.txtPasswordLogin.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (ProfilesPanel.this.txtPasswordLogin.getPassword().length == 0) {
|
||||
ProfilesPanel.this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
ProfilesPanel.this.txtPasswordLogin.setText(ProfilesPanel.PASSWORD_LABEL);
|
||||
ProfilesPanel.this.txtPasswordLogin.setEchoChar('\u0000');
|
||||
}
|
||||
}
|
||||
});
|
||||
if (config.rememberPassword()) {
|
||||
this.add((Component)this.txtPasswordLogin, this.c);
|
||||
++this.c.gridy;
|
||||
}
|
||||
this.c.insets = new Insets(0, 0, 15, 0);
|
||||
final JButton btnAddAccount = new JButton("Add Account");
|
||||
btnAddAccount.setPreferredSize(PREFERRED_SIZE);
|
||||
btnAddAccount.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
btnAddAccount.setMinimumSize(MINIMUM_SIZE);
|
||||
btnAddAccount.addActionListener(e -> {
|
||||
String labelText = String.valueOf(this.txtAccountLabel.getText());
|
||||
String loginText = String.valueOf(this.txtAccountLogin.getPassword());
|
||||
String passwordText = String.valueOf(this.txtPasswordLogin.getPassword());
|
||||
if (labelText.equals(ACCOUNT_LABEL) || loginText.equals(ACCOUNT_USERNAME)) {
|
||||
return;
|
||||
}
|
||||
String data = config.rememberPassword() && this.txtPasswordLogin.getPassword() != null ? labelText + ":" + loginText + ":" + passwordText : labelText + ":" + loginText;
|
||||
log.info(data);
|
||||
this.addAccount(data);
|
||||
ProfilesPanel.addProfile(data);
|
||||
this.txtAccountLabel.setText(ACCOUNT_LABEL);
|
||||
this.txtAccountLabel.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtAccountLogin.setText(ACCOUNT_USERNAME);
|
||||
this.txtAccountLogin.setEchoChar('\u0000');
|
||||
this.txtAccountLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
this.txtPasswordLogin.setText(PASSWORD_LABEL);
|
||||
this.txtPasswordLogin.setEchoChar('\u0000');
|
||||
this.txtPasswordLogin.setForeground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||
});
|
||||
this.txtAccountLogin.addKeyListener(new KeyAdapter(){
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (e.getKeyCode() == 10) {
|
||||
btnAddAccount.doClick();
|
||||
btnAddAccount.requestFocus();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.txtAccountLogin.addMouseListener(new MouseListener(){
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
});
|
||||
this.add((Component)btnAddAccount, this.c);
|
||||
++this.c.gridy;
|
||||
this.profilesPanel.setLayout(new GridBagLayout());
|
||||
this.add((Component)this.profilesPanel, this.c);
|
||||
this.c.gridy = 0;
|
||||
this.c.insets = new Insets(0, 0, 5, 0);
|
||||
this.addAccounts(config.profilesData());
|
||||
}
|
||||
|
||||
void redrawProfiles() {
|
||||
this.profilesPanel.removeAll();
|
||||
this.c.gridy = 0;
|
||||
this.addAccounts(profilesConfig.profilesData());
|
||||
}
|
||||
|
||||
private void addAccount(String data) {
|
||||
ProfilePanel profile = new ProfilePanel(this.client, data, profilesConfig);
|
||||
++this.c.gridy;
|
||||
this.profilesPanel.add((Component)profile, this.c);
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
void addAccounts(String data) {
|
||||
if (!(data = data.trim()).contains(":")) {
|
||||
return;
|
||||
}
|
||||
Arrays.stream(data.split("\\n")).forEach(this::addAccount);
|
||||
}
|
||||
|
||||
static void addProfile(String data) {
|
||||
profilesConfig.profilesData(profilesConfig.profilesData() + data + "\n");
|
||||
}
|
||||
|
||||
static void removeProfile(String data) {
|
||||
profilesConfig.profilesData(profilesConfig.profilesData().replaceAll(data + "\\n", ""));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Decompiled with CFR 0.139.
|
||||
*/
|
||||
package net.runelite.client.plugins.profiles;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.logging.Logger;
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
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.ClientToolbar;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
@PluginDescriptor(name="Account Switcher", description="Allow for a allows you to easily switch between multiple OSRS Accounts", tags={"profile", "account", "login", "log in"})
|
||||
public class ProfilesPlugin
|
||||
extends Plugin {
|
||||
@Inject
|
||||
private ClientToolbar clientToolbar;
|
||||
@Inject
|
||||
private Client client;
|
||||
@Inject
|
||||
private ProfilesConfig config;
|
||||
private ProfilesPanel panel;
|
||||
private NavigationButton navButton;
|
||||
String text = "Hello World";
|
||||
private static String key = "Bar12345Bar12345";
|
||||
private static Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
|
||||
|
||||
@Provides
|
||||
ProfilesConfig getConfig(ConfigManager configManager) {
|
||||
return configManager.getConfig(ProfilesConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception {
|
||||
this.panel = this.injector.getInstance(ProfilesPanel.class);
|
||||
BufferedImage icon = ImageUtil.getResourceStreamFromClass(this.getClass(), "/net/runelite/client/plugins/profiles/profiles_icon.png");
|
||||
this.navButton = NavigationButton.builder().tooltip("Profiles").icon(icon).priority(8).panel(this.panel).build();
|
||||
this.clientToolbar.addNavigation(this.navButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() {
|
||||
this.clientToolbar.removeNavigation(this.navButton);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onConfigChanged(ConfigChanged event) throws Exception {
|
||||
if (event.getGroup().equals("profiles") && event.getKey().equals("rememberPassword")) {
|
||||
this.panel = this.injector.getInstance(ProfilesPanel.class);
|
||||
this.shutDown();
|
||||
this.startUp();
|
||||
}
|
||||
}
|
||||
|
||||
public static String decryptText(String text) {
|
||||
byte[] bb = new byte[text.length()];
|
||||
for (int i = 0; i < text.length(); ++i) {
|
||||
bb[i] = (byte)text.charAt(i);
|
||||
}
|
||||
Cipher cipher = null;
|
||||
try {
|
||||
cipher = Cipher.getInstance("AES");
|
||||
}
|
||||
catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
cipher.init(2, aesKey);
|
||||
}
|
||||
catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
Logger.getLogger("EncryptionLogger").info("Decrypted " + text + " to " + new String(cipher.doFinal(bb)));
|
||||
return new String(cipher.doFinal(bb));
|
||||
}
|
||||
catch (BadPaddingException | IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public static String encryptText(String text) {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance("AES");
|
||||
cipher.init(1, aesKey);
|
||||
byte[] encrypted = cipher.doFinal(text.getBytes());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : encrypted) {
|
||||
sb.append((char)b);
|
||||
}
|
||||
Logger.getLogger("EncryptionLogger").info("Encrypted " + text + " to " + sb.toString());
|
||||
return sb.toString();
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (NoSuchPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (BadPaddingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (IllegalBlockSizeException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (InvalidKeyException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Steffen Hauge <steffen.oerum.hauge@hotmail.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.pyramidplunder;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.util.Set;
|
||||
import static net.runelite.api.ObjectID.SPEARTRAP_21280;
|
||||
|
||||
public class Obstacles
|
||||
{
|
||||
static final Set<Integer> WALL_OBSTACLE_IDS = ImmutableSet.of(
|
||||
26618, 26619, 26620, 26621
|
||||
);
|
||||
|
||||
static final Set<Integer> TRAP_OBSTACLE_IDS = ImmutableSet.of(
|
||||
SPEARTRAP_21280
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Steffen Hauge <steffen.oerum.hauge@hotmail.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.pyramidplunder;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("pyramidplunder")
|
||||
public interface PyramidPlunderConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "highlightDoors",
|
||||
name = "Highlights doors",
|
||||
description = "Highlights the four doors in each room"
|
||||
)
|
||||
default boolean highlightDoors()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "highlightSpearTrap",
|
||||
name = "Highlights spear traps",
|
||||
description = "Highlights the spear traps in each room"
|
||||
)
|
||||
default boolean highlightSpearTrap()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "showTimer",
|
||||
name = "Display numerical timer",
|
||||
description = "Displays a numerical timer instead of the default timer"
|
||||
)
|
||||
default boolean showTimer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Steffen Hauge <steffen.oerum.hauge@hotmail.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.pyramidplunder;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Area;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ObjectComposition;
|
||||
import static net.runelite.api.ObjectID.SPEARTRAP_21280;
|
||||
import static net.runelite.api.ObjectID.TOMB_DOOR_20948;
|
||||
import static net.runelite.api.ObjectID.TOMB_DOOR_20949;
|
||||
import net.runelite.api.Point;
|
||||
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;
|
||||
|
||||
public class PyramidPlunderOverlay extends Overlay
|
||||
{
|
||||
private static final int MAX_DISTANCE = 2400;
|
||||
private static final Color COLOR_DOOR = Color.GREEN;
|
||||
private static final Color COLOR_SPEAR_TRAP = Color.ORANGE;
|
||||
|
||||
private final Client client;
|
||||
private final PyramidPlunderPlugin plugin;
|
||||
private final PyramidPlunderConfig config;
|
||||
|
||||
@Inject
|
||||
private PyramidPlunderOverlay(Client client, PyramidPlunderPlugin plugin, PyramidPlunderConfig config)
|
||||
{
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.isInGame())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
LocalPoint playerLocation = client.getLocalPlayer().getLocalLocation();
|
||||
Point mousePosition = client.getMouseCanvasPosition();
|
||||
|
||||
plugin.getObstacles().forEach((object, tile) ->
|
||||
{
|
||||
if (Obstacles.WALL_OBSTACLE_IDS.contains(object.getId()) && !config.highlightDoors() ||
|
||||
Obstacles.TRAP_OBSTACLE_IDS.contains(object.getId()) && !config.highlightSpearTrap())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (tile.getPlane() == client.getPlane() &&
|
||||
object.getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE)
|
||||
{
|
||||
int objectID = object.getId();
|
||||
if (Obstacles.WALL_OBSTACLE_IDS.contains(object.getId()))
|
||||
{
|
||||
//Impostor
|
||||
ObjectComposition comp = client.getObjectDefinition(objectID);
|
||||
ObjectComposition impostor = comp.getImpostor();
|
||||
|
||||
if (impostor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
objectID = impostor.getId();
|
||||
}
|
||||
|
||||
Area objectClickbox = object.getClickbox();
|
||||
if (objectClickbox != null)
|
||||
{
|
||||
Color configColor = Color.GREEN;
|
||||
switch (objectID)
|
||||
{
|
||||
case SPEARTRAP_21280:
|
||||
configColor = COLOR_SPEAR_TRAP;
|
||||
break;
|
||||
case TOMB_DOOR_20948:
|
||||
case TOMB_DOOR_20949:
|
||||
configColor = COLOR_DOOR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (objectClickbox.contains(mousePosition.getX(), mousePosition.getY()))
|
||||
{
|
||||
graphics.setColor(configColor.darker());
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.setColor(configColor);
|
||||
}
|
||||
|
||||
graphics.draw(objectClickbox);
|
||||
graphics.setColor(new Color(configColor.getRed(), configColor.getGreen(), configColor.getBlue(), 50));
|
||||
graphics.fill(objectClickbox);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Steffen Hauge <steffen.oerum.hauge@hotmail.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.pyramidplunder;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Provides;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.TileObject;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameObjectChanged;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.events.WallObjectChanged;
|
||||
import net.runelite.api.events.WallObjectDespawned;
|
||||
import net.runelite.api.events.WallObjectSpawned;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
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;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "PyramidPlunder",
|
||||
description = "Highlights doors and spear traps in pyramid plunder and adds a numerical timer",
|
||||
tags = {"pyramidplunder", "pyramid", "plunder", "overlay", "skilling", "thieving"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
|
||||
public class PyramidPlunderPlugin extends Plugin
|
||||
{
|
||||
private static final int PYRAMIND_PLUNDER_REGION_ID = 7749;
|
||||
private static final int PYRAMIND_PLUNDER_TIMER_MAX = 500;
|
||||
private static final double GAMETICK_SECOND = 0.6;
|
||||
|
||||
@Getter
|
||||
private final Map<TileObject, Tile> obstacles = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private PyramidPlunderConfig config;
|
||||
|
||||
@Inject
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private PyramidPlunderOverlay pyramidPlunderOverlay;
|
||||
|
||||
@Getter
|
||||
private boolean isInGame;
|
||||
|
||||
private int pyramidTimer = 0;
|
||||
|
||||
@Provides
|
||||
PyramidPlunderConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(PyramidPlunderConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(pyramidPlunderOverlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(pyramidPlunderOverlay);
|
||||
obstacles.clear();
|
||||
reset();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (!config.showTimer())
|
||||
{
|
||||
removeTimer();
|
||||
}
|
||||
|
||||
if (config.showTimer() && isInGame)
|
||||
{
|
||||
int remainingTime = PYRAMIND_PLUNDER_TIMER_MAX - pyramidTimer;
|
||||
|
||||
if (remainingTime >= 2)
|
||||
{
|
||||
double timeInSeconds = remainingTime * GAMETICK_SECOND;
|
||||
showTimer((int)timeInSeconds, ChronoUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeTimer()
|
||||
{
|
||||
infoBoxManager.removeIf(infoBox -> infoBox instanceof PyramidPlunderTimer);
|
||||
}
|
||||
|
||||
private void showTimer()
|
||||
{
|
||||
showTimer(5, ChronoUnit.MINUTES);
|
||||
}
|
||||
|
||||
private void showTimer(int period, ChronoUnit chronoUnit)
|
||||
{
|
||||
removeTimer();
|
||||
infoBoxManager.addInfoBox(new PyramidPlunderTimer(this, itemManager.getImage(PHARAOHS_SCEPTRE), period, chronoUnit));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChange(GameStateChanged event)
|
||||
{
|
||||
switch (event.getGameState())
|
||||
{
|
||||
case HOPPING:
|
||||
case LOGIN_SCREEN:
|
||||
reset();
|
||||
break;
|
||||
case LOADING:
|
||||
obstacles.clear();
|
||||
case LOGGED_IN:
|
||||
if (!isInRegion())
|
||||
{
|
||||
reset();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInRegion()
|
||||
{
|
||||
Player local = client.getLocalPlayer();
|
||||
if (local == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WorldPoint location = local.getWorldLocation();
|
||||
if (location.getRegionID() != PYRAMIND_PLUNDER_REGION_ID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
int lastValue = pyramidTimer;
|
||||
pyramidTimer = client.getVar(Varbits.PYRAMID_PLUNDER_TIMER);
|
||||
|
||||
if (lastValue == pyramidTimer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (pyramidTimer == 0)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
if (pyramidTimer == 1)
|
||||
{
|
||||
isInGame = true;
|
||||
if (config.showTimer())
|
||||
{
|
||||
showTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reset()
|
||||
{
|
||||
isInGame = false;
|
||||
removeTimer();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectSpawned(GameObjectSpawned event)
|
||||
{
|
||||
onTileObject(event.getTile(), null, event.getGameObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectChanged(GameObjectChanged event)
|
||||
{
|
||||
onTileObject(event.getTile(), event.getPrevious(), event.getGameObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameObjectDeSpawned(GameObjectDespawned event)
|
||||
{
|
||||
onTileObject(event.getTile(), event.getGameObject(), null);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWallObjectSpawned(WallObjectSpawned event)
|
||||
{
|
||||
onTileObject(event.getTile(), null, event.getWallObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWallObjectChanged(WallObjectChanged event)
|
||||
{
|
||||
onTileObject(event.getTile(), event.getPrevious(), event.getWallObject());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWallObjectDeSpawned(WallObjectDespawned event)
|
||||
{
|
||||
onTileObject(event.getTile(), event.getWallObject(), null);
|
||||
}
|
||||
|
||||
private void onTileObject(Tile tile, TileObject oldObject, TileObject newObject)
|
||||
{
|
||||
obstacles.remove(oldObject);
|
||||
|
||||
if (newObject == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Obstacles.WALL_OBSTACLE_IDS.contains(newObject.getId()) ||
|
||||
Obstacles.TRAP_OBSTACLE_IDS.contains(newObject.getId()))
|
||||
{
|
||||
obstacles.put(newObject, tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Steffen Hauge <steffen.oerum.hauge@hotmail.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.pyramidplunder;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.ui.overlay.infobox.Timer;
|
||||
|
||||
public class PyramidPlunderTimer extends Timer
|
||||
{
|
||||
PyramidPlunderTimer(Plugin plugin, BufferedImage image, int period, ChronoUnit chronoUnit)
|
||||
{
|
||||
super(period, chronoUnit, image, plugin);
|
||||
setTooltip("Time left until minigame ends");
|
||||
}
|
||||
}
|
||||
@@ -139,7 +139,7 @@ class ScreenMarkerPanel extends JPanel
|
||||
INVISIBLE_ICON = new ImageIcon(invisibleImg);
|
||||
INVISIBLE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(invisibleImg, -100));
|
||||
|
||||
final BufferedImage deleteImg = ImageUtil.getResourceStreamFromClass(ScreenMarkerPlugin.class, "delete_icon.png");
|
||||
final BufferedImage deleteImg = ImageUtil.getResourceStreamFromClass(ScreenMarkerPlugin.class, "net/runelite/client/plugins/profiles/delete_icon.png");
|
||||
DELETE_ICON = new ImageIcon(deleteImg);
|
||||
DELETE_HOVER_ICON = new ImageIcon(ImageUtil.alphaOffset(deleteImg, -100));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.shayzieninfirmary;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
public class ShayzienInfirmaryOverlay extends Overlay
|
||||
{
|
||||
private final ShayzienInfirmaryPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
private BufferedImage medPackImage;
|
||||
|
||||
@Inject
|
||||
public ShayzienInfirmaryOverlay(ShayzienInfirmaryPlugin plugin, Client client, ItemManager itemManager)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
|
||||
medPackImage = itemManager.getImage(ItemID.SHAYZIEN_MEDPACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.isAtInfirmary())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (NPC npc : plugin.getUnhealedSoldiers())
|
||||
{
|
||||
|
||||
Polygon tilePoly = npc.getCanvasTilePoly();
|
||||
|
||||
if (tilePoly == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
OverlayUtil.renderPolygon(graphics, npc.getCanvasTilePoly(), Color.ORANGE);
|
||||
|
||||
Point imageLocation = npc.getCanvasImageLocation(medPackImage, 25);
|
||||
|
||||
if (imageLocation == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Composite originalComposite = graphics.getComposite();
|
||||
Composite translucentComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f);
|
||||
|
||||
graphics.setComposite(translucentComposite);
|
||||
|
||||
OverlayUtil.renderImageLocation(graphics, imageLocation, medPackImage);
|
||||
|
||||
graphics.setComposite(originalComposite);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Yani <yani@xenokore.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.shayzieninfirmary;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.events.GameTick;
|
||||
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;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "Shayzien Infirmary",
|
||||
description = "Shows the status of wounded soldiers",
|
||||
tags = {"shayzien", "infirmary", "soldiers"}
|
||||
)
|
||||
public class ShayzienInfirmaryPlugin extends Plugin
|
||||
{
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<NPC> unhealedSoldiers = new ArrayList<NPC>();
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ShayzienInfirmaryOverlay overlay;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
loadPlugin();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
unloadPlugin();
|
||||
}
|
||||
|
||||
private void loadPlugin()
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
}
|
||||
|
||||
private void unloadPlugin()
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
if(!isAtInfirmary())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
unhealedSoldiers.clear();
|
||||
|
||||
for (NPC npc : client.getNpcs())
|
||||
{
|
||||
if (isUnhealedSoldierId(npc.getId()))
|
||||
{
|
||||
unhealedSoldiers.add(npc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSoldierId(int npcId)
|
||||
{
|
||||
return (npcId >= 6826 && npcId <= 6857);
|
||||
}
|
||||
|
||||
public boolean isUnhealedSoldierId(int npcId)
|
||||
{
|
||||
return (isSoldierId(npcId) && npcId % 2 == 0);
|
||||
}
|
||||
|
||||
public boolean isHealedSoldierId(int npcId)
|
||||
{
|
||||
return (isSoldierId(npcId) && npcId % 2 == 1);
|
||||
}
|
||||
|
||||
public boolean isAtInfirmary()
|
||||
{
|
||||
return client.getLocalPlayer().getWorldLocation().getRegionID() == 6200;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Plinko60
|
||||
* 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.shiftwalker;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("shiftwalkhere")
|
||||
public interface ShiftWalkerConfig extends Config
|
||||
{
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "shiftWalkEverything",
|
||||
name = "Walk Under Everything",
|
||||
description = "Enable this option when you do not want to interact with anything while Shift is pressed. " +
|
||||
"If Walk Here is an option it will be the action taken."
|
||||
)
|
||||
default boolean shiftWalkEverything()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "shiftWalkBoxTraps",
|
||||
name = "Walk Under Box Traps",
|
||||
description = "Press \"Shift\" to be able to walk under instead of picking up a Box Trap."
|
||||
)
|
||||
default boolean shiftWalkBoxTraps()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "shiftWalkAttackOption",
|
||||
name = "Walk Under Attack Options",
|
||||
description = "Press \"Shift\" to be able to walk instead of attacking. Make sure Left Click Attack is on."
|
||||
)
|
||||
default boolean shiftWalkAttackOption()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package net.runelite.client.plugins.shiftwalker;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
public final class ShiftWalkerGroups
|
||||
{
|
||||
//Specific Targets to limit the walking to
|
||||
private static final String BOX_TRAP = "BOX TRAP";
|
||||
private static final String BOX_TRAP_SHAKING = "SHAKING BOX";
|
||||
|
||||
//Specific menu options to replace
|
||||
private static final String BOX_TRAP_DISMANTLE = "DISMANTLE";
|
||||
private static final String BOX_TRAP_CHECK = "CHECK";
|
||||
|
||||
private static final String ATTACK_OPTIONS_ATTACK = "ATTACK";
|
||||
|
||||
public static final HashSet<String> BOX_TRAP_TARGETS = new HashSet<>();
|
||||
public static final HashSet<String> BOX_TRAP_KEYWORDS = new HashSet<>();
|
||||
public static final HashSet<String> ATTACK_OPTIONS_KEYWORDS = new HashSet<>();
|
||||
|
||||
static
|
||||
{
|
||||
BOX_TRAP_TARGETS.add(BOX_TRAP);
|
||||
BOX_TRAP_TARGETS.add(BOX_TRAP_SHAKING);
|
||||
|
||||
BOX_TRAP_KEYWORDS.add(BOX_TRAP_DISMANTLE);
|
||||
BOX_TRAP_KEYWORDS.add(BOX_TRAP_CHECK);
|
||||
|
||||
ATTACK_OPTIONS_KEYWORDS.add(ATTACK_OPTIONS_ATTACK);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Plinko60
|
||||
* 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.shiftwalker;
|
||||
|
||||
import net.runelite.client.input.KeyListener;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.event.KeyEvent;
|
||||
|
||||
public class ShiftWalkerInputListener implements KeyListener
|
||||
{
|
||||
|
||||
@Inject
|
||||
private ShiftWalkerPlugin plugin;
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent event)
|
||||
{
|
||||
if (event.getKeyCode() == KeyEvent.VK_SHIFT)
|
||||
{
|
||||
plugin.setHotKeyPressed(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent event)
|
||||
{
|
||||
if (event.getKeyCode() == KeyEvent.VK_SHIFT)
|
||||
{
|
||||
plugin.setHotKeyPressed(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Plinko60
|
||||
* 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.shiftwalker;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.events.*;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Shift Walker Plugin. Credit to MenuEntrySwapperPlugin for code some code structure used here.
|
||||
*/
|
||||
@PluginDescriptor(
|
||||
name = "<font color=\"green\">!Shift To Walk Here</font>",
|
||||
description = "Use Shift to toggle the Walk Here menu option. While pressed you will Walk rather than interact with objects.",
|
||||
tags = {"npcs", "items", "objects"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class ShiftWalkerPlugin extends Plugin
|
||||
{
|
||||
|
||||
private static final String WALK_HERE = "WALK HERE";
|
||||
private static final String CANCEL = "CANCEL";
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ShiftWalkerConfig config;
|
||||
|
||||
@Inject
|
||||
private ShiftWalkerInputListener inputListener;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
@Setter
|
||||
private boolean hotKeyPressed = false;
|
||||
|
||||
@Provides
|
||||
ShiftWalkerConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(ShiftWalkerConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
keyManager.registerKeyListener(inputListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
keyManager.unregisterKeyListener(inputListener);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onFocusChanged(FocusChanged event)
|
||||
{
|
||||
if (!event.isFocused())
|
||||
{
|
||||
hotKeyPressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event when a new menu entry was added.
|
||||
* @param event {@link MenuEntryAdded}.
|
||||
*/
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN || !hotKeyPressed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final String pOptionToReplace = Text.removeTags(event.getOption()).toUpperCase();
|
||||
|
||||
//If the option is already to walk there, or cancel we don't need to swap it with anything
|
||||
if (pOptionToReplace.equals(CANCEL) || pOptionToReplace.equals(WALK_HERE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String target = Text.removeTags(event.getTarget().toUpperCase());
|
||||
|
||||
if (config.shiftWalkEverything())
|
||||
{
|
||||
//swap(pOptionToReplace); //Swap everything with walk here
|
||||
stripEntries();
|
||||
}
|
||||
else if (config.shiftWalkBoxTraps() && ShiftWalkerGroups.BOX_TRAP_TARGETS.contains(target)
|
||||
&& ShiftWalkerGroups.BOX_TRAP_KEYWORDS.contains(pOptionToReplace))
|
||||
{
|
||||
//swap(pOptionToReplace); //Swap only on box traps
|
||||
stripEntries();
|
||||
}
|
||||
else if (config.shiftWalkAttackOption() && ShiftWalkerGroups.ATTACK_OPTIONS_KEYWORDS.contains(pOptionToReplace))
|
||||
{
|
||||
//swap(pOptionToReplace); //Swap on everything that has an attack keyword as the first option
|
||||
stripEntries();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip everything except "Walk here"
|
||||
* Other way was unconventional because if there was multiple targets in the menu entry it wouldn't swap correctly
|
||||
*/
|
||||
private void stripEntries() {
|
||||
MenuEntry walkkHereEntry = null;
|
||||
|
||||
for (MenuEntry entry : client.getMenuEntries()) {
|
||||
switch (entry.getOption()) {
|
||||
case "Walk here":
|
||||
walkkHereEntry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (walkkHereEntry != null) {
|
||||
MenuEntry[] newEntries = new MenuEntry[1];
|
||||
newEntries[0] = walkkHereEntry;
|
||||
client.setMenuEntries(newEntries);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps menu entries if the entries could be found. This places Walk Here where the top level menu option was.
|
||||
* @param pOptionToReplace The String containing the Menu Option that needs to be replaced. IE: "Attack", "Chop Down".
|
||||
*/
|
||||
private void swap(String pOptionToReplace)
|
||||
{
|
||||
MenuEntry[] entries = client.getMenuEntries();
|
||||
|
||||
Integer walkHereEntry = searchIndex(entries, WALK_HERE);
|
||||
Integer entryToReplace = searchIndex(entries, pOptionToReplace);
|
||||
|
||||
if (walkHereEntry != null
|
||||
&& entryToReplace != null)
|
||||
{
|
||||
MenuEntry walkHereMenuEntry = entries[walkHereEntry];
|
||||
entries[walkHereEntry] = entries[entryToReplace];
|
||||
entries[entryToReplace] = walkHereMenuEntry;
|
||||
|
||||
client.setMenuEntries(entries);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the index of the menu that contains the verbiage we are looking for.
|
||||
* @param pMenuEntries The list of {@link MenuEntry}s.
|
||||
* @param pMenuEntryToSearchFor The Option in the menu to search for.
|
||||
* @return The index location or null if it was not found.
|
||||
*/
|
||||
private Integer searchIndex(MenuEntry[] pMenuEntries, String pMenuEntryToSearchFor)
|
||||
{
|
||||
Integer indexLocation = 0;
|
||||
|
||||
for (MenuEntry menuEntry : pMenuEntries)
|
||||
{
|
||||
String entryOption = Text.removeTags(menuEntry.getOption()).toUpperCase();
|
||||
|
||||
if (entryOption.equals(pMenuEntryToSearchFor))
|
||||
{
|
||||
return indexLocation;
|
||||
}
|
||||
|
||||
indexLocation++;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
package net.runelite.client.plugins.slayermusiq;
|
||||
|
||||
import net.runelite.client.util.LinkBrowser;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.client.chat.ChatColorType;
|
||||
import net.runelite.client.chat.ChatMessageBuilder;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
|
||||
public class QuestGuideLinks {
|
||||
private static final Link[] QUEST_GUIDE_LINKS = {
|
||||
// Free Quests
|
||||
new Link("Cook's Assistant", "https://www.youtube.com/watch?v=ehmtDRelj3c"),
|
||||
new Link("Romeo & Juliet", "https://www.youtube.com/watch?v=rH_biWSNWVY"),
|
||||
new Link("Demon Slayer", "https://www.youtube.com/watch?v=hgACrzJSiQk"),
|
||||
new Link("Shield of Arrav", "https://www.youtube.com/watch?v=a_imLDKUdzg"),
|
||||
new Link("Sheep Shearer", "https://www.youtube.com/watch?v=XFG3aNwK68s"),
|
||||
new Link("The Restless Ghost", "https://www.youtube.com/watch?v=UkWNcsG_pXM"),
|
||||
new Link("Ernest the Chicken", "https://www.youtube.com/watch?v=cq8NIVhSqh4"),
|
||||
new Link("Vampire Slayer", "https://www.youtube.com/watch?v=FcEuxsDJWCU"),
|
||||
new Link("Imp Catcher", "https://www.youtube.com/watch?v=LHgnl0FbOzk"),
|
||||
new Link("Prince Ali Rescue", "https://www.youtube.com/watch?v=hrSPl1GfFaw"),
|
||||
new Link("Doric's Quest", "https://www.youtube.com/watch?v=5TYyxHU27a4"),
|
||||
new Link("Black Knights' Fortress", "https://www.youtube.com/watch?v=aekoZi3f9cU"),
|
||||
new Link("Witch's Potion", "https://www.youtube.com/watch?v=XV4i5sPUvXo"),
|
||||
new Link("The Knight's Sword", "https://www.youtube.com/watch?v=UkBWaI0rOqE"),
|
||||
new Link("Goblin Diplomacy", "https://www.youtube.com/watch?v=P9BKOb_dLoY"),
|
||||
new Link("Pirate's Treasure", "https://www.youtube.com/watch?v=zcD87PQW8Qk"),
|
||||
new Link("Dragon Slayer", "https://www.youtube.com/watch?v=bMtCjlFOaBI"),
|
||||
new Link("Rune Mysteries", "https://www.youtube.com/watch?v=l8ZhaN8uoS0"),
|
||||
new Link("Misthalin Mystery", "https://www.youtube.com/watch?v=QlFqVAobAlQ"),
|
||||
new Link("The Corsair Curse", "https://www.youtube.com/watch?v=wi7mUAHExz4"),
|
||||
new Link("X Marks the Spot", "https://www.youtube.com/watch?v=GhRgvEG5jxQ"),
|
||||
// Members Quests
|
||||
new Link("Druidic Ritual", "https://www.youtube.com/watch?v=QIfU6HSmH4w"),
|
||||
new Link("Lost City", "https://www.youtube.com/watch?v=T-kQNUSjFZI"),
|
||||
new Link("Witch's House", "https://www.youtube.com/watch?v=TLsg7Wa-LUA"),
|
||||
new Link("Merlin's Crystal", "https://www.youtube.com/watch?v=ESX-qriNtCE"),
|
||||
new Link("Heroes' Quest", "https://www.youtube.com/watch?v=hK2N0WLKviE"),
|
||||
new Link("Scorpion Catcher", "https://www.youtube.com/watch?v=xpqdec7_ZWg"),
|
||||
new Link("Family Crest", "https://www.youtube.com/watch?v=0mk_Cgjr738"),
|
||||
new Link("Monk's Friend", "https://www.youtube.com/watch?v=avi4y4G3Hcw"),
|
||||
new Link("Temple of Ikov", "https://www.youtube.com/watch?v=5K7jDgr_4Z4"),
|
||||
new Link("Clock Tower", "https://www.youtube.com/watch?v=GUCkkQFzyDw"),
|
||||
new Link("Holy Grail", "https://www.youtube.com/watch?v=cgXoV1QlYco"),
|
||||
new Link("Tree Gnome Village", "https://www.youtube.com/watch?v=T6Su__yuyRI"),
|
||||
new Link("Fight Arena", "https://www.youtube.com/watch?v=4Nqjep2E5pw"),
|
||||
new Link("Hazeel Cult", "https://www.youtube.com/watch?v=2_fhFJW6cNY"),
|
||||
new Link("Sheep Herder", "https://www.youtube.com/watch?v=akC9FeYCG1Q"),
|
||||
new Link("Plague City", "https://www.youtube.com/watch?v=Hf2wQQZL5CU"),
|
||||
new Link("Waterfall Quest", "https://www.youtube.com/watch?v=xWBSnGkQTi4"),
|
||||
new Link("Jungle Potion", "https://www.youtube.com/watch?v=xqLKsFz08As"),
|
||||
new Link("The Grand Tree", "https://www.youtube.com/watch?v=N5e_Jus_E-Y"),
|
||||
new Link("Underground Pass", "https://www.youtube.com/watch?v=5klGJg1wY8k"),
|
||||
new Link("Observatory Quest", "https://www.youtube.com/watch?v=yxa9B6svv44"),
|
||||
new Link("Watchtower", "https://www.youtube.com/watch?v=Vb10GoYP7FE"),
|
||||
new Link("Dwarf Cannon", "https://www.youtube.com/watch?v=pROFg5jcCR0"),
|
||||
new Link("Murder Mystery", "https://www.youtube.com/watch?v=P1IDGCA2f9o"),
|
||||
new Link("The Dig Site", "https://www.youtube.com/watch?v=TOdcWV4MzuU"),
|
||||
new Link("Gertrude's Cat", "https://www.youtube.com/watch?v=g7S09wA8EAY"),
|
||||
new Link("Legends' Quest", "https://www.youtube.com/watch?v=Lid8enDEF_U"),
|
||||
new Link("Death Plateau", "https://www.youtube.com/watch?v=SIQFmTvnb6w"),
|
||||
new Link("Big Chompy Bird Hunting", "https://www.youtube.com/watch?v=s2fytMOHJXI"),
|
||||
new Link("Elemental Workshop I", "https://www.youtube.com/watch?v=tbZD2RDqvfQ"),
|
||||
new Link("Nature Spirit", "https://www.youtube.com/watch?v=Enf8vUWb5o0"),
|
||||
new Link("Priest in Peril", "https://www.youtube.com/watch?v=fyYri6wUQIU"),
|
||||
new Link("Regicide", "https://www.youtube.com/watch?v=KkWM-ok3C4Y"),
|
||||
new Link("Tai Bwo Wannai Trio", "https://www.youtube.com/watch?v=Mdair5mvZL0"),
|
||||
new Link("Troll Stronghold", "https://www.youtube.com/watch?v=zqmUs-f3AKA"),
|
||||
new Link("Horror from the Deep", "https://www.youtube.com/watch?v=9htK8kb6DR8"),
|
||||
new Link("Throne of Miscellania", "https://www.youtube.com/watch?v=fzGMnv2skBE"),
|
||||
new Link("Monkey Madness I", "https://www.youtube.com/watch?v=VnoRfeBnPFA"),
|
||||
new Link("Haunted Mine", "https://www.youtube.com/watch?v=cIc6loJHm9Q"),
|
||||
new Link("Troll Romance", "https://www.youtube.com/watch?v=j2zifZVu7Gc"),
|
||||
new Link("In Search of the Myreque", "https://www.youtube.com/watch?v=5nmYFHdAXAQ"),
|
||||
new Link("Creature of Fenkenstrain", "https://www.youtube.com/watch?v=swqUVIs7B7M"),
|
||||
new Link("Roving Elves", "https://www.youtube.com/watch?v=J3qf9DnT9cA"),
|
||||
new Link("One Small Favour", "https://www.youtube.com/watch?v=ix_0-W3e9ps"),
|
||||
new Link("Mountain Daughter", "https://www.youtube.com/watch?v=HETx_LX7aiY"),
|
||||
new Link("Between a Rock...", "https://www.youtube.com/watch?v=cB11I45EGgA"),
|
||||
new Link("The Golem", "https://www.youtube.com/watch?v=qpEHpiO6lLw"),
|
||||
new Link("Desert Treasure", "https://www.youtube.com/watch?v=BuIqulIsICo"),
|
||||
new Link("Icthlarin's Little Helper", "https://www.youtube.com/watch?v=wpNKm8_vUOM"),
|
||||
new Link("Tears of Guthix", "https://www.youtube.com/watch?v=EMonDNI0uPk"),
|
||||
new Link("The Lost Tribe", "https://www.youtube.com/watch?v=spZErjRnCdc"),
|
||||
new Link("The Giant Dwarf", "https://www.youtube.com/watch?v=Z7PsGpOYgxY"),
|
||||
new Link("Recruitment Drive", "https://www.youtube.com/watch?v=sOuzMpA_xtw"),
|
||||
new Link("Mourning's Ends Part I", "https://www.youtube.com/watch?v=vuzAdk-h3c0"),
|
||||
new Link("Garden of Tranquillity", "https://www.youtube.com/watch?v=7hbCzYnLCsQ"),
|
||||
new Link("A Tail of Two Cats", "https://www.youtube.com/watch?v=SgN9Yw_YqHk"),
|
||||
new Link("Wanted!", "https://www.youtube.com/watch?v=ZHZAKDCfXGs"),
|
||||
new Link("Mourning's Ends Part II", "https://www.youtube.com/watch?v=FK5sLogGbU8"),
|
||||
new Link("Rum Deal", "https://www.youtube.com/watch?v=I14CIu5x2S8"),
|
||||
new Link("Shadow of the Storm", "https://www.youtube.com/watch?v=5ZvWd3XCQjI"),
|
||||
new Link("Ratcatchers", "https://www.youtube.com/watch?v=s7G22fEuhTc"),
|
||||
new Link("Spirits of the Elid", "https://www.youtube.com/watch?v=A1zAX55hZC0"),
|
||||
new Link("Devious Minds", "https://www.youtube.com/watch?v=_UtlFmrWt1w"),
|
||||
new Link("Enakhra's Lament", "https://www.youtube.com/watch?v=Y3kEIPYVaVE"),
|
||||
new Link("Cabin Fever", "https://www.youtube.com/watch?v=k5DtxNXhOaw"),
|
||||
new Link("Fairytale I - Growing Pains", "https://www.youtube.com/watch?v=cfGI9qFOmsg"),
|
||||
new Link("Recipe for Disaster", "https://www.youtube.com/watch?v=hrAyyInJaTA"),
|
||||
new Link("In Aid of the Myreque", "https://www.youtube.com/watch?v=O2Ru2NmuTaA"),
|
||||
new Link("A Soul's Bane", "https://www.youtube.com/watch?v=dp8dp79qp6I"),
|
||||
new Link("Rag and Bone Man", "https://www.youtube.com/watch?v=3owXSeN56W8"),
|
||||
new Link("Swan Song", "https://www.youtube.com/watch?v=IpmERThXv2g"),
|
||||
new Link("Royal Trouble", "https://www.youtube.com/watch?v=bVWUlKzNXEg"),
|
||||
new Link("Death to the Dorgeshuun", "https://www.youtube.com/watch?v=2XJHuLhig98"),
|
||||
new Link("Fairytale II - Cure a Queen", "https://www.youtube.com/watch?v=P6KkRk4_e3U"),
|
||||
new Link("Lunar Diplomacy", "https://www.youtube.com/watch?v=vmeSKb7IBgQ"),
|
||||
new Link("The Eyes of Glouphrie", "https://www.youtube.com/watch?v=0YCPwmZcxKA"),
|
||||
new Link("Darkness of Hallowvale", "https://www.youtube.com/watch?v=QziKl99qdtU"),
|
||||
new Link("Elemental Workshop II", "https://www.youtube.com/watch?v=Bb4E7ecIgv0"),
|
||||
new Link("My Arm's Big Adventure", "https://www.youtube.com/watch?v=xa1KWOewgYA"),
|
||||
new Link("Enlightened Journey", "https://www.youtube.com/watch?v=XAPthC8d7k0"),
|
||||
new Link("Eagles' Peak", "https://www.youtube.com/watch?v=KDxIrrwXp7U"),
|
||||
new Link("Animal Magnetism", "https://www.youtube.com/watch?v=kUyjXA7TaFU"),
|
||||
new Link("Contact!", "https://www.youtube.com/watch?v=czn-yWABBWs"),
|
||||
new Link("Cold War", "https://www.youtube.com/watch?v=0m1KpP-qKWI"),
|
||||
new Link("The Fremennik Isles", "https://www.youtube.com/watch?v=EvxhiOWmraY"),
|
||||
new Link("The Great Brain Robbery", "https://www.youtube.com/watch?v=ImHFASuNUN8"),
|
||||
new Link("What Lies Below", "https://www.youtube.com/watch?v=f_9nVMGTtuo"),
|
||||
new Link("Olaf's Quest", "https://www.youtube.com/watch?v=mXV5bM1NFMM"),
|
||||
new Link("Dream Mentor", "https://www.youtube.com/watch?v=XDLUu0Kf0sE"),
|
||||
new Link("Grim Tales", "https://www.youtube.com/watch?v=dFB0Q6v8Apw"),
|
||||
new Link("King's Ransom", "https://www.youtube.com/watch?v=UJz9ZfF3uCY"),
|
||||
new Link("Shilo Village", "https://www.youtube.com/watch?v=bDvBi8FT-QI"),
|
||||
new Link("Biohazard", "https://www.youtube.com/watch?v=n9k87LwOGMk"),
|
||||
new Link("Tower of Life", "https://www.youtube.com/watch?v=KReMcWpeY3k"),
|
||||
new Link("Rag and Bone Man II", "https://www.youtube.com/watch?v=KGdHiDDUX_U"),
|
||||
new Link("Zogre Flesh Eaters", "https://www.youtube.com/watch?v=vzm4949kXP4"),
|
||||
new Link("Monkey Madness II", "https://www.youtube.com/watch?v=ykE5LbjABaI"),
|
||||
new Link("Client of Kourend", "https://www.youtube.com/watch?v=Y-KIHF-cL9w"),
|
||||
new Link("The Queen of Thieves", "https://www.youtube.com/watch?v=W94zFZVrHkQ"),
|
||||
new Link("Bone Voyage", "https://www.youtube.com/watch?v=-VTR4p8kPmI"),
|
||||
new Link("Dragon Slayer II", "https://www.youtube.com/watch?v=4BMb3Zwzk_U"),
|
||||
new Link("The Depths of Despair", "https://www.youtube.com/watch?v=CaVUk2eAsKs"),
|
||||
new Link("A Taste of Hope", "https://www.youtube.com/watch?v=VjdgEIizdSc"),
|
||||
new Link("Tale of the Righteous", "https://www.youtube.com/watch?v=99yiv0tPl58"),
|
||||
new Link("Making Friends with My Arm", "https://www.youtube.com/watch?v=DltzzhIsM_Q"),
|
||||
new Link("The Ascent of Arceuus", "https://www.youtube.com/watch?v=4VQnfrv6S18"),
|
||||
new Link("The Forsaken Tower", "https://www.youtube.com/watch?v=con0sXl5NBY"),
|
||||
new Link("Fishing Contest", "https://www.youtube.com/watch?v=XYSv37A_l5w"),
|
||||
new Link("Tribal Totem", "https://www.youtube.com/watch?v=XkUEIjr886M"),
|
||||
new Link("Sea Slug", "https://www.youtube.com/watch?v=oOZVfa5SkVQ"),
|
||||
new Link("The Tourist Trap", "https://www.youtube.com/watch?v=0bmSCCepMvo"),
|
||||
new Link("Eadgar's Ruse", "https://www.youtube.com/watch?v=aVQ3DjTElXg"),
|
||||
new Link("Shades of Mort'ton", "https://www.youtube.com/watch?v=eF05R8OMxgg"),
|
||||
new Link("The Fremennik Trials", "https://www.youtube.com/watch?v=YUIvEgcvl5c"),
|
||||
new Link("Ghosts Ahoy", "https://www.youtube.com/watch?v=aNBkLOywDfM"),
|
||||
new Link("The Feud", "https://www.youtube.com/watch?v=nlBSc9IUklA"),
|
||||
new Link("Forgettable Tale...", "https://www.youtube.com/watch?v=3HvFd6AxNU0"),
|
||||
new Link("Making History", "https://www.youtube.com/watch?v=bOTGi2zAuhs"),
|
||||
new Link("The Hand in the Sand", "https://www.youtube.com/watch?v=gdNLcZ-l1Lw"),
|
||||
new Link("The Slug Menace", "https://www.youtube.com/watch?v=BRQbdr3JEZ8"),
|
||||
new Link("Another Slice of H.A.M.", "https://www.youtube.com/watch?v=Yq3db7827Lk")
|
||||
};
|
||||
|
||||
private static class Link {
|
||||
|
||||
private String questName;
|
||||
private String url;
|
||||
|
||||
public Link(String questName, String url) {
|
||||
this.questName = questName;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getQuestName() {
|
||||
return questName;
|
||||
}
|
||||
|
||||
public void openURL() {
|
||||
LinkBrowser.browse(this.url);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static boolean openGuide(String questName) {
|
||||
for (Link link : QUEST_GUIDE_LINKS) {
|
||||
if (link.getQuestName().equals(questName)) {
|
||||
link.openURL();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void logQuestNotFoundError(String questName, ChatMessageManager chatMessageManager) {
|
||||
String chatMessage = new ChatMessageBuilder()
|
||||
.append(ChatColorType.HIGHLIGHT)
|
||||
.append("Could not find Slayermusiq1 guide for " + questName)
|
||||
.build();
|
||||
|
||||
chatMessageManager.queue(QueuedMessage.builder()
|
||||
.type(ChatMessageType.CONSOLE)
|
||||
.runeLiteFormattedMessage(chatMessage)
|
||||
.build());
|
||||
}
|
||||
|
||||
public static void tryOpenGuide(String questName, ChatMessageManager chatMessageManager) {
|
||||
boolean success = openGuide(questName);
|
||||
if (!success) {
|
||||
logQuestNotFoundError(questName, chatMessageManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Jeremy Berchtold <https://github.com/i-yam-jeremy>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
|
||||
// Based off RuneLite's Wiki Plugin
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* 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.slayermusiq;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import com.google.common.primitives.Ints;
|
||||
import java.awt.Dimension;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuAction;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.client.util.Text;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "<font color=\"green\">!Slayermusiq1 Guides</font>",
|
||||
description = "Adds a right-click option to go to Slayermusiq1's guides from the quest tab",
|
||||
tags = {"quest", "guide", "slayermusiq"}
|
||||
)
|
||||
@Slf4j
|
||||
public class SlayermusiqPlugin extends Plugin
|
||||
{
|
||||
|
||||
private static final int[] QUESTLIST_WIDGET_IDS = new int[]
|
||||
{
|
||||
WidgetInfo.QUESTLIST_FREE_CONTAINER.getId(),
|
||||
WidgetInfo.QUESTLIST_MEMBERS_CONTAINER.getId(),
|
||||
WidgetInfo.QUESTLIST_MINIQUEST_CONTAINER.getId(),
|
||||
};
|
||||
|
||||
private static final String MENUOP_SLAYERMUSIQ = "Slayermusiq";
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ChatMessageManager chatMessageManager;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
int widgetID = event.getActionParam1();
|
||||
if (Ints.contains(QUESTLIST_WIDGET_IDS, widgetID) && "Read Journal:".equals(event.getOption())) {
|
||||
MenuEntry[] menuEntries = client.getMenuEntries();
|
||||
|
||||
MenuEntry newMenuEntry = createSlayermusiqOptionMenuEntry(event);
|
||||
menuEntries = Arrays.copyOf(menuEntries, menuEntries.length + 1);
|
||||
menuEntries[menuEntries.length - 1] = newMenuEntry;
|
||||
|
||||
client.setMenuEntries(menuEntries);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
private void onMenuOptionClicked(MenuOptionClicked ev) {
|
||||
if (ev.getMenuAction() == MenuAction.RUNELITE && ev.getMenuOption().equals(MENUOP_SLAYERMUSIQ)) {
|
||||
ev.consume();
|
||||
String quest = Text.removeTags(ev.getMenuTarget());
|
||||
QuestGuideLinks.tryOpenGuide(quest, chatMessageManager);
|
||||
}
|
||||
}
|
||||
|
||||
private MenuEntry createSlayermusiqOptionMenuEntry(MenuEntryAdded event) {
|
||||
int widgetIndex = event.getActionParam0();
|
||||
int widgetID = event.getActionParam1();
|
||||
|
||||
MenuEntry menuEntry = new MenuEntry();
|
||||
menuEntry.setTarget(event.getTarget());
|
||||
menuEntry.setOption(MENUOP_SLAYERMUSIQ);
|
||||
menuEntry.setParam0(widgetIndex);
|
||||
menuEntry.setParam1(widgetID);
|
||||
menuEntry.setType(MenuAction.RUNELITE.getId());
|
||||
|
||||
return menuEntry;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package net.runelite.client.plugins.spellbookfixer;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("spellbookfixer")
|
||||
public interface SpellbookFixerConfig extends Config
|
||||
{
|
||||
@ConfigItem(position = 0, keyName = "shouldHideOthers", name = "Hide Others", description = "Toggle on to hide spells not useful for pking that cannot be filtered otherwise.")
|
||||
default boolean shouldHideOthers()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//ice blitz
|
||||
@ConfigItem(position = 1, keyName = "shouldModifyIceBlitz", name = "Ice Blitz", description = "Toggle on to enable Ice Blitz modifications.")
|
||||
default boolean shouldModifyIceBlitz() { return false; }
|
||||
@ConfigItem(position = 2, keyName = "getBlitzPositionX", name = "Ice Blitz Pos X", description = "Modifies the X-axis position of Ice Blitz.")
|
||||
default int getBlitzPositionX()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ConfigItem(position = 3, keyName = "getBlitzPositionY", name = "Ice Blitz Pos Y", description = "Modifies the Y-axis position of Ice Blitz.")
|
||||
default int getBlitzPositionY()
|
||||
{
|
||||
return 118;
|
||||
}
|
||||
@ConfigItem(position = 4, keyName = "getBlitzSize", name = "Ice Blitz Size", description = "Modifies the width of Ice Blitz.")
|
||||
default int getBlitzSize()
|
||||
{
|
||||
return 80;
|
||||
}
|
||||
|
||||
//ice barrage
|
||||
@ConfigItem(position = 5, keyName = "shouldModifyIceBarrage", name = "Ice Barrage", description = "Toggle on to enable Ice Barrage modifications.")
|
||||
default boolean shouldModifyIceBarrage() { return false; }
|
||||
@ConfigItem(position = 6, keyName = "getBarragePositionX", name = "Ice Barrage Pos X", description = "Modifies the X-axis position of Ice Barrage.")
|
||||
default int getBarragePositionX()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ConfigItem(position = 7, keyName = "getBarragePositionY", name = "Ice Barrage Pos X", description = "Modifies the X-axis position of Ice Barrage.")
|
||||
default int getBarragePositionY()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ConfigItem(position = 8, keyName = "getBarrageSize", name = "Ice Barrage Size", description = "Modifies the width position of Ice Barrage.")
|
||||
default int getBarrageSize()
|
||||
{
|
||||
return 80;
|
||||
}
|
||||
|
||||
//vengeance
|
||||
@ConfigItem(position = 9, keyName = "shouldModifyVengeance", name = "Vengeance", description = "Toggle on to enable Vengeance modifications.")
|
||||
default boolean shouldModifyVengeance() { return false; }
|
||||
@ConfigItem(position = 10, keyName = "getVengeancePositionX", name = "Vengeance Pos X", description = "Modifies the X-axis position of Vengeance.")
|
||||
default int getVengeancePositionX()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ConfigItem(position = 11, keyName = "getVengeancePositionY", name = "Vengeance Pos X", description = "Modifies the X-axis position of Vengeance.")
|
||||
default int getVengeancePositionY()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ConfigItem(position = 12, keyName = "getVengeanceSize", name = "Vengeance Size", description = "Modifies the width position of Vengeance.")
|
||||
default int getVengeanceSize()
|
||||
{
|
||||
return 80;
|
||||
}
|
||||
|
||||
//teleblock
|
||||
@ConfigItem(position = 13, keyName = "shouldModifyTeleBlock", name = "TeleBlock", description = "Toggle on to enable TeleBlock modifications.")
|
||||
default boolean shouldModifyTeleBlock() { return false; }
|
||||
@ConfigItem(position = 14, keyName = "getTeleBlockPositionX", name = "TeleBlock Pos X", description = "Modifies the X-axis position of TeleBlock.")
|
||||
default int getTeleBlockPositionX()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ConfigItem(position = 15, keyName = "getTeleBlockPositionY", name = "TeleBlock Pos X", description = "Modifies the X-axis position of TeleBlock.")
|
||||
default int getTeleBlockPositionY()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ConfigItem(position = 16, keyName = "getTeleBlockSize", name = "TeleBlock Size", description = "Modifies the width position of TeleBlock.")
|
||||
default int getTeleBlockSize()
|
||||
{
|
||||
return 80;
|
||||
}
|
||||
|
||||
//entangle
|
||||
@ConfigItem(position = 17, keyName = "shouldModifyEntangle", name = "Entangle", description = "Toggle on to enable Entangle modifications.")
|
||||
default boolean shouldModifyEntangle() { return false; }
|
||||
@ConfigItem(position = 18, keyName = "getEntanglePositionX", name = "Entangle Pos X", description = "Modifies the X-axis position of Entangle.")
|
||||
default int getEntanglePositionX()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ConfigItem(position = 19, keyName = "getEntanglePositionY", name = "Entangle Pos X", description = "Modifies the X-axis position of Entangle.")
|
||||
default int getEntanglePositionY()
|
||||
{
|
||||
return 118;
|
||||
}
|
||||
@ConfigItem(position = 20, keyName = "getEntangleSize", name = "Entangle Size", description = "Modifies the width position of Entangle.")
|
||||
default int getEntangleSize()
|
||||
{
|
||||
return 80;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package net.runelite.client.plugins.spellbookfixer;
|
||||
|
||||
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.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
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.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Spellbook Fixer",
|
||||
description = "Resize and filter spellbook for PKing",
|
||||
tags = {"resize", "spellbook", "magic", "spell", "pk", "book", "filter", "bogla"}
|
||||
)
|
||||
@Slf4j
|
||||
public class SpellbookFixerPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
SpellbookFixerConfig config;
|
||||
|
||||
@Provides
|
||||
SpellbookFixerConfig provideConfig(ConfigManager configManager) { return configManager.getConfig(SpellbookFixerConfig.class); }
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
adjustSpellbook();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
resetSpellbook();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() == GameState.LOGGED_IN)
|
||||
adjustSpellbook();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(WidgetLoaded event)
|
||||
{
|
||||
if (event.getGroupId() == WidgetID.SPELLBOOK_GROUP_ID)
|
||||
adjustSpellbook();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
adjustSpellbook();
|
||||
}
|
||||
|
||||
private void adjustSpellbook()
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (config.shouldModifyIceBarrage())
|
||||
modifySpell(WidgetInfo.SPELL_ICE_BARRAGE, config.getBarragePositionX(), config.getBarragePositionY(), config.getBarrageSize());
|
||||
|
||||
if (config.shouldModifyIceBlitz())
|
||||
modifySpell(WidgetInfo.SPELL_ICE_BLITZ, config.getBlitzPositionX(), config.getBlitzPositionY(), config.getBlitzSize());
|
||||
|
||||
if (config.shouldModifyVengeance())
|
||||
modifySpell(WidgetInfo.SPELL_VENGEANCE, config.getVengeancePositionX(), config.getVengeancePositionY(), config.getVengeanceSize());
|
||||
|
||||
if (config.shouldModifyTeleBlock())
|
||||
modifySpell(WidgetInfo.SPELL_TELE_BLOCK, config.getTeleBlockPositionX(), config.getTeleBlockPositionY(), config.getTeleBlockSize());
|
||||
|
||||
if (config.shouldModifyEntangle())
|
||||
modifySpell(WidgetInfo.SPELL_ENTANGLE, config.getEntanglePositionX(), config.getEntanglePositionY(), config.getEntangleSize());
|
||||
|
||||
setSpellHidden(WidgetInfo.SPELL_BLOOD_BLITZ, config.shouldHideOthers());
|
||||
setSpellHidden(WidgetInfo.SPELL_VENGEANCE_OTHER, config.shouldHideOthers());
|
||||
setSpellHidden(WidgetInfo.SPELL_BIND, config.shouldHideOthers());
|
||||
setSpellHidden(WidgetInfo.SPELL_SNARE, config.shouldHideOthers());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//swallow
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void resetSpellbook()
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
if (config.shouldModifyIceBarrage())
|
||||
modifySpell(WidgetInfo.SPELL_ICE_BARRAGE, config.getBarragePositionX(), config.getBarragePositionY(), 24);
|
||||
|
||||
if (config.shouldModifyIceBlitz())
|
||||
modifySpell(WidgetInfo.SPELL_ICE_BLITZ, config.getBlitzPositionX(), config.getBlitzPositionY(), 24);
|
||||
|
||||
if (config.shouldModifyVengeance())
|
||||
modifySpell(WidgetInfo.SPELL_VENGEANCE, config.getVengeancePositionX(), config.getVengeancePositionY(), 24);
|
||||
|
||||
if (config.shouldModifyTeleBlock())
|
||||
modifySpell(WidgetInfo.SPELL_TELE_BLOCK, config.getTeleBlockPositionX(), config.getTeleBlockPositionY(), 24);
|
||||
|
||||
if (config.shouldModifyEntangle())
|
||||
modifySpell(WidgetInfo.SPELL_ENTANGLE, config.getEntanglePositionX(), config.getEntanglePositionY(), 24);
|
||||
|
||||
setSpellHidden(WidgetInfo.SPELL_BLOOD_BLITZ, false);
|
||||
setSpellHidden(WidgetInfo.SPELL_VENGEANCE_OTHER, false);
|
||||
setSpellHidden(WidgetInfo.SPELL_BIND, false);
|
||||
setSpellHidden(WidgetInfo.SPELL_SNARE, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//swallow
|
||||
}
|
||||
}
|
||||
|
||||
private void modifySpell(WidgetInfo widgetInfo, int posX, int posY, int size)
|
||||
{
|
||||
Widget widget = client.getWidget(widgetInfo);
|
||||
|
||||
if (widget == null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
widget.setOriginalX(posX);
|
||||
widget.setOriginalY(posY);
|
||||
widget.setOriginalWidth(size);
|
||||
widget.setOriginalHeight(size);
|
||||
widget.revalidate();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//swallow
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setSpellHidden(WidgetInfo widgetInfo, boolean hidden)
|
||||
{
|
||||
Widget widget = client.getWidget(widgetInfo);
|
||||
|
||||
if (widget == null)
|
||||
return;
|
||||
|
||||
widget.setHidden(hidden);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user