This commit is contained in:
PKLite
2019-08-01 09:12:25 -04:00
22 changed files with 1760 additions and 438 deletions

View File

@@ -28,11 +28,12 @@ allprojects {
apply plugin: 'checkstyle'
group = 'net.runelite'
version = '1.5.30-SNAPSHOT'
version = '1.5.31-SNAPSHOT'
ext {
rsversion = 181
cacheversion = 165
plusVersion = '2.1.2.0'
gitCommit = localGitCommit
gitCommitShort = localGitCommitShort

View File

@@ -102,11 +102,12 @@ public class ProjectileID
public static final int HYDRA_LIGHTNING_2 = 1665;
public static final int DRAKE_BREATH = 1637;
public static final int HUNLEFF_MAGE_ATTACK = 1707;
public static final int HUNLEFF_CORRUPTED_MAGE_ATTACK = 1708;
public static final int HUNLEFF_RANGE_ATTACK = 1711;
public static final int HUNLEFF_CORRUPTED_RANGE_ATTACK = 1712;
public static final int HUNLLEF_MAGE_ATTACK = 1707;
public static final int HUNLLEF_CORRUPTED_MAGE_ATTACK = 1708;
public static final int HUNLLEF_RANGE_ATTACK = 1711;
public static final int HUNLLEF_CORRUPTED_RANGE_ATTACK = 1712;
public static final int HUNLLEF_PRAYER_ATTACK = 1713;
public static final int HUNLLEF_CORRUPTED_PRAYER_ATTACK = 1714;
public static final int ZALCANO_PROJECTILE = 1728;
}

View File

@@ -692,7 +692,12 @@ public enum Varbits
/**
* 1 is true, 0 is false.
*/
GAUNTLET_FINAL_ROOM_ENTERED(9177);
GAUNTLET_FINAL_ROOM_ENTERED(9177),
/**
* 1 is true, 0 is false.
*/
GAUNTLET_ENTERED(9178);
/**
* The raw varbit ID.

View File

@@ -1,3 +1,6 @@
import org.apache.tools.ant.filters.ReplaceTokens
import java.text.SimpleDateFormat
plugins {
id 'com.github.johnrengelman.shadow' version '5.1.0'
id 'java'
@@ -60,6 +63,23 @@ dependencies {
compileOnly group: 'net.runelite', name: 'orange-extensions', version: '1.0'
}
static def getDate() {
return new SimpleDateFormat("MM-dd-yyyy", Locale.forLanguageTag("en-US")).format(new Date())
}
def buildDate = getDate()
processResources {
from file("src/main/resources/runelite.plus.properties"), {
filter(ReplaceTokens, tokens: [
"project.version": project.version,
"rs.version": rsversion.toString(),
"runelite.plus.version": plusVersion.toString(),
"runelite.plus.builddate": buildDate.toString()
])
}
}
tasks.withType(AbstractArchiveTask) {
preserveFileTimestamps = false
reproducibleFileOrder = true

View File

@@ -24,18 +24,29 @@
*/
package net.runelite.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.config.RuneLitePlusConfig;
import net.runelite.http.api.RuneLiteAPI;
@Singleton
@Slf4j
public class RuneLiteProperties
{
private static final String DISCORD_APP_ID_PLUS = "560644885250572289";
private static final String RUNELITE_TITLE = "runelite.plus.title";
private static final String RUNELITE_VERSION = "runelite.version";
private static final String RUNELITE_PLUS_VERSION = "runelite.plus.version";
private static final String RUNELITE_PLUS_DATE = "runelite.plus.builddate";
private static final String RUNESCAPE_VERSION = "runescape.version";
private static final String DISCORD_APP_ID = "runelite.plus.discord.appid";
private static final String DISCORD_INVITE = "runelite.discord.invite";
private static final String GITHUB_LINK = "runelite.github.link";
private static final String WIKI_LINK = "runelite.wiki.link";
private static final String PATREON_LINK = "runelite.patreon.link";
private static final String LAUNCHER_VERSION_PROPERTY = "runelite.launcher.version";
private final Properties properties = new Properties();
@@ -45,6 +56,15 @@ public class RuneLiteProperties
public RuneLiteProperties(final RuneLitePlusConfig runeLiteConfig)
{
this.runeLitePlusConfig = runeLiteConfig;
try (InputStream in = getClass().getResourceAsStream("/runelite.plus.properties"))
{
properties.load(in);
}
catch (IOException ex)
{
log.warn("unable to load propertries", ex);
}
}
public RuneLiteProperties()
@@ -54,7 +74,7 @@ public class RuneLiteProperties
public String getTitle()
{
final StringBuilder sb = new StringBuilder("RuneLitePlus");
final StringBuilder sb = new StringBuilder(properties.getProperty(RUNELITE_TITLE));
String proxy;
if ((proxy = System.getProperty("socksProxyHost")) != null)
{
@@ -65,41 +85,46 @@ public class RuneLiteProperties
public String getVersion()
{
return RuneLiteAPI.getVersion();
return properties.getProperty(RUNELITE_VERSION);
}
public String getPlusVersion()
{
return RuneLite.PLUS_VERSION;
return properties.getProperty(RUNELITE_PLUS_VERSION);
}
public String getPlusDate()
{
return properties.getProperty(RUNELITE_PLUS_DATE);
}
public String getRunescapeVersion()
{
return "" + RuneLiteAPI.getRsVersion();
return properties.getProperty(RUNESCAPE_VERSION);
}
public String getDiscordAppId()
{
return DISCORD_APP_ID_PLUS;
return properties.getProperty(DISCORD_APP_ID);
}
public String getDiscordInvite()
{
return "https://discord.gg/HN5gf3m";
return properties.getProperty(DISCORD_INVITE);
}
public String getGithubLink()
{
return "https://github.com/runelite-extended/runelite";
return properties.getProperty(GITHUB_LINK);
}
public String getWikiLink()
{
return "https://github.com/runelite-extended/runelite/wiki";
return properties.getProperty(WIKI_LINK);
}
public String getPatreonLink()
{
return "https://www.patreon.com/RuneLitePlus";
return properties.getProperty(PATREON_LINK);
}
}

View File

@@ -37,13 +37,13 @@ import net.runelite.api.Client;
import net.runelite.api.DecorativeObject;
import net.runelite.api.GameObject;
import net.runelite.api.GroundObject;
import net.runelite.api.TileItemPile;
import net.runelite.api.MainBufferProvider;
import net.runelite.api.Model;
import net.runelite.api.NPC;
import net.runelite.api.NPCDefinition;
import net.runelite.api.Perspective;
import net.runelite.api.Player;
import net.runelite.api.TileItemPile;
import net.runelite.api.TileObject;
import net.runelite.api.WallObject;
import net.runelite.api.coords.LocalPoint;
@@ -968,7 +968,7 @@ public class ModelOutlineRenderer
}
}
private void drawOutline(GameObject gameObject, int outlineWidth, Color innerColor, Color outerColor)
public void drawOutline(GameObject gameObject, int outlineWidth, Color innerColor, Color outerColor)
{
LocalPoint lp = gameObject.getLocalLocation();
if (lp != null)
@@ -979,7 +979,7 @@ public class ModelOutlineRenderer
}
}
private void drawOutline(GroundObject groundObject, int outlineWidth, Color innerColor, Color outerColor)
public void drawOutline(GroundObject groundObject, int outlineWidth, Color innerColor, Color outerColor)
{
LocalPoint lp = groundObject.getLocalLocation();
if (lp != null)

View File

@@ -39,7 +39,7 @@ enum Boss
KREEARRA(NpcID.KREEARRA, 90, ChronoUnit.SECONDS, ItemID.PET_KREEARRA),
COMMANDER_ZILYANA(NpcID.COMMANDER_ZILYANA, 90, ChronoUnit.SECONDS, ItemID.PET_ZILYANA),
CALLISTO(NpcID.CALLISTO_6609, 30, ChronoUnit.SECONDS, ItemID.CALLISTO_CUB),
CHAOS_ELEMENTAL(NpcID.CHAOS_ELEMENTAL, 150, ChronoUnit.SECONDS, ItemID.PET_CHAOS_ELEMENTAL),
CHAOS_ELEMENTAL(NpcID.CHAOS_ELEMENTAL, 60, ChronoUnit.SECONDS, ItemID.PET_CHAOS_ELEMENTAL),
CHAOS_FANATIC(NpcID.CHAOS_FANATIC, 30, ChronoUnit.SECONDS, ItemID.ANCIENT_STAFF),
CRAZY_ARCHAEOLOGIST(NpcID.CRAZY_ARCHAEOLOGIST, 30, ChronoUnit.SECONDS, ItemID.FEDORA),
KING_BLACK_DRAGON(NpcID.KING_BLACK_DRAGON, 9, ChronoUnit.SECONDS, ItemID.PRINCE_BLACK_DRAGON),

View File

@@ -0,0 +1,272 @@
/*
* THIS SOFTWARE WRITTEN BY A KEYBOARD-WIELDING MONKEY BOI
* No rights reserved. Use, redistribute, and modify at your own discretion,
* and in accordance with Yagex and RuneLite guidelines.
* However, aforementioned monkey would prefer if you don't sell this plugin for profit.
* Good luck on your raids!
*/
package net.runelite.client.plugins.gauntlet;
import java.awt.Color;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Range;
import net.runelite.client.config.Stub;
@ConfigGroup("Gauntlet")
public interface GauntletConfig extends Config
{
@ConfigItem(
position = 0,
keyName = "resources",
name = "Resources",
description = ""
)
default Stub resources()
{
return new Stub();
}
@ConfigItem(
position = 1,
keyName = "highlightResources",
name = "Highlight Resources",
description = "Highlights all the resources in each room with a color.",
parent = "resources"
)
default boolean highlightResources()
{
return true;
}
@ConfigItem(
position = 2,
keyName = "highlightResourcesColor",
name = "Highlight Color",
description = "Highlights all the resources in each room with this color.",
parent = "resources",
hidden = true,
unhide = "highlightResources"
)
default Color highlightResourcesColor()
{
return Color.YELLOW;
}
@ConfigItem(
position = 3,
keyName = "highlightResourcesIcons",
name = "Highlight Resources with an Icon",
description = "Highlights all the icons in each room with an icon.",
parent = "resources",
hidden = true,
unhide = "highlightResources"
)
default boolean highlightResourcesIcons()
{
return true;
}
@Range(
min = 1,
max = 50
)
@ConfigItem(
position = 4,
keyName = "resourceIconSize",
name = "Resource Icon Size",
description = " change the size of resource icons.",
hidden = true,
unhide = "highlightResources",
parent = "resources"
)
default int resourceIconSize()
{
return 20;
}
@ConfigItem(
position = 5,
keyName = "boss",
name = "Boss",
description = ""
)
default Stub boss()
{
return new Stub();
}
@ConfigItem(
position = 6,
keyName = "countBossAttacks",
name = "Count Boss Attacks",
description = "Count the attacks until the boss switches their style.",
parent = "boss"
)
default boolean countBossAttacks()
{
return true;
}
@ConfigItem(
position = 7,
keyName = "countPlayerAttacks",
name = "Count Player Attacks",
description = "Count the player attacks until the boss switches their prayer.",
parent = "boss"
)
default boolean countPlayerAttacks()
{
return true;
}
@ConfigItem(
position = 8,
keyName = "highlightWidget",
name = "Highlight Correct Prayer",
description = "Highlights correct prayer in your prayer book.",
parent = "boss"
)
default boolean highlightWidget()
{
return true;
}
@ConfigItem(
position = 8,
keyName = "flashOnWrongAttack",
name = "Flash on Wrong Attack",
description = "This will flash your screen if you attack with the wrong stlye.",
parent = "boss"
)
default boolean flashOnWrongAttack()
{
return true;
}
@ConfigItem(
position = 9,
keyName = "uniquePrayerAudio",
name = "Unique Prayer Audio",
description = "Plays a unique sound whenever the boss is about to shut down your prayer.",
parent = "boss"
)
default boolean uniquePrayerAudio()
{
return true;
}
@ConfigItem(
position = 10,
keyName = "uniquePrayerVisual",
name = "Unique Prayer Visual",
description = "Prayer attacks will have a unique overlay visual.",
parent = "boss"
)
default boolean uniquePrayerVisual()
{
return true;
}
@ConfigItem(
position = 11,
keyName = "uniqueAttackVisual",
name = "Unique Magic & Range Visuals",
description = "Magic and Range attacks will have a unique overlay visual.",
parent = "boss"
)
default boolean uniqueAttackVisual()
{
return false;
}
@ConfigItem(
position = 12,
keyName = "overlayBoss",
name = "Overlay the Boss (Color)",
description = "Overlay the boss with an color denoting it's current attack style.",
parent = "boss"
)
default boolean overlayBoss()
{
return true;
}
@ConfigItem(
position = 13,
keyName = "overlayBossPrayer",
name = "Overlay the Boss (Icon)",
description = "Overlay the boss with an icon denoting it's current attack style.",
parent = "boss"
)
default boolean overlayBossPrayer()
{
return false;
}
@ConfigItem(
position = 14,
keyName = "overlayTornadoes",
name = "Show Tornado Decay",
description = "Display the amount of ticks left until the tornadoes decay.",
parent = "boss"
)
default boolean overlayTornadoes()
{
return true;
}
@Range(
min = 1,
max = 50
)
@ConfigItem(
position = 15,
keyName = "projectileIconSize",
name = "Boss Projectile Icon Size",
description = " change the size of Projectile icons.",
parent = "boss"
)
default int projectileIconSize()
{
return 20;
}
@ConfigItem(
position = 16,
keyName = "timer",
name = "Timer",
description = ""
)
default Stub timer()
{
return new Stub();
}
@ConfigItem(
position = 17,
keyName = "displayTimerWidget",
name = "Show Custom Timer (Widget)",
description = "Display a timer widget that tracks your gauntlet progress.",
parent = "timer"
)
default boolean displayTimerWidget()
{
return true;
}
@ConfigItem(
position = 18,
keyName = "displayTimerChat",
name = "Show Custom Timer (Chat)",
description = "Display a chat message that tracks your gauntlet progress.",
parent = "timer"
)
default boolean displayTimerChat()
{
return true;
}
}

View File

@@ -1,82 +0,0 @@
/*
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* 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.gauntlet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
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.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
import net.runelite.client.util.ColorUtil;
@Singleton
@Slf4j
public class GauntletCounter extends Overlay
{
private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150);
private final GauntletPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
GauntletCounter(final GauntletPlugin plugin)
{
this.plugin = plugin;
setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
panelComponent.getChildren().clear();
if (plugin.getHunllef() == null || !plugin.isInRoom())
{
return null;
}
panelComponent.getChildren().add(TitleComponent.builder()
.text("Hunllef")
.color(Color.pink)
.build());
Color color = plugin.getPlayerAttacks() == 1 ? Color.RED : Color.WHITE;
final String pHits = ColorUtil.prependColorTag(Integer.toString(plugin.getPlayerAttacks()), color);
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
tableComponent.addRow("Hunllef Hits: ", Integer.toString(plugin.getAttacks()));
tableComponent.addRow("Player Hits Left: ", pHits);
panelComponent.getChildren().add(tableComponent);
return panelComponent.render(graphics);
}
}

View File

@@ -1,133 +0,0 @@
/*
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* 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.gauntlet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.Prayer;
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.InfoBoxComponent;
import net.runelite.client.ui.overlay.components.PanelComponent;
@Singleton
@Slf4j
public class GauntletInfoBox extends Overlay
{
private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150);
private final Client client;
private final GauntletPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
private final SpriteManager spriteManager;
@Inject
GauntletInfoBox(final @Nullable Client client, final GauntletPlugin plugin, final SpriteManager spriteManager)
{
this.client = client;
this.plugin = plugin;
this.spriteManager = spriteManager;
setPosition(OverlayPosition.BOTTOM_RIGHT);
setPriority(OverlayPriority.HIGH);
}
@Override
public Dimension render(Graphics2D graphics)
{
panelComponent.getChildren().clear();
if (plugin.getHunllef() == null || !plugin.isInRoom())
{
return null;
}
Prayer prayer = plugin.getNextPrayer();
if (prayer == null)
{
return null;
}
InfoBoxComponent prayComponent = new InfoBoxComponent();
BufferedImage prayImg = scaleImg(getPrayerImage(prayer));
prayComponent.setImage(prayImg);
prayComponent.setColor(Color.WHITE);
prayComponent.setBackgroundColor(client.isPrayerActive(prayer)
? ComponentConstants.STANDARD_BACKGROUND_COLOR
: NOT_ACTIVATED_BACKGROUND_COLOR);
prayComponent.setPreferredSize(new Dimension(40, 40));
panelComponent.getChildren().add(prayComponent);
panelComponent.setPreferredSize(new Dimension(40, 40));
panelComponent.setBorder(new Rectangle(0, 0, 0, 0));
return panelComponent.render(graphics);
}
private BufferedImage getPrayerImage(Prayer prayer)
{
switch (prayer)
{
case PROTECT_FROM_MAGIC:
return spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0);
case PROTECT_FROM_MELEE:
return spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MELEE, 0);
case PROTECT_FROM_MISSILES:
return spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
}
return null;
}
private static BufferedImage scaleImg(final BufferedImage img)
{
if (img == null)
{
return null;
}
final double width = img.getWidth(null);
final double height = img.getHeight(null);
final double size = 36; // Limit size to 2 as that is minimum size not causing breakage
final double scalex = size / width;
final double scaley = size / height;
final double scale = Math.min(scalex, scaley);
final int newWidth = (int) (width * scale);
final int newHeight = (int) (height * scale);
final BufferedImage scaledImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_ARGB);
final Graphics g = scaledImage.createGraphics();
g.drawImage(img, 0, 0, newWidth, newHeight, null);
g.dispose();
return scaledImage;
}
}

View File

@@ -0,0 +1,416 @@
/*
* Copyright (c) 2019, kThisIsCvpv <https://github.com/kThisIsCvpv>
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* 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.gauntlet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import net.runelite.api.Client;
import net.runelite.api.Model;
import net.runelite.api.NPC;
import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.Projectile;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.model.Jarvis;
import net.runelite.api.model.Vertex;
import net.runelite.client.graphics.ModelOutlineRenderer;
import net.runelite.client.ui.overlay.Overlay;
import net.runelite.client.ui.overlay.OverlayLayer;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.OverlayUtil;
import static net.runelite.client.util.ImageUtil.resizeImage;
public class GauntletOverlay extends Overlay
{
private static final Color FLASH_COLOR = new Color(255, 0, 0, 70);
private static final int MAX_DISTANCE = 2400;
private final Client client;
private final GauntletPlugin plugin;
private final ModelOutlineRenderer outlineRenderer;
private int timeout;
@Inject
private GauntletOverlay(Client client, GauntletPlugin plugin, ModelOutlineRenderer outlineRenderer)
{
this.client = client;
this.plugin = plugin;
this.outlineRenderer = outlineRenderer;
setPosition(OverlayPosition.DYNAMIC);
setPriority(OverlayPriority.HIGH);
setLayer(OverlayLayer.ALWAYS_ON_TOP);
}
@Override
public Dimension render(Graphics2D graphics)
{
// Save resources. There's nothing to render if the user is not in a raid.
if (!plugin.startedGauntlet())
{
return null;
}
if (plugin.fightingBoss())
{
// This section handles the visuals when the player is in the boss room.
// This section handles the projectile overlays.
Set<Missiles> projectiles = plugin.getProjectiles();
projectiles.forEach(projectile ->
{
BufferedImage icon = resizeImage(projectile.getImage(), plugin.getProjectileIconSize(), plugin.getProjectileIconSize());
Color color = projectile.getColor();
Polygon polygon = boundProjectile(projectile.getProjectile());
if (polygon == null)
{
int x = (int) projectile.getProjectile().getX();
int y = (int) projectile.getProjectile().getY();
LocalPoint point = new LocalPoint(x, y);
Point loc = Perspective.getCanvasImageLocation(client, point, icon, -(int) projectile.getProjectile().getZ());
if (loc == null)
{
return;
}
if (plugin.isUniqueAttackVisual())
{
graphics.drawImage(icon, loc.getX(), loc.getY(), null);
}
}
else
{
graphics.setColor(color);
graphics.draw(polygon);
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), 50));
graphics.fill(polygon);
if (plugin.isUniqueAttackVisual())
{
Rectangle bounds = polygon.getBounds();
int x = (int) bounds.getCenterX() - (icon.getWidth() / 2);
int y = (int) bounds.getCenterY() - (icon.getHeight() / 2);
graphics.drawImage(icon, x, y, null);
}
}
});
projectiles.removeIf(proj -> proj.getProjectile().getRemainingCycles() <= 0);
plugin.getTornadoes().forEach(tornado ->
{
if (plugin.isOverlayTornadoes())
{
if (tornado.getTimeLeft() <= 0)
{
return;
}
final String textOverlay = Integer.toString(tornado.getTimeLeft());
final Point textLoc = Perspective.getCanvasTextLocation(client, graphics, tornado.getNpc().getLocalLocation(), textOverlay, 0);
final LocalPoint lp = LocalPoint.fromWorld(client, tornado.getNpc().getWorldLocation());
if (lp == null)
{
return;
}
final Polygon tilePoly = Perspective.getCanvasTilePoly(client, lp);
OverlayUtil.renderPolygon(graphics, tilePoly, Color.YELLOW);
if (textLoc == null)
{
return;
}
Font oldFont = graphics.getFont();
graphics.setFont(new Font("Arial", Font.BOLD, 20));
Point pointShadow = new Point(textLoc.getX() + 1, textLoc.getY() + 1);
OverlayUtil.renderTextLocation(graphics, pointShadow, textOverlay, Color.BLACK);
OverlayUtil.renderTextLocation(graphics, textLoc, textOverlay, Color.YELLOW);
graphics.setFont(oldFont);
}
});
if (plugin.getHunllef() != null)
{
final Hunllef hunllef = plugin.getHunllef();
final Hunllef.BossAttackPhase phase = hunllef.getCurrentPhase();
final NPC boss = hunllef.getNpc();
final LocalPoint point = boss.getLocalLocation();
if (plugin.isFlash())
{
final Color flash = graphics.getColor();
graphics.setColor(FLASH_COLOR);
graphics.fill(new Rectangle(client.getCanvas().getSize()));
graphics.setColor(flash);
timeout++;
if (timeout >= 15)
{
timeout = 0;
plugin.setFlash(false);
}
}
if (plugin.isOverlayBoss())
{
Polygon polygon = boss.getConvexHull();
if (polygon == null)
{
return null;
}
if (phase.getPrayer() != null && !client.isPrayerActive(phase.getPrayer()))
{
Color color = phase.getColor();
outlineRenderer.drawOutline(boss, 12, color, new Color(0, 0, 0, 0));
}
}
if (plugin.isOverlayBossPrayer())
{
BufferedImage attackIcon = null;
switch (phase)
{
case MAGIC:
attackIcon = resizeImage(hunllef.getMage(), plugin.getProjectileIconSize(), plugin.getProjectileIconSize());
break;
case RANGE:
attackIcon = resizeImage(hunllef.getRange(), plugin.getProjectileIconSize(), plugin.getProjectileIconSize());
break;
default:
break;
}
if (attackIcon == null)
{
return null;
}
Point imageLoc = Perspective.getCanvasImageLocation(client, point, attackIcon, boss.getLogicalHeight() / 2);
if (imageLoc == null)
{
return null;
}
graphics.drawImage(attackIcon, imageLoc.getX(), imageLoc.getY(), null);
}
if (plugin.isHighlightWidget())
{
if (phase.getPrayer() == null)
{
return null;
}
final Rectangle bounds = OverlayUtil.renderPrayerOverlay(graphics, client, phase.getPrayer(), phase.getColor());
if (bounds != null)
{
final Color color = hunllef.getTicksUntilAttack() == 1 ? Color.WHITE : phase.getColor();
renderTextLocation(graphics, Integer.toString(hunllef.getTicksUntilAttack()), 16, Font.BOLD, color, centerPoint(bounds), false);
}
}
// This section handles any text overlays.
String textOverlay = "";
// Handles the counter for the boss.
if (plugin.isCountBossAttacks())
{
textOverlay = Integer.toString(hunllef.getBossAttacks());
}
// Handles the counter for the player.
if (plugin.isCountPlayerAttacks())
{
if (textOverlay.length() > 0)
{
textOverlay += " | ";
}
textOverlay += Integer.toString(hunllef.getPlayerAttacks());
}
// Handles drawing the text onto the boss.
if (textOverlay.length() > 0)
{
Point textLoc = Perspective.getCanvasTextLocation(client, graphics, point, textOverlay, boss.getLogicalHeight() / 2);
if (textLoc == null)
{
return null;
}
textLoc = new Point(textLoc.getX(), textLoc.getY() + 35);
Font oldFont = graphics.getFont();
graphics.setFont(new Font("Arial", Font.BOLD, 20));
Point pointShadow = new Point(textLoc.getX() + 1, textLoc.getY() + 1);
OverlayUtil.renderTextLocation(graphics, pointShadow, textOverlay, Color.BLACK);
OverlayUtil.renderTextLocation(graphics, textLoc, textOverlay, phase.getColor());
graphics.setFont(oldFont);
}
}
}
else
{
// This section overlays all resources.
final LocalPoint playerLocation = client.getLocalPlayer().getLocalLocation();
final Set<Resources> resources = plugin.getResources();
resources.forEach(object ->
{
if (object.getGameObject().getLocalLocation().distanceTo(playerLocation) < MAX_DISTANCE)
{
// Don't use Convex Hull click box. As the room start to fill up, your FPS will dip.
Polygon polygon = object.getGameObject().getConvexHull();
if (polygon == null)
{
return;
}
// This section will highlight the resource with color.
if (plugin.isHighlightResources())
{
outlineRenderer.drawOutline(object.getGameObject(), 2, plugin.getHighlightResourcesColor());
}
// This section will overlay the resource with an icon.
if (plugin.isHighlightResourcesIcons())
{
BufferedImage icon = resizeImage(object.getImage(), plugin.getResourceIconSize(), plugin.getResourceIconSize());
if (icon != null)
{
Rectangle bounds = polygon.getBounds();
int startX = (int) bounds.getCenterX() - (icon.getWidth() / 2);
int startY = (int) bounds.getCenterY() - (icon.getHeight() / 2);
graphics.drawImage(icon, startX, startY, null);
}
}
}
});
}
return null;
}
private Polygon boundProjectile(Projectile proj)
{
if (proj == null || proj.getModel() == null)
{
return null;
}
Model model = proj.getModel();
LocalPoint point = new LocalPoint((int) proj.getX(), (int) proj.getY());
int tileHeight = Perspective.getTileHeight(client, point, client.getPlane());
double angle = Math.atan(proj.getVelocityY() / proj.getVelocityX());
angle = Math.toDegrees(angle) + (proj.getVelocityX() < 0 ? 180 : 0);
angle = angle < 0 ? angle + 360 : angle;
angle = 360 - angle - 90;
double ori = angle * (512d / 90d);
ori = ori < 0 ? ori + 2048 : ori;
int orientation = (int) Math.round(ori);
List<Vertex> vertices = model.getVertices();
for (int i = 0; i < vertices.size(); ++i)
{
vertices.set(i, vertices.get(i).rotate(orientation));
}
List<Point> list = new ArrayList<>();
for (Vertex vertex : vertices)
{
final Point localToCanvas = Perspective.localToCanvas(client, point.getX() - vertex.getX(), point.getY() - vertex.getZ(), tileHeight + vertex.getY() + (int) proj.getZ());
if (localToCanvas != null)
{
list.add(localToCanvas);
}
}
final List<Point> convexHull = Jarvis.convexHull(list);
if (convexHull == null)
{
return null;
}
final Polygon polygon = new Polygon();
for (final Point hullPoint : convexHull)
{
polygon.addPoint(hullPoint.getX(), hullPoint.getY());
}
return polygon;
}
private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, Point canvasPoint, boolean shadows)
{
graphics.setFont(new Font("Arial", fontStyle, fontSize));
if (canvasPoint != null)
{
final Point canvasCenterPoint = new Point(
canvasPoint.getX() - 3,
canvasPoint.getY() + 6);
final Point canvasCenterPoint_shadow = new Point(
canvasPoint.getX() - 2,
canvasPoint.getY() + 7);
if (shadows)
{
OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK);
}
OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor);
}
}
private Point centerPoint(Rectangle rect)
{
int x = (int) (rect.getX() + rect.getWidth() / 2);
int y = (int) (rect.getY() + rect.getHeight() / 2);
return new Point(x, y);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, xperiaclash <https://github.com/xperiaclash>
* Copyright (c) 2019, kThisIsCvpv <https://github.com/kThisIsCvpv>
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* All rights reserved.
*
@@ -22,244 +22,430 @@
* (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.gauntlet;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Provides;
import java.awt.Color;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.AnimationID;
import net.runelite.api.Actor;
import net.runelite.api.Client;
import net.runelite.api.GameObject;
import net.runelite.api.GameState;
import net.runelite.api.HeadIcon;
import net.runelite.api.NPC;
import net.runelite.api.NPCDefinition;
import net.runelite.api.Prayer;
import net.runelite.api.NpcID;
import net.runelite.api.ObjectID;
import net.runelite.api.Player;
import net.runelite.api.Projectile;
import net.runelite.api.ProjectileID;
import net.runelite.api.SoundEffectID;
import net.runelite.api.Varbits;
import net.runelite.api.events.AnimationChanged;
import net.runelite.api.events.ConfigChanged;
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.NpcDespawned;
import net.runelite.api.events.NpcSpawned;
import net.runelite.api.events.ProjectileSpawned;
import net.runelite.api.events.VarbitChanged;
import net.runelite.client.callback.ClientThread;
import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.EventBus;
import net.runelite.client.game.SkillIconManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.plugins.PluginType;
import static net.runelite.client.plugins.gauntlet.Hunllef.BossAttack.LIGHTNING;
import static net.runelite.client.plugins.gauntlet.Hunllef.BossAttack.MAGIC;
import static net.runelite.client.plugins.gauntlet.Hunllef.BossAttack.PRAYER;
import static net.runelite.client.plugins.gauntlet.Hunllef.BossAttack.RANGE;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Gauntlet Boss Helper",
description = "Prayer Overlay For The Gauntlet Boss",
tags = {"gauntlet"},
type = PluginType.PVM,
enabledByDefault = false
name = "Gauntlet",
description = "All-in-one plugin for the Gauntlet.",
tags = {"Gauntlet"},
enabledByDefault = false,
type = PluginType.PVM
)
@Singleton
@Slf4j
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
public class GauntletPlugin extends Plugin
{
private static final Set<Integer> PLAYER_ANIMATIONS = ImmutableSet.of(426, 1167, 422, 423, 440, 428);
private static final Set<Integer> HUNLEFF_ANIMATIONS = ImmutableSet.of(AnimationID.HUNLEFF_ATTACK, AnimationID.HUNLEFF_TORNADO);
private static final Set<Integer> HUNLEFF_MAGE_PROJECTILES = ImmutableSet.of(ProjectileID.HUNLEFF_MAGE_ATTACK, ProjectileID.HUNLEFF_CORRUPTED_MAGE_ATTACK);
private static final Set<Integer> HUNLEFF_RANGE_PROJECTILES = ImmutableSet.of(ProjectileID.HUNLEFF_RANGE_ATTACK, ProjectileID.HUNLEFF_CORRUPTED_RANGE_ATTACK);
private static final int BOW_ATTACK = 426;
private static final int STAFF_ATTACK = 1167;
private static final int LIGHTNING_ANIMATION = 8418;
private static final Set<Integer> TORNADO_NPC_IDS = ImmutableSet.of(9025, 9039);
private static final Set<Integer> MELEE_ANIMATIONS = ImmutableSet.of(395, 401, 400, 401, 386, 390, 422, 423, 401, 428, 440);
private static final Set<Integer> PLAYER_ANIMATIONS = ImmutableSet.of(395, 401, 400, 401, 386, 390, 422, 423, 401, 428, 440, 426, 1167);
private static final Set<Integer> HUNLLEF_MAGE_PROJECTILES = ImmutableSet.of(ProjectileID.HUNLLEF_MAGE_ATTACK, ProjectileID.HUNLLEF_CORRUPTED_MAGE_ATTACK);
private static final Set<Integer> HUNLLEF_RANGE_PROJECTILES = ImmutableSet.of(ProjectileID.HUNLLEF_RANGE_ATTACK, ProjectileID.HUNLLEF_CORRUPTED_RANGE_ATTACK);
private static final Set<Integer> HUNLLEF_PRAYER_PROJECTILES = ImmutableSet.of(ProjectileID.HUNLLEF_PRAYER_ATTACK, ProjectileID.HUNLLEF_CORRUPTED_PRAYER_ATTACK);
private static final Set<Integer> HUNLLEF_PROJECTILES = ImmutableSet.of(ProjectileID.HUNLLEF_PRAYER_ATTACK, ProjectileID.HUNLLEF_CORRUPTED_PRAYER_ATTACK,
ProjectileID.HUNLLEF_RANGE_ATTACK, ProjectileID.HUNLLEF_CORRUPTED_RANGE_ATTACK, ProjectileID.HUNLLEF_MAGE_ATTACK, ProjectileID.HUNLLEF_CORRUPTED_MAGE_ATTACK
);
private static final Set<Integer> HUNLLEF_NPC_IDS = ImmutableSet.of(NpcID.CRYSTALLINE_HUNLLEF, NpcID.CRYSTALLINE_HUNLLEF_9022, NpcID.CRYSTALLINE_HUNLLEF_9023,
NpcID.CRYSTALLINE_HUNLLEF_9024, NpcID.CORRUPTED_HUNLLEF, NpcID.CORRUPTED_HUNLLEF_9036, NpcID.CORRUPTED_HUNLLEF_9037, NpcID.CORRUPTED_HUNLLEF_9038
);
private static final Set<Integer> RESOURCES = ImmutableSet.of(ObjectID.CRYSTAL_DEPOSIT, ObjectID.CORRUPT_DEPOSIT, ObjectID.PHREN_ROOTS,
ObjectID.PHREN_ROOTS_36066, ObjectID.FISHING_SPOT_36068, ObjectID.FISHING_SPOT_35971, ObjectID.GRYM_ROOT, ObjectID.GRYM_ROOT_36070,
ObjectID.LINUM_TIRINUM, ObjectID.LINUM_TIRINUM_36072
);
@Inject
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private Client client;
@Inject
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private EventBus eventBus;
private ClientThread clientThread;
@Inject
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private OverlayManager overlayManager;
@Inject
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private GauntletInfoBox GauntletInfoBox;
private GauntletOverlay overlay;
@Inject
@Getter(AccessLevel.NONE)
@Setter(AccessLevel.NONE)
private GauntletCounter GauntletCounter;
private int attacks = 0;
private int playerAttacks = 0;
private Prayer nextPrayer;
private NPC hunllef;
private boolean firstHitDetected;
private HeadIcon currentPrayer;
private GauntletConfig config;
@Inject
@Getter(AccessLevel.NONE)
private EventBus eventBus;
@Inject
@Getter(AccessLevel.NONE)
private GauntletTimer timer;
@Inject
@Getter(AccessLevel.NONE)
private SkillIconManager skillIconManager;
@Setter(AccessLevel.PACKAGE)
private Hunllef hunllef;
private final Set<Resources> resources = new HashSet<>();
private final Set<Missiles> projectiles = new HashSet<>();
private final Map<String, Integer> items = new HashMap<>();
private Set<Tornado> tornadoes = new HashSet<>();
private boolean completeStartup = false;
private boolean countBossAttacks;
private boolean countPlayerAttacks;
private boolean displayTimerChat;
private boolean highlightResources;
private boolean highlightResourcesIcons;
private boolean highlightWidget;
private boolean overlayBoss;
private boolean overlayBossPrayer;
private boolean overlayTornadoes;
@Setter(AccessLevel.PACKAGE)
private boolean flash;
private boolean flashOnWrongAttack;
private Color highlightResourcesColor;
private boolean displayTimerWidget;
private boolean timerVisible = true;
private boolean uniqueAttackVisual;
private boolean uniquePrayerAudio;
private boolean uniquePrayerVisual;
private int resourceIconSize;
private int projectileIconSize;
@Override
protected void startUp() throws Exception
@Provides
GauntletConfig getConfig(ConfigManager configManager)
{
addSubscriptions();
overlayManager.add(GauntletInfoBox);
overlayManager.add(GauntletCounter);
reset();
return configManager.getConfig(GauntletConfig.class);
}
@Override
protected void shutDown() throws Exception
protected void startUp()
{
addSubscriptions();
updateConfig();
timerVisible = this.displayTimerWidget;
timer.resetStates();
if (timerVisible)
{
overlayManager.add(timer);
}
overlayManager.add(overlay);
if (client.getGameState() != GameState.STARTING && client.getGameState() != GameState.UNKNOWN)
{
completeStartup = false;
clientThread.invoke(() -> {
timer.initStates();
completeStartup = true;
});
}
else
{
completeStartup = true;
}
}
@Override
protected void shutDown()
{
eventBus.unregister(this);
overlayManager.remove(GauntletInfoBox);
overlayManager.remove(GauntletCounter);
reset();
timer.resetStates();
if (timerVisible)
{
overlayManager.remove(timer);
timerVisible = false;
}
overlayManager.remove(overlay);
resources.clear();
projectiles.clear();
tornadoes.clear();
setHunllef(null);
}
private void addSubscriptions()
{
eventBus.subscribe(AnimationChanged.class, this, this::onAnimationChanged);
eventBus.subscribe(NpcSpawned.class, this, this::onNpcSpawned);
eventBus.subscribe(NpcDespawned.class, this, this::onNpcDespawned);
eventBus.subscribe(ProjectileSpawned.class, this, this::onProjectileSpawned);
eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
eventBus.subscribe(GameObjectDespawned.class, this, this::onGameObjectDespawned);
eventBus.subscribe(GameObjectSpawned.class, this, this::onGameObjectSpawned);
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
eventBus.subscribe(GameTick.class, this, this::onGameTick);
eventBus.subscribe(NpcDespawned.class, this, this::onNpcDespawned);
eventBus.subscribe(NpcSpawned.class, this, this::onNpcSpawned);
eventBus.subscribe(ProjectileSpawned.class, this, this::onProjectileSpawned);
eventBus.subscribe(VarbitChanged.class, this, this::onVarbitChanged);
}
private void onAnimationChanged(AnimationChanged event)
{
if (getHunllef() == null || !isInRoom())
final Actor actor = event.getActor();
// This section handles the player counter.
if (actor instanceof Player && fightingBoss())
{
final Player player = (Player) actor;
final int anim = player.getAnimation();
if (!player.getName().equals(client.getLocalPlayer().getName()) || anim == -1 || !PLAYER_ANIMATIONS.contains(anim))
{
return;
}
NPCDefinition comp = hunllef.getNpc().getDefinition();
if (comp == null || comp.getOverheadIcon() == null)
{
return;
}
final HeadIcon prayer = comp.getOverheadIcon();
switch (prayer)
{
case MELEE:
if (MELEE_ANIMATIONS.contains(anim))
{
setFlash(true);
return;
}
hunllef.updatePlayerAttack();
break;
case RANGED:
if (BOW_ATTACK == anim)
{
setFlash(true);
return;
}
hunllef.updatePlayerAttack();
break;
case MAGIC:
if (STAFF_ATTACK == anim)
{
setFlash(true);
return;
}
hunllef.updatePlayerAttack();
break;
}
}
// This section handles the boss attack counter if they perform a lightning attack.
if (actor instanceof NPC)
{
final NPC npc = (NPC) actor;
if (npc.getAnimation() == LIGHTNING_ANIMATION)
{
hunllef.updateAttack(LIGHTNING);
}
}
}
private void onConfigChanged(ConfigChanged event)
{
if (!event.getGroup().equals("Gauntlet"))
{
return;
}
final int anim = event.getActor().getAnimation();
updateConfig();
if (HUNLEFF_ANIMATIONS.contains(anim))
if (event.getKey().equals("displayTimerWidget"))
{
setAttacks(getAttacks() + 1);
if (getAttacks() == 4)
if (this.displayTimerWidget && !timerVisible)
{
if (getNextPrayer() == Prayer.PROTECT_FROM_MISSILES)
{
log.debug("Attacks are: {}, switching to prot mage", getAttacks());
setNextPrayer(Prayer.PROTECT_FROM_MAGIC);
}
else if (getNextPrayer() == Prayer.PROTECT_FROM_MAGIC)
{
log.debug("Attacks are: {}, switching to prot missiles", getAttacks());
setNextPrayer(Prayer.PROTECT_FROM_MISSILES);
}
setAttacks(0);
overlayManager.add(timer);
timerVisible = true;
}
else if (!this.displayTimerWidget && timerVisible)
{
overlayManager.remove(timer);
timerVisible = false;
}
}
else if (PLAYER_ANIMATIONS.contains(anim))
}
private void onGameObjectDespawned(GameObjectDespawned event)
{
final GameObject obj = event.getGameObject();
if (RESOURCES.contains(obj.getId()))
{
setPlayerAttacks(getPlayerAttacks() - 1);
if (getPlayerAttacks() == 0)
{
setPlayerAttacks(6);
}
resources.removeIf(object -> object.getGameObject() == obj);
}
}
private void onGameObjectSpawned(GameObjectSpawned event)
{
final GameObject obj = event.getGameObject();
if (RESOURCES.contains(obj.getId()))
{
resources.add(new Resources(obj, event.getTile(), skillIconManager));
}
}
private void onGameStateChanged(GameStateChanged event)
{
if (event.getGameState() == GameState.LOADING)
{
resources.clear();
}
}
private void onGameTick(GameTick event)
{
if (getHunllef() == null || !isInRoom())
// This handles the timer based on player health.
if (this.completeStartup)
{
return;
timer.checkStates(false);
}
HeadIcon overhead = getOverheadIcon(getHunllef());
if (overhead == null)
if (!tornadoes.isEmpty())
{
return;
tornadoes.forEach(Tornado::updateTimeLeft);
}
switch (overhead)
if (hunllef != null)
{
case MELEE:
case MAGIC:
case RANGED:
if (currentPrayer == overhead)
{
return;
}
currentPrayer = overhead;
setPlayerAttacks(6);
break;
if (hunllef.getTicksUntilAttack() > 0)
{
hunllef.setTicksUntilAttack(hunllef.getTicksUntilAttack() - 1);
}
}
}
private void onNpcDespawned(NpcDespawned event)
{
final NPC npc = event.getNpc();
if (npc.getName() == null || !npc.getName().toLowerCase().contains("hunllef"))
if (HUNLLEF_NPC_IDS.contains(npc.getId()))
{
return;
setHunllef(null);
}
else if (TORNADO_NPC_IDS.contains(npc.getId()))
{
tornadoes.removeIf(tornado -> tornado.getNpc() == npc);
}
reset();
}
private void onNpcSpawned(NpcSpawned event)
{
final NPC npc = event.getNpc();
if (npc.getName() == null || !npc.getName().toLowerCase().contains("hunllef"))
if (HUNLLEF_NPC_IDS.contains(npc.getId()))
{
return;
setHunllef(new Hunllef(npc, skillIconManager));
}
else if (TORNADO_NPC_IDS.contains(npc.getId()))
{
tornadoes.add(new Tornado(npc));
}
setPlayerAttacks(6);
setAttacks(0);
setHunllef(npc);
}
private void onProjectileSpawned(ProjectileSpawned event)
{
if (getHunllef() == null || !isInRoom() || isFirstHitDetected())
if (hunllef == null)
{
return;
}
final int projectileID = event.getProjectile().getId();
final Projectile proj = event.getProjectile();
if (HUNLEFF_MAGE_PROJECTILES.contains(projectileID))
if (HUNLLEF_PROJECTILES.contains(proj.getId()))
{
setNextPrayer(Prayer.PROTECT_FROM_MAGIC);
setFirstHitDetected(true);
}
else if (HUNLEFF_RANGE_PROJECTILES.contains(projectileID))
{
setNextPrayer(Prayer.PROTECT_FROM_MISSILES);
setFirstHitDetected(true);
projectiles.add(new Missiles(proj, skillIconManager));
if (HUNLLEF_MAGE_PROJECTILES.contains(proj.getId()))
{
hunllef.updateAttack(MAGIC);
}
else if (HUNLLEF_PRAYER_PROJECTILES.contains(proj.getId()))
{
hunllef.updateAttack(PRAYER);
if (this.uniquePrayerAudio)
{
client.playSoundEffect(SoundEffectID.MAGIC_SPLASH_BOING);
}
}
else if (HUNLLEF_RANGE_PROJECTILES.contains(proj.getId()))
{
hunllef.updateAttack(RANGE);
}
}
}
private void reset()
private void onVarbitChanged(VarbitChanged event)
{
setHunllef(null);
setNextPrayer(null);
setCurrentPrayer(null);
setFirstHitDetected(false);
setAttacks(0);
setPlayerAttacks(6);
}
private HeadIcon getOverheadIcon(NPC npc)
{
NPCDefinition composition = npc.getDefinition();
if (composition != null)
if (this.completeStartup)
{
return composition.getOverheadIcon();
timer.checkStates(true);
}
return null;
}
boolean isInRoom()
boolean fightingBoss()
{
return client.getVar(Varbits.GAUNTLET_FINAL_ROOM_ENTERED) == 1;
}
boolean startedGauntlet()
{
return client.getVar(Varbits.GAUNTLET_ENTERED) == 1;
}
private void updateConfig()
{
this.highlightResources = config.highlightResources();
this.highlightResourcesColor = config.highlightResourcesColor();
this.highlightResourcesIcons = config.highlightResourcesIcons();
this.flashOnWrongAttack = config.flashOnWrongAttack();
this.highlightWidget = config.highlightWidget();
this.resourceIconSize = config.resourceIconSize();
this.projectileIconSize = config.projectileIconSize();
this.countBossAttacks = config.countBossAttacks();
this.countPlayerAttacks = config.countPlayerAttacks();
this.uniquePrayerAudio = config.uniquePrayerAudio();
this.uniquePrayerVisual = config.uniquePrayerVisual();
this.uniqueAttackVisual = config.uniqueAttackVisual();
this.overlayBoss = config.overlayBoss();
this.overlayBossPrayer = config.overlayBossPrayer();
this.overlayTornadoes = config.overlayTornadoes();
this.displayTimerWidget = config.displayTimerWidget();
this.displayTimerChat = config.displayTimerChat();
}
}

View File

@@ -0,0 +1,313 @@
/*
* Copyright (c) 2018, Seth <http://github.com/sethtroll>
* 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.gauntlet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import javax.inject.Inject;
import net.runelite.api.ChatMessageType;
import net.runelite.api.Client;
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
import net.runelite.api.Player;
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 static net.runelite.client.plugins.gauntlet.GauntletTimer.RaidState.IN_BOSS;
import static net.runelite.client.plugins.gauntlet.GauntletTimer.RaidState.IN_RAID;
import static net.runelite.client.plugins.gauntlet.GauntletTimer.RaidState.UNKNOWN;
import net.runelite.client.ui.overlay.Overlay;
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
import net.runelite.client.ui.overlay.OverlayMenuEntry;
import net.runelite.client.ui.overlay.OverlayPosition;
import net.runelite.client.ui.overlay.OverlayPriority;
import net.runelite.client.ui.overlay.components.PanelComponent;
import net.runelite.client.ui.overlay.components.TitleComponent;
import net.runelite.client.ui.overlay.components.table.TableAlignment;
import net.runelite.client.ui.overlay.components.table.TableComponent;
class GauntletTimer extends Overlay
{
private final Client client;
private final GauntletPlugin plugin;
private final PanelComponent panelComponent = new PanelComponent();
@Inject
private ChatMessageManager chatMessageManager;
private long timeRaidStart = -1L;
private long timeBossEnter = -1L;
private RaidState currentState = UNKNOWN;
@Inject
public GauntletTimer(Client client, GauntletPlugin plugin)
{
super(plugin);
setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT);
setPriority(OverlayPriority.HIGH);
this.client = client;
this.plugin = plugin;
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Gauntlet Timer Overlay"));
}
/**
* Resets the timer.
*/
void resetStates()
{
timeRaidStart = -1L;
timeBossEnter = -1L;
currentState = UNKNOWN;
}
/**
* This is called when the player resets the plugin mid-raid. We do not want to confuse the timer.
* <p>
* TODO: Originally, this function will disable the timer if the plugin is started mid raid.
* Unfortunately, VARBITS can't be checked unless you're on the client thread.
* I've no idea how to access RL's task handler.
* Good luck to you. If you restart plugin mid raid, oh well. Your timer's going to be inaccurate.
*/
void initStates()
{
timeRaidStart = -1L;
timeBossEnter = -1L;
if (plugin.startedGauntlet())
{
currentState = IN_RAID;
if (plugin.fightingBoss())
{
currentState = IN_BOSS;
}
}
else
{
currentState = UNKNOWN;
}
}
/**
* Converts the different between two epoch times into minutes:seconds format.
*
* @param epochA long
* @param epochB long
* @return String
*/
private String calculateElapsedTime(long epochA, long epochB)
{
long max = Math.max(epochA, epochB);
long min = Math.min(epochA, epochB);
long elapsedEpoch = max - min;
long seconds = elapsedEpoch / 1000L;
long minutes = seconds / 60L;
seconds = seconds % 60;
if (seconds == 0)
{
return minutes + ":00";
}
if (seconds < 10)
{
return minutes + ":0" + seconds;
}
return minutes + ":" + seconds;
}
/**
* Called when varbit changes. See if the the raid state has changed.
*/
void checkStates(boolean checkVarps)
{
final Player p = client.getLocalPlayer();
if (p == null || !plugin.isCompleteStartup())
{
return;
}
if (checkVarps)
{
switch (currentState)
{
case UNKNOWN:
if (plugin.startedGauntlet() && p.getHealthRatio() != 0)
{
// Player has started a new raid.
if (!plugin.fightingBoss())
{
currentState = IN_RAID;
timeRaidStart = System.currentTimeMillis();
return;
}
currentState = IN_RAID;
timeRaidStart = timeBossEnter = System.currentTimeMillis();
}
break;
case IN_RAID:
if (!plugin.startedGauntlet())
{
printPrepTime();
resetStates();
return;
}
if (plugin.fightingBoss())
{
// Player has begun the boss fight.
printPrepTime();
currentState = IN_BOSS;
timeBossEnter = System.currentTimeMillis();
}
break;
case IN_BOSS:
if (!plugin.fightingBoss() || !plugin.startedGauntlet())
{
// Player has killed the boss.
resetStates();
}
break;
}
}
else
{
if (currentState == IN_BOSS && p.getHealthRatio() == 0)
{
printBossTime();
resetStates();
}
}
}
private void printPrepTime()
{
if (!plugin.isDisplayTimerChat() || timeRaidStart == -1L)
{
return;
}
String elapsedTime = calculateElapsedTime(System.currentTimeMillis(), timeRaidStart);
final ChatMessageBuilder prepmessage = new ChatMessageBuilder()
.append(ChatColorType.NORMAL)
.append("Preparation time: ")
.append(ChatColorType.HIGHLIGHT)
.append(elapsedTime);
chatMessageManager.queue(QueuedMessage.builder()
.type(ChatMessageType.FRIENDSCHATNOTIFICATION)
.runeLiteFormattedMessage(prepmessage.build())
.build());
}
private void printBossTime()
{
if (!plugin.isDisplayTimerChat() || timeRaidStart == -1L || timeBossEnter == -1L)
{
return;
}
String elapsedBossTime = calculateElapsedTime(System.currentTimeMillis(), timeBossEnter);
String elapsedPrepTime = calculateElapsedTime(timeRaidStart, timeBossEnter);
String elapsedTotalTime = calculateElapsedTime(System.currentTimeMillis(), timeRaidStart);
final ChatMessageBuilder challengedurationmessage = new ChatMessageBuilder()
.append(ChatColorType.NORMAL)
.append("Challenge duration: ")
.append(ChatColorType.HIGHLIGHT)
.append(elapsedTotalTime);
chatMessageManager.queue(QueuedMessage.builder()
.type(ChatMessageType.FRIENDSCHATNOTIFICATION)
.runeLiteFormattedMessage(challengedurationmessage.build())
.build());
final ChatMessageBuilder prepdeathmessage = new ChatMessageBuilder()
.append(ChatColorType.NORMAL)
.append("Preparation time: ")
.append(ChatColorType.HIGHLIGHT)
.append(elapsedPrepTime)
.append(ChatColorType.NORMAL)
.append(" player/boss death time: ")
.append(ChatColorType.HIGHLIGHT)
.append(elapsedBossTime);
chatMessageManager.queue(QueuedMessage.builder()
.type(ChatMessageType.FRIENDSCHATNOTIFICATION)
.runeLiteFormattedMessage(prepdeathmessage.build())
.build());
}
@Override
public Dimension render(Graphics2D graphics)
{
if (currentState == UNKNOWN)
{
return null;
}
panelComponent.getChildren().clear();
panelComponent.getChildren().add(TitleComponent.builder().text("Gauntlet Timer").color(Color.WHITE).build());
TableComponent tableComponent = new TableComponent();
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
if (timeRaidStart == -1L)
{ // User restarted the plugin mid raid. Timer is inaccurate.
tableComponent.addRow("Inactive", "0:00");
}
else
{
String elapsedPrepTime, elapsedBossTime, elapsedTotalTime;
elapsedTotalTime = calculateElapsedTime(System.currentTimeMillis(), timeRaidStart);
if (currentState == IN_RAID)
{
elapsedPrepTime = calculateElapsedTime(timeRaidStart, System.currentTimeMillis());
elapsedBossTime = "0:00";
}
else
{
elapsedPrepTime = calculateElapsedTime(timeRaidStart, timeBossEnter);
elapsedBossTime = calculateElapsedTime(System.currentTimeMillis(), timeBossEnter);
}
tableComponent.addRow("Preparation", elapsedPrepTime);
tableComponent.addRow("Boss Fight", elapsedBossTime);
tableComponent.addRow("Total Time", elapsedTotalTime);
panelComponent.getChildren().add(tableComponent);
}
return panelComponent.render(graphics);
}
public enum RaidState
{
UNKNOWN, IN_RAID, IN_BOSS
}
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* 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.gauntlet;
import java.awt.Color;
import java.awt.image.BufferedImage;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import net.runelite.api.NPC;
import net.runelite.api.Prayer;
import net.runelite.api.Skill;
import net.runelite.client.game.SkillIconManager;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
public class Hunllef
{
private NPC npc;
private int bossAttacks;
private int playerAttacks;
private int ticksUntilAttack;
private BufferedImage mage;
private BufferedImage range;
private BossAttackPhase currentPhase;
Hunllef(NPC npc, SkillIconManager skillIconManager)
{
this.npc = npc;
this.bossAttacks = 0;
this.playerAttacks = 6;
this.ticksUntilAttack = 0;
this.mage = skillIconManager.getSkillImage(Skill.MAGIC);
this.range = skillIconManager.getSkillImage(Skill.RANGED);
this.currentPhase = BossAttackPhase.UNKNOWN;
}
void updatePlayerAttack()
{
playerAttacks--;
if (playerAttacks <= 0)
{
playerAttacks = 6;
}
}
void updateAttack(BossAttack style)
{
ticksUntilAttack = 6;
if (style == BossAttack.PRAYER)
{
style = BossAttack.MAGIC;
}
if (style == BossAttack.LIGHTNING)
{
bossAttacks--;
}
else if (style == BossAttack.RANGE)
{
if (currentPhase != BossAttackPhase.RANGE)
{
currentPhase = BossAttackPhase.RANGE;
bossAttacks = 3;
}
else
{
bossAttacks--;
}
}
else if (style == BossAttack.MAGIC)
{
if (currentPhase != BossAttackPhase.MAGIC)
{
currentPhase = BossAttackPhase.MAGIC;
bossAttacks = 3;
}
else
{
bossAttacks--;
}
}
if (bossAttacks <= 0)
{
BossAttackPhase nextPhase;
switch (currentPhase)
{
case MAGIC:
bossAttacks = 4;
nextPhase = BossAttackPhase.RANGE;
break;
case RANGE:
bossAttacks = 4;
nextPhase = BossAttackPhase.MAGIC;
break;
default:
bossAttacks = 0;
nextPhase = BossAttackPhase.UNKNOWN;
break;
}
currentPhase = nextPhase;
}
}
@AllArgsConstructor
@Getter(AccessLevel.PACKAGE)
enum BossAttackPhase
{
MAGIC(Color.CYAN, Prayer.PROTECT_FROM_MAGIC),
RANGE(Color.GREEN, Prayer.PROTECT_FROM_MISSILES),
UNKNOWN(Color.WHITE, null);
private Color color;
private Prayer prayer;
}
enum BossAttack
{
MAGIC,
RANGE,
PRAYER,
LIGHTNING
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* 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.gauntlet;
import java.awt.Color;
import java.awt.image.BufferedImage;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.Projectile;
import net.runelite.api.ProjectileID;
import net.runelite.api.Skill;
import net.runelite.client.game.SkillIconManager;
@Getter(AccessLevel.PACKAGE)
class Missiles
{
private Projectile projectile;
private int id;
private BufferedImage image;
private Color color;
Missiles(Projectile projectile, SkillIconManager skillIconManager)
{
this.projectile = projectile;
this.id = projectile.getId();
this.image = assignedImage(skillIconManager, id);
this.color = assignedColor(id);
}
private Color assignedColor(int id)
{
switch (id)
{
case ProjectileID.HUNLLEF_MAGE_ATTACK:
case ProjectileID.HUNLLEF_CORRUPTED_MAGE_ATTACK:
return Color.CYAN;
case ProjectileID.HUNLLEF_RANGE_ATTACK:
case ProjectileID.HUNLLEF_CORRUPTED_RANGE_ATTACK:
return Color.GREEN;
case ProjectileID.HUNLLEF_PRAYER_ATTACK:
case ProjectileID.HUNLLEF_CORRUPTED_PRAYER_ATTACK:
return Color.MAGENTA;
default:
return null;
}
}
private BufferedImage assignedImage(SkillIconManager SkillIconManager, int id)
{
switch (id)
{
case ProjectileID.HUNLLEF_MAGE_ATTACK:
case ProjectileID.HUNLLEF_CORRUPTED_MAGE_ATTACK:
return SkillIconManager.getSkillImage(Skill.MAGIC);
case ProjectileID.HUNLLEF_RANGE_ATTACK:
case ProjectileID.HUNLLEF_CORRUPTED_RANGE_ATTACK:
return SkillIconManager.getSkillImage(Skill.RANGED);
case ProjectileID.HUNLLEF_PRAYER_ATTACK:
case ProjectileID.HUNLLEF_CORRUPTED_PRAYER_ATTACK:
return SkillIconManager.getSkillImage(Skill.PRAYER);
default:
return null;
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* 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.gauntlet;
import java.awt.image.BufferedImage;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.GameObject;
import net.runelite.api.ObjectID;
import net.runelite.api.Skill;
import net.runelite.api.Tile;
import net.runelite.client.game.SkillIconManager;
@Getter(AccessLevel.PACKAGE)
class Resources
{
private GameObject gameObject;
private Tile tile;
private BufferedImage image;
Resources(GameObject object, Tile tile, SkillIconManager skillIconManager)
{
this.gameObject = object;
this.tile = tile;
this.image = assignedImage(skillIconManager, object.getId());
}
private BufferedImage assignedImage(SkillIconManager SkillIconManager, int id)
{
switch (id)
{
case ObjectID.CRYSTAL_DEPOSIT:
case ObjectID.CORRUPT_DEPOSIT:
return SkillIconManager.getSkillImage(Skill.MINING);
case ObjectID.PHREN_ROOTS:
case ObjectID.PHREN_ROOTS_36066:
return SkillIconManager.getSkillImage(Skill.WOODCUTTING);
case ObjectID.FISHING_SPOT_36068:
case ObjectID.FISHING_SPOT_35971:
return SkillIconManager.getSkillImage(Skill.FISHING);
case ObjectID.GRYM_ROOT:
case ObjectID.GRYM_ROOT_36070:
return SkillIconManager.getSkillImage(Skill.HERBLORE);
case ObjectID.LINUM_TIRINUM:
case ObjectID.LINUM_TIRINUM_36072:
return SkillIconManager.getSkillImage(Skill.FARMING);
default:
return null;
}
}
}

View File

@@ -1,5 +1,4 @@
/*
* Copyright (c) 2019, xperiaclash <https://github.com/xperiaclash>
* Copyright (c) 2019, ganom <https://github.com/Ganom>
* All rights reserved.
*
@@ -22,21 +21,30 @@
* (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.gauntlet;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigItem;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.NPC;
public interface GauntletPluginConfig extends Config
@Getter(AccessLevel.PACKAGE)
class Tornado
{
@ConfigItem(
position = 0,
keyName = "gauntletEnable",
name = "Enable gauntlet",
description = "gauntlet boss prayer"
)
default boolean enableGauntlet()
private NPC npc;
private int timeLeft;
Tornado(NPC npc)
{
return true;
this.npc = npc;
this.timeLeft = 20;
}
}
void updateTimeLeft()
{
if (timeLeft > 0)
{
timeLeft--;
}
}
}

View File

@@ -175,7 +175,7 @@ enum TransportationPointLocation
TELEPORT_RUNE_ARDOUGNE("Teleport to Rune Essence", new WorldPoint(2681, 3325, 0)),
TELEPORT_RUNE_YANILLE("Teleport to Rune Essence", new WorldPoint(2592, 3089, 0)),
TELEPORT_SORCERESS_GARDEN("Teleport to Sorceress's Garden", new WorldPoint(3320, 3141, 0)),
TELEPORT_PRIFDDINAS_LIBRARY("Teleport to Priffdinas Library", new WorldPoint(3254, 6082, 2)),
TELEPORT_PRIFDDINAS_LIBRARY("Teleport to Prifddinas Library", new WorldPoint(3254, 6082, 2)),
//Other
ALTER_KOUREND_UNDERGROUND("Altar to Skotizo", new WorldPoint(1662, 10047, 0)),

View File

@@ -30,6 +30,8 @@ import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.imageio.ImageIO;
import javax.inject.Singleton;
import javax.swing.ImageIcon;
@@ -40,8 +42,6 @@ import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicProgressBarUI;
import lombok.extern.slf4j.Slf4j;
import net.runelite.client.RuneLite;
import net.runelite.client.RuneLiteProperties;
import net.runelite.client.util.SwingUtil;
import org.pushingpixels.substance.internal.SubstanceSynapse;
@@ -53,7 +53,9 @@ import org.pushingpixels.substance.internal.SubstanceSynapse;
@Singleton
public class RuneLiteSplashScreen
{
private final RuneLiteProperties runeLiteProperties = new RuneLiteProperties();
private static final String RUNELITE_VERSION = "runelite.version";
private static final String RUNELITE_PLUS_VERSION = "runelite.plus.version";
private static final String RUNELITE_PLUS_DATE = "runelite.plus.builddate";
private JFrame frame;
private final JPanel panel = new JPanel();
@@ -61,6 +63,20 @@ public class RuneLiteSplashScreen
private JLabel subMessageLabel;
private final JProgressBar progressBar = new JProgressBar();
private final Properties properties = new Properties();
public RuneLiteSplashScreen()
{
try (InputStream in = getClass().getResourceAsStream("/runelite.plus.properties"))
{
properties.load(in);
}
catch (IOException ex)
{
log.warn("unable to load propertries", ex);
}
}
/**
* This is not done in the constructor in order to avoid processing in case the user chooses to not load
* the splash screen.
@@ -90,7 +106,7 @@ public class RuneLiteSplashScreen
panel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
final GridBagLayout layout = new GridBagLayout();
layout.columnWeights = new double[]{1};
layout.rowWeights = new double[]{1, 0, 0, 1, 0, 1};
layout.rowWeights = new double[]{1, 0, 0, 1, 0, 0, 1};
panel.setLayout(layout);
// logo
@@ -119,7 +135,7 @@ public class RuneLiteSplashScreen
panel.add(title, titleConstraints);
// version
final JLabel version = new JLabel("RuneLite Version : " + runeLiteProperties.getVersion());
final JLabel version = new JLabel("RuneLite Version : " + properties.getProperty(RUNELITE_VERSION));
version.setForeground(Color.GREEN);
version.setFont(FontManager.getRunescapeSmallFont());
version.setForeground(version.getForeground().darker());
@@ -128,34 +144,42 @@ public class RuneLiteSplashScreen
panel.add(version, versionConstraints);
// version
final JLabel litVersion = new JLabel("Plus Version : " + RuneLite.PLUS_VERSION);
final JLabel litVersion = new JLabel("Plus Version : " + properties.getProperty(RUNELITE_PLUS_VERSION));
litVersion.setForeground(Color.GREEN);
litVersion.setFont(FontManager.getRunescapeSmallFont());
litVersion.setForeground(litVersion.getForeground().darker());
final GridBagConstraints litVersionConstraints = new GridBagConstraints();
litVersionConstraints.gridy = 3;
litVersionConstraints.weightx = 4;
panel.add(litVersion, litVersionConstraints);
// build date
final JLabel litBuildDate = new JLabel("Build date : " + properties.getProperty(RUNELITE_PLUS_DATE));
litBuildDate.setForeground(Color.GREEN);
litBuildDate.setFont(FontManager.getRunescapeSmallFont());
litBuildDate.setForeground(litBuildDate.getForeground().darker());
final GridBagConstraints litBuildDateConstraints = new GridBagConstraints();
litBuildDateConstraints.gridy = 4;
panel.add(litBuildDate, litBuildDateConstraints);
// progressbar
final GridBagConstraints progressConstraints = new GridBagConstraints();
progressConstraints.fill = GridBagConstraints.HORIZONTAL;
progressConstraints.anchor = GridBagConstraints.SOUTH;
progressConstraints.gridy = 4;
progressConstraints.gridy = 5;
panel.add(progressBar, progressConstraints);
// main message
messageLabel.setFont(FontManager.getRunescapeSmallFont());
final GridBagConstraints messageConstraints = new GridBagConstraints();
messageConstraints.gridy = 5;
messageConstraints.gridy = 6;
panel.add(messageLabel, messageConstraints);
// alternate message
final GridBagConstraints subMessageConstraints = new GridBagConstraints();
subMessageLabel.setForeground(subMessageLabel.getForeground().darker());
subMessageLabel.setFont(FontManager.getRunescapeSmallFont());
subMessageConstraints.gridy = 6;
subMessageConstraints.gridy = 7;
panel.add(subMessageLabel, subMessageConstraints);
frame.setContentPane(panel);
@@ -235,7 +259,7 @@ public class RuneLiteSplashScreen
final GridBagConstraints progressConstraints = new GridBagConstraints();
progressConstraints.fill = GridBagConstraints.HORIZONTAL;
progressConstraints.anchor = GridBagConstraints.SOUTH;
progressConstraints.gridy = 4;
progressConstraints.gridy = 5;
panel.add(progressBar, progressConstraints);
panel.validate();
}

View File

@@ -45,6 +45,7 @@ import net.runelite.api.Perspective;
import net.runelite.api.Point;
import net.runelite.api.Prayer;
import net.runelite.api.TileObject;
import net.runelite.api.VarClientInt;
import net.runelite.api.coords.LocalPoint;
import net.runelite.api.coords.WorldArea;
import net.runelite.api.coords.WorldPoint;
@@ -348,7 +349,7 @@ public class OverlayUtil
{
Widget widget = client.getWidget(prayer.getWidgetInfo());
if (widget == null || widget.isHidden())
if (widget == null || client.getVar(VarClientInt.PLAYER_INTERFACE_CONTAINER_OPENED) != 5)
{
return null;
}

View File

@@ -1,10 +1,10 @@
runelite.title=RuneLite
runelite.version=${project.version}
runescape.version=${rs.version}
runelite.discord.appid=409416265891971072
runelite.version=@project.version@
runescape.version=@rs.version@
runelite.plus.discord.appid=560644885250572289
runelite.discord.invite=https://discord.gg/HN5gf3m
runelite.github.link=https://github.com/runelite-extended/runelite
runelite.wiki.link=https://github.com/runelite-extended/runelite/wiki
runelite.patreon.link=https://www.patreon.com/RuneLitePlus
runelit.version =2.0.1-1
runelite.plus.title=RuneLitePlus
runelite.plus.version=@runelite.plus.version@
runelite.plus.builddate=@runelite.plus.builddate@

View File

@@ -1,43 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.runelite</groupId>
<artifactId>scripts</artifactId>
<version>1.0.0</version>
<name>Scripts</name>
<build>
<extensions>
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-webdav-jackrabbit</artifactId>
<version>2.12</version>
</extension>
</extensions>
</build>
</project>