runelite-client: add volcanic mine plugin
This commit is contained in:
@@ -48,6 +48,7 @@ class WidgetID
|
||||
static final int PRIVATE_CHAT = 163;
|
||||
static final int CHATBOX_GROUP_ID = 162;
|
||||
static final int WORLD_MAP_MENU_GROUP_ID = 160;
|
||||
static final int VOLCANIC_MINE_GROUP_ID = 611;
|
||||
|
||||
static class WorldMap
|
||||
{
|
||||
@@ -188,4 +189,20 @@ class WidgetID
|
||||
static final int WEAPON_NAME = 1;
|
||||
static final int LEVEL = 2;
|
||||
}
|
||||
|
||||
static class VolcanicMine
|
||||
{
|
||||
static final int GENERAL_INFOBOX_GROUP_ID = 4;
|
||||
static final int TIME_LEFT = 8;
|
||||
static final int POINTS = 10;
|
||||
static final int STABILITY = 12;
|
||||
static final int PLAYER_COUNT = 14;
|
||||
static final int VENTS_INFOBOX_GROUP_ID = 15;
|
||||
static final int VENT_A_PERCENTAGE = 19;
|
||||
static final int VENT_B_PERCENTAGE = 20;
|
||||
static final int VENT_C_PERCENTAGE = 21;
|
||||
static final int VENT_A_STATUS = 23;
|
||||
static final int VENT_B_STATUS = 24;
|
||||
static final int VENT_C_STATUS = 25;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,19 @@ public enum WidgetInfo
|
||||
PESTCONTROL_ACTIVITY_BAR(WidgetID.PESTRCONTROL_GROUP_ID, WidgetID.PestControl.ACTIVITY_BAR),
|
||||
PESTCONTROL_ACTIVITY_PROGRESS(WidgetID.PESTRCONTROL_GROUP_ID, WidgetID.PestControl.ACTIVITY_PROGRESS),
|
||||
|
||||
VOLCANICMINE_GENERAL_INFOBOX_GROUP(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.GENERAL_INFOBOX_GROUP_ID),
|
||||
VOLCANICMINE_TIME_LEFT(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.TIME_LEFT),
|
||||
VOLCANICMINE_POINTS(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.POINTS),
|
||||
VOLCANICMINE_STABILITY(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.STABILITY),
|
||||
VOLCANICMINE_PLAYER_COUNT(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.PLAYER_COUNT),
|
||||
VOLCANICMINE_VENTS_INFOBOX_GROUP(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.VENTS_INFOBOX_GROUP_ID),
|
||||
VOLCANICMINE_VENT_A_PERCENTAGE(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.VENT_A_PERCENTAGE),
|
||||
VOLCANICMINE_VENT_B_PERCENTAGE(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.VENT_B_PERCENTAGE),
|
||||
VOLCANICMINE_VENT_C_PERCENTAGE(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.VENT_C_PERCENTAGE),
|
||||
VOLCANICMINE_VENT_A_STATUS(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.VENT_A_STATUS),
|
||||
VOLCANICMINE_VENT_B_STATUS(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.VENT_B_STATUS),
|
||||
VOLCANICMINE_VENT_C_STATUS(WidgetID.VOLCANIC_MINE_GROUP_ID, WidgetID.VolcanicMine.VENT_C_STATUS),
|
||||
|
||||
CLAN_CHAT_TITLE(WidgetID.CLAN_CHAT_GROUP_ID, WidgetID.ClanChat.TITLE),
|
||||
CLAN_CHAT_NAME(WidgetID.CLAN_CHAT_GROUP_ID, WidgetID.ClanChat.NAME),
|
||||
CLAN_CHAT_OWNER(WidgetID.CLAN_CHAT_GROUP_ID, WidgetID.ClanChat.OWNER),
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.volcanicminehelper;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public enum LavaPlatform
|
||||
{
|
||||
STAGE_1(30998, 90),
|
||||
STAGE_2(30999, 45),
|
||||
STAGE_3(31000, 5);
|
||||
|
||||
private final int objectId;
|
||||
private final Duration time;
|
||||
|
||||
LavaPlatform(int objectId, int time)
|
||||
{
|
||||
this.objectId = objectId;
|
||||
this.time = Duration.ofSeconds(time);
|
||||
}
|
||||
|
||||
public int getObjectId()
|
||||
{
|
||||
return objectId;
|
||||
}
|
||||
|
||||
public Duration getTime()
|
||||
{
|
||||
return time;
|
||||
}
|
||||
|
||||
public static LavaPlatform fromId(int id)
|
||||
{
|
||||
for (LavaPlatform lavaPlatform : values())
|
||||
{
|
||||
if (lavaPlatform.objectId == id)
|
||||
{
|
||||
return lavaPlatform;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2017. l2-
|
||||
*
|
||||
* 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.volcanicminehelper;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup(
|
||||
keyName = "VolcanicMine",
|
||||
name = "Volcanic mine",
|
||||
description = "Configuration for the volcanic mine plugin"
|
||||
)
|
||||
public interface VolcanicMineConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 0,
|
||||
keyName = "enabled",
|
||||
name = "Enable",
|
||||
description = "Configures whether the volcanic mine plugin is displayed"
|
||||
)
|
||||
default boolean enabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "tray",
|
||||
name = "Send Tray Notification",
|
||||
description = "Toggles tray notifications"
|
||||
)
|
||||
default boolean sendTrayNotification()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "focused",
|
||||
name = "Alert When Focused",
|
||||
description = "Toggles idle notifications for when the client is focused"
|
||||
)
|
||||
default boolean alertWhenFocused()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "request",
|
||||
name = "Request Window Focus",
|
||||
description = "Toggles window focus request"
|
||||
)
|
||||
default boolean requestFocus()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 4,
|
||||
keyName = "prayerHelper",
|
||||
name = "shows prayer",
|
||||
description = "Shows when you need to use protection prayers"
|
||||
)
|
||||
default boolean prayerHelperEnabled()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 5,
|
||||
keyName = "platformColorLow",
|
||||
name = "PlatformColor low risk",
|
||||
description = "Configures the color for the platformOverlay"
|
||||
)
|
||||
default Color platformColorLow()
|
||||
{
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 6,
|
||||
keyName = "platformColorMed",
|
||||
name = "PlatformColor med risk",
|
||||
description = "Configures the color for the platformOverlay"
|
||||
)
|
||||
default Color platformColorMed()
|
||||
{
|
||||
return Color.YELLOW;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 7,
|
||||
keyName = "platformColorHigh",
|
||||
name = "PlatformColor high risk",
|
||||
description = "Configures the color for the platformOverlay"
|
||||
)
|
||||
default Color platformColorHigh()
|
||||
{
|
||||
return Color.decode("#FF3333");
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
keyName = "platformTimerThreshold",
|
||||
name = "Platform timer notification threshold",
|
||||
description = "At what time does the plugin notify (in seconds), set to -1 to disable"
|
||||
)
|
||||
default int platformTimerThreshold()
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 9,
|
||||
keyName = "timeLeftThreshold",
|
||||
name = "Time left threshold",
|
||||
description = "At what time does the plugin notify (in seconds), set to -1 to disable"
|
||||
)
|
||||
default int timerThreshold()
|
||||
{
|
||||
return 40;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 9,
|
||||
keyName = "stabilityThreshold",
|
||||
name = "Stability threshold",
|
||||
description = "At what stability does the plugin notify (in percentage), set to -1 to disable"
|
||||
)
|
||||
default int stabilityPercentageThreshold()
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 10,
|
||||
keyName = "prayer",
|
||||
name = "Prayer warning",
|
||||
description = "Protect prayer warning setting"
|
||||
)
|
||||
default WarningMode prayerWarning()
|
||||
{
|
||||
return WarningMode.INGAME_AND_NOTIFICATION;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 11,
|
||||
keyName = "hotTiles",
|
||||
name = "Hot Tile warning",
|
||||
description = "Hot tile warning setting"
|
||||
)
|
||||
default WarningMode hotTileWarning()
|
||||
{
|
||||
return WarningMode.INGAME_AND_NOTIFICATION;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 12,
|
||||
keyName = "timerWarning",
|
||||
name = "timer warning",
|
||||
description = "timer low warning setting"
|
||||
)
|
||||
default WarningMode timerWarning()
|
||||
{
|
||||
return WarningMode.INGAME_AND_NOTIFICATION;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 13,
|
||||
keyName = "stabilityWarning",
|
||||
name = "stability warning",
|
||||
description = "stability low warning setting"
|
||||
)
|
||||
default WarningMode stabilityWarning()
|
||||
{
|
||||
return WarningMode.INGAME_AND_NOTIFICATION;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
/*
|
||||
* Copyright (c) 2017. l2-
|
||||
*
|
||||
* 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.volcanicminehelper;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.inject.Binder;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import static java.lang.Math.abs;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Region;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.RuneLite;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.task.Schedule;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.Query;
|
||||
import net.runelite.api.queries.NPCQuery;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Volcanic mine helper"
|
||||
)
|
||||
public class VolcanicMineHelperPlugin extends Plugin
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(VolcanicMineHelperPlugin.class);
|
||||
private static final int REGION_SIZE = 104;
|
||||
private static final int MAX_DISTANCE = 2400;
|
||||
private static final int LAVA_ID = 30997;
|
||||
private static final int LAVA_BEAST_ATTACK_RANGE = 1400;
|
||||
private static final String LAVA_BEAST = "Lava beast";
|
||||
private static final Pattern coltagPattern = Pattern.compile("((<col=([0-f]){6}>)|(<\\/col>))");
|
||||
|
||||
@Inject
|
||||
@Nullable
|
||||
Client client;
|
||||
|
||||
@Inject
|
||||
RuneLite runeLite;
|
||||
|
||||
@Inject
|
||||
VolcanicMineConfig config;
|
||||
|
||||
@Inject
|
||||
VolcanicMineOverlay overlay;
|
||||
|
||||
private Map<Tile, Instant> objectTimerMap = new HashMap<>();
|
||||
private boolean drawRangePray = false;
|
||||
private boolean isAboutToFall = false;
|
||||
private boolean isAboutToCollapse = false;
|
||||
private boolean timerRunningLow = false;
|
||||
private boolean isInside = false;
|
||||
private int stabilityPercentageThreshold;
|
||||
|
||||
@Override
|
||||
public void configure(Binder binder)
|
||||
{
|
||||
binder.bind(VolcanicMineOverlay.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
VolcanicMineConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(VolcanicMineConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
if (config.stabilityPercentageThreshold() >= -1 && config.stabilityPercentageThreshold() <= 100)
|
||||
{
|
||||
stabilityPercentageThreshold = config.stabilityPercentageThreshold();
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean getInside()
|
||||
{
|
||||
return isInside;
|
||||
}
|
||||
|
||||
public VolcanicMineConfig getConfig()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
public Map<Tile, Instant> getObjectTimerMap()
|
||||
{
|
||||
return objectTimerMap;
|
||||
}
|
||||
|
||||
public Boolean getDrawRangePray()
|
||||
{
|
||||
return drawRangePray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Overlay getOverlay()
|
||||
{
|
||||
return overlay;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (config.stabilityPercentageThreshold() >= -1 && config.stabilityPercentageThreshold() <= 100)
|
||||
{
|
||||
stabilityPercentageThreshold = config.stabilityPercentageThreshold();
|
||||
}
|
||||
}
|
||||
|
||||
@Schedule(
|
||||
period = 600,
|
||||
unit = ChronoUnit.MILLIS
|
||||
)
|
||||
public void update()
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN || !config.enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
isInside = isInside();
|
||||
if (!isInside)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lookForGameObjects();
|
||||
cleanMap();
|
||||
//-- it is unlikely more than 1 of the following notifications will be triggered in 1 update call.
|
||||
//-- it is possible so maybe send 1 notification per update max which contains the message(s)?
|
||||
//check if in range of a lava beast
|
||||
boolean lastRangePray = drawRangePray;
|
||||
drawRangePray = lavaBeastInRange(client.getLocalPlayer());
|
||||
if (!client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES) && drawRangePray && !lastRangePray)
|
||||
{
|
||||
warnPlayer(config.prayerWarning(), "Turn on prayer!");
|
||||
}
|
||||
//check if about to fall into lava
|
||||
boolean lastIsAboutToFall = isAboutToFall;
|
||||
isAboutToFall = isAboutToFall(client.getLocalPlayer().getLocalLocation());
|
||||
if (isAboutToFall && !lastIsAboutToFall)
|
||||
{
|
||||
warnPlayer(config.hotTileWarning(), "Watch out for the lava!");
|
||||
}
|
||||
//check if timer is about to run out
|
||||
boolean lastTimerRunningLow = timerRunningLow;
|
||||
timerRunningLow = isTimerRunningLow();
|
||||
if (timerRunningLow && !lastTimerRunningLow)
|
||||
{
|
||||
warnPlayer(config.timerWarning(), "Time to bail!");
|
||||
}
|
||||
//check if stability is low
|
||||
boolean lastIsAboutToCollapse = isAboutToCollapse;
|
||||
isAboutToCollapse = isAboutToCollapse();
|
||||
if (isAboutToCollapse && !lastIsAboutToCollapse)
|
||||
{
|
||||
warnPlayer(config.stabilityWarning(), "Stability is low!");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAboutToCollapse()
|
||||
{
|
||||
Widget widget = client.getWidget(WidgetInfo.VOLCANICMINE_STABILITY);
|
||||
if (widget != null && !widget.isHidden())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Integer.parseInt(removeColTags(widget.getText().replace("%", ""))) < stabilityPercentageThreshold) //sanitize of col tags
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException ex)
|
||||
{
|
||||
logger.debug("Failed to retrieve stability percentage", ex);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isTimerRunningLow()
|
||||
{
|
||||
Widget widget = client.getWidget(WidgetInfo.VOLCANICMINE_TIME_LEFT);
|
||||
if (widget != null && !widget.isHidden())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (timeToSeconds(widget.getText()) < config.timerThreshold())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException ex)
|
||||
{
|
||||
logger.debug("Failed to retrieve time left", ex);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAboutToFall(Point point)
|
||||
{
|
||||
Instant now = Instant.now();
|
||||
for (Tile tile : objectTimerMap.keySet())
|
||||
{
|
||||
if (tile.getGameObjects() != null
|
||||
&& tile.getGameObjects()[0] != null
|
||||
&& tile.getGameObjects()[0].getLocalLocation().equals(point)
|
||||
&& objectTimerMap.get(tile).isAfter(now) //in case the entry hasn't been removed from the hashmap, ignore.
|
||||
&& Duration.between(now, objectTimerMap.get(tile)).getSeconds() < config.platformTimerThreshold())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isInside()
|
||||
{
|
||||
Widget widget = client.getWidget(WidgetInfo.VOLCANICMINE_GENERAL_INFOBOX_GROUP);
|
||||
return widget != null && !widget.isHidden();
|
||||
}
|
||||
|
||||
private boolean lavaBeastInRange(Player player)
|
||||
{
|
||||
Query query = new NPCQuery()
|
||||
.nameEquals(LAVA_BEAST)
|
||||
.isWithinArea(player.getLocalLocation(), LAVA_BEAST_ATTACK_RANGE);
|
||||
NPC[] npcs = runeLite.runQuery(query);
|
||||
return npcs.length > 0;
|
||||
}
|
||||
|
||||
private void warnPlayer(WarningMode warningMode, String warning)
|
||||
{
|
||||
if (warningMode == WarningMode.INGAME || warningMode == WarningMode.INGAME_AND_NOTIFICATION)
|
||||
{
|
||||
client.sendGameMessage(getColTag(config.platformColorHigh()) + "Volcanic Mine helper: " + warning);
|
||||
}
|
||||
if (warningMode == WarningMode.NOTIFICATION || warningMode == WarningMode.INGAME_AND_NOTIFICATION)
|
||||
{
|
||||
sendNotification(warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendNotification(String message)
|
||||
{
|
||||
if (!config.alertWhenFocused() && runeLite.getGui().isFocused())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (config.requestFocus())
|
||||
{
|
||||
runeLite.getGui().requestFocus();
|
||||
}
|
||||
if (config.sendTrayNotification())
|
||||
{
|
||||
runeLite.notify(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void lookForGameObjects()
|
||||
{
|
||||
Player player = client.getLocalPlayer();
|
||||
Region region = client.getRegion();
|
||||
Tile[][][] tiles = region.getTiles();
|
||||
|
||||
int z = client.getPlane();
|
||||
|
||||
for (int x = 0; x < REGION_SIZE; ++x)
|
||||
{
|
||||
for (int y = 0; y < REGION_SIZE; ++y)
|
||||
{
|
||||
Tile tile = tiles[z][x][y];
|
||||
|
||||
if (tile == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
lookForPlatforms(tile, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void lookForPlatforms(Tile tile, Player player)
|
||||
{
|
||||
Point playerLocation = player.getLocalLocation();
|
||||
GameObject[] gameObjects = tile.getGameObjects();
|
||||
if (gameObjects == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (GameObject gameObject : gameObjects)
|
||||
{
|
||||
if (gameObject == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LavaPlatform lavaPlatform = LavaPlatform.fromId(gameObject.getId());
|
||||
Point objectLocation = gameObject.getLocalLocation();
|
||||
|
||||
if (lavaPlatform == null
|
||||
|| abs(playerLocation.getX() - objectLocation.getX()) > MAX_DISTANCE
|
||||
|| abs(playerLocation.getY() - objectLocation.getY()) > MAX_DISTANCE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant vanishTime = now.plus(lavaPlatform.getTime());
|
||||
|
||||
Instant returnInstant = objectTimerMap.putIfAbsent(tile, vanishTime);
|
||||
if (returnInstant != null)
|
||||
{
|
||||
if (returnInstant.isBefore(now)
|
||||
|| vanishTime.isBefore(returnInstant))
|
||||
{
|
||||
objectTimerMap.replace(tile, vanishTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanMap()
|
||||
{
|
||||
//remove the timers which hit 0
|
||||
objectTimerMap = objectTimerMap.entrySet().stream()
|
||||
.filter(entry -> Instant.now().isBefore(entry.getValue()))
|
||||
.filter(v -> v.getKey().getGameObjects() != null && v.getKey().getGameObjects()[0] != null && v.getKey().getGameObjects()[0].getId() != LAVA_ID)
|
||||
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
|
||||
}
|
||||
|
||||
public static int timeToSeconds(String s) throws NumberFormatException
|
||||
{
|
||||
String[] time = s.split(":", 2);
|
||||
if (time.length < 2)
|
||||
{
|
||||
return Integer.parseInt(time[0]);
|
||||
}
|
||||
return Integer.parseInt(time[0]) * 60 + Integer.parseInt(time[1]);
|
||||
}
|
||||
|
||||
public static String getColTag(Color color)
|
||||
{
|
||||
return color == null ? "" : "<col=" + Integer.toHexString(color.getRGB() & 0xFFFFFF) + ">";
|
||||
}
|
||||
|
||||
public static String removeColTags(String s)
|
||||
{
|
||||
StringBuffer result = new StringBuffer();
|
||||
Matcher m = coltagPattern.matcher(s);
|
||||
while (m.find())
|
||||
{
|
||||
m.appendReplacement(result, "");
|
||||
}
|
||||
m.appendTail(result);
|
||||
return result.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2017. l2-
|
||||
*
|
||||
* 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.volcanicminehelper;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.Region;
|
||||
import net.runelite.api.Tile;
|
||||
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.OverlayUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class VolcanicMineOverlay extends Overlay
|
||||
{
|
||||
private static final Logger logger = LoggerFactory.getLogger(VolcanicMineHelperPlugin.class);
|
||||
|
||||
private static final int THRESH_LOW = 45;
|
||||
private static final int THRESH_MED = 5;
|
||||
|
||||
private static final int REGION_SIZE = 104;
|
||||
private static final int Z_OFFSET_TIMER = 25;
|
||||
private static final String PROTECT_MESSAGE = "Protect!";
|
||||
|
||||
private final VolcanicMineHelperPlugin plugin;
|
||||
private final VolcanicMineConfig config;
|
||||
|
||||
private final Client client;
|
||||
private Image protectFromMissilesImg;
|
||||
|
||||
@Inject
|
||||
VolcanicMineOverlay(@Nullable Client client, VolcanicMineHelperPlugin plugin, VolcanicMineConfig config)
|
||||
{
|
||||
super(OverlayPosition.DYNAMIC);
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (client == null || client.getGameState() != GameState.LOGGED_IN || !plugin.getInside() || !config.enabled())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
Font font = FontManager.getRunescapeFont();
|
||||
if (font != null)
|
||||
{
|
||||
graphics.setFont(font);
|
||||
}
|
||||
renderTileObjects(graphics);
|
||||
renderRangePrayer(graphics);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderRangePrayer(Graphics2D graphics)
|
||||
{
|
||||
if (client.getViewportWidget() == null || !plugin.getDrawRangePray() || !config.prayerHelperEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Image protectFromMissiles = getProtectFromMissilesImage();
|
||||
if (protectFromMissiles == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Rectangle viewport = client.getViewportWidget().getBounds();
|
||||
Rectangle stringBounds = graphics.getFontMetrics().getStringBounds(PROTECT_MESSAGE, graphics).getBounds();
|
||||
int x = (int) (viewport.getX() + viewport.getWidth());
|
||||
int y = (int) (viewport.getY() + viewport.getHeight());
|
||||
int width = (int) stringBounds.getWidth() + 6;
|
||||
int height = (int) (protectFromMissiles.getHeight(null) + stringBounds.getHeight()) + 5;
|
||||
Rectangle rectangle = new Rectangle(x - width, y - height, width, height);
|
||||
graphics.setColor(new Color(255, 255, 255, 150));
|
||||
graphics.fillRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
||||
graphics.setColor(client.isPrayerActive(Prayer.PROTECT_FROM_MISSILES) ? Color.GREEN : Color.WHITE);
|
||||
graphics.drawRect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
|
||||
graphics.drawImage(protectFromMissiles, x - protectFromMissiles.getWidth(null) - 10, y - protectFromMissiles.getHeight(null) - 15, null);
|
||||
graphics.drawString(PROTECT_MESSAGE, x - (int) stringBounds.getWidth() - 2, y);
|
||||
}
|
||||
|
||||
//this is less efficient than drawing from the map however this is more accurate as it doesn't draw false positives (tiles which are not in the current region).
|
||||
private void renderTileObjects(Graphics2D graphics)
|
||||
{
|
||||
Region region = client.getRegion();
|
||||
Tile[][][] tiles = region.getTiles();
|
||||
|
||||
int z = client.getPlane();
|
||||
|
||||
for (int x = 0; x < REGION_SIZE; ++x)
|
||||
{
|
||||
for (int y = 0; y < REGION_SIZE; ++y)
|
||||
{
|
||||
Tile tile = tiles[z][x][y];
|
||||
|
||||
if (tile == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
renderGameObjects(graphics, tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderGameObjects(Graphics2D graphics, Tile tile)
|
||||
{
|
||||
GameObject[] gameObjects = tile.getGameObjects();
|
||||
if (gameObjects == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (GameObject gameObject : gameObjects)
|
||||
{
|
||||
if (gameObject != null && plugin.getObjectTimerMap().containsKey(tile))
|
||||
{
|
||||
Duration duration = Duration.between(Instant.now(), plugin.getObjectTimerMap().get(tile));
|
||||
if (!duration.isNegative())
|
||||
{
|
||||
long seconds = duration.getSeconds();
|
||||
int minutes = (int) seconds / 60;
|
||||
String text = String.format("%d:%02d", minutes, seconds % 60); // format as m:ss
|
||||
Color color;
|
||||
if (seconds > THRESH_LOW)
|
||||
{
|
||||
color = config.platformColorLow();;
|
||||
}
|
||||
else if (seconds > THRESH_MED)
|
||||
{
|
||||
color = config.platformColorMed();
|
||||
}
|
||||
else
|
||||
{
|
||||
color = config.platformColorHigh();
|
||||
}
|
||||
|
||||
Point location = gameObject.getCanvasTextLocation(graphics, text, Z_OFFSET_TIMER);
|
||||
if (location != null)
|
||||
{
|
||||
OverlayUtil.renderTextLocation(graphics, location, text, color);
|
||||
return; //only 1 timer per tile
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Image getProtectFromMissilesImage()
|
||||
{
|
||||
if (protectFromMissilesImg == null)
|
||||
{
|
||||
String path = "/prayers/protect_from_missiles.png";
|
||||
protectFromMissilesImg = getImage(path);
|
||||
}
|
||||
return protectFromMissilesImg;
|
||||
}
|
||||
|
||||
private Image getImage(String path)
|
||||
{
|
||||
Image image = null;
|
||||
try
|
||||
{
|
||||
InputStream in = VolcanicMineOverlay.class.getResourceAsStream(path);
|
||||
image = ImageIO.read(in);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
logger.warn("Error loading image", e);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2017. l2-
|
||||
*
|
||||
* 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.volcanicminehelper;
|
||||
|
||||
public enum WarningMode
|
||||
{
|
||||
OFF("Off"),
|
||||
INGAME("Ingame message"),
|
||||
NOTIFICATION("Windows notification"),
|
||||
INGAME_AND_NOTIFICATION("Ingame & notification");
|
||||
|
||||
private final String name;
|
||||
|
||||
WarningMode(String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user