Merge branch 'master' into loot-tracker-reset
This commit is contained in:
@@ -451,7 +451,7 @@ public interface ChatColorConfig extends Config
|
||||
)
|
||||
default Color transparentExamineHighlight()
|
||||
{
|
||||
return Color.decode("#0000FF");
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
|
||||
@@ -28,6 +28,8 @@ import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -36,26 +38,49 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
{
|
||||
private final ConfigManager manager;
|
||||
|
||||
// Caches for annotation values
|
||||
private static final Map<Class<?>, String> groupValueCache = new HashMap<>();
|
||||
private static final Map<Method, String> methodKeyNameCache = new HashMap<>();
|
||||
|
||||
public ConfigInvocationHandler(ConfigManager manager)
|
||||
{
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
private static String groupValueFromProxy(Class<?> proxyClass)
|
||||
{
|
||||
Class<?> iface = proxyClass.getInterfaces()[0];
|
||||
ConfigGroup group = iface.getAnnotation(ConfigGroup.class);
|
||||
|
||||
return group == null ? null : group.value();
|
||||
}
|
||||
|
||||
private static String keyNameFromMethod(Method method)
|
||||
{
|
||||
ConfigItem item = method.getAnnotation(ConfigItem.class);
|
||||
|
||||
return item == null ? null : item.keyName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
|
||||
{
|
||||
Class<?> iface = proxy.getClass().getInterfaces()[0];
|
||||
|
||||
ConfigGroup group = iface.getAnnotation(ConfigGroup.class);
|
||||
ConfigItem item = method.getAnnotation(ConfigItem.class);
|
||||
|
||||
if (group == null)
|
||||
String itemKeyName, groupValue;
|
||||
try
|
||||
{
|
||||
groupValue = groupValueCache.computeIfAbsent(proxy.getClass(), ConfigInvocationHandler::groupValueFromProxy);
|
||||
}
|
||||
catch (NullPointerException e)
|
||||
{
|
||||
log.warn("Configuration proxy class {} has no @ConfigGroup!", proxy.getClass());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item == null)
|
||||
try
|
||||
{
|
||||
itemKeyName = methodKeyNameCache.computeIfAbsent(method, ConfigInvocationHandler::keyNameFromMethod);
|
||||
}
|
||||
catch (NullPointerException e)
|
||||
{
|
||||
log.warn("Configuration method {} has no @ConfigItem!", method);
|
||||
return null;
|
||||
@@ -64,38 +89,43 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
if (args == null)
|
||||
{
|
||||
// Getting configuration item
|
||||
String value = manager.getConfiguration(group.value(), item.keyName());
|
||||
|
||||
if (value == null)
|
||||
return manager.getConfigObjectFromCacheOrElse(groupValue, itemKeyName, (value) ->
|
||||
{
|
||||
if (method.isDefault())
|
||||
try
|
||||
{
|
||||
return callDefaultMethod(proxy, method, null);
|
||||
value = manager.getConfiguration(value);
|
||||
if (value == null)
|
||||
{
|
||||
if (method.isDefault())
|
||||
{
|
||||
return callDefaultMethod(proxy, method, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert value to return type
|
||||
Class<?> returnType = method.getReturnType();
|
||||
|
||||
try
|
||||
{
|
||||
return ConfigManager.stringToObject(value, returnType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Unable to unmarshal {}.{} ", groupValue, itemKeyName, e);
|
||||
if (method.isDefault())
|
||||
{
|
||||
return callDefaultMethod(proxy, method, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert value to return type
|
||||
Class<?> returnType = method.getReturnType();
|
||||
|
||||
try
|
||||
{
|
||||
return ConfigManager.stringToObject(value, returnType);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e);
|
||||
if (method.isDefault())
|
||||
catch (Throwable throwable)
|
||||
{
|
||||
Object defaultValue = callDefaultMethod(proxy, method, null);
|
||||
|
||||
manager.setConfiguration(group.value(), item.keyName(), defaultValue);
|
||||
|
||||
return defaultValue;
|
||||
log.error("Unable to resolve configuration value {}.{}", groupValue, itemKeyName, throwable);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -103,13 +133,13 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
|
||||
if (args.length != 1)
|
||||
{
|
||||
throw new RuntimeException("Invalid number of arguents to configuration method");
|
||||
throw new RuntimeException("Invalid number of arguments to configuration method");
|
||||
}
|
||||
|
||||
Object newValue = args[0];
|
||||
|
||||
Class<?> type = method.getParameterTypes()[0];
|
||||
Object oldValue = manager.getConfiguration(group.value(), item.keyName(), type);
|
||||
Object oldValue = manager.getConfiguration(groupValue, itemKeyName, type);
|
||||
|
||||
if (Objects.equals(oldValue, newValue))
|
||||
{
|
||||
@@ -124,19 +154,19 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
if (Objects.equals(newValue, defaultValue))
|
||||
{
|
||||
// Just unset if it goes back to the default
|
||||
manager.unsetConfiguration(group.value(), item.keyName());
|
||||
manager.unsetConfiguration(groupValue, itemKeyName);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (newValue == null)
|
||||
{
|
||||
manager.unsetConfiguration(group.value(), item.keyName());
|
||||
manager.unsetConfiguration(groupValue, itemKeyName);
|
||||
}
|
||||
else
|
||||
{
|
||||
String newValueStr = ConfigManager.objectToString(newValue);
|
||||
manager.setConfiguration(group.value(), item.keyName(), newValueStr);
|
||||
manager.setConfiguration(groupValue, itemKeyName, newValueStr);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@@ -81,6 +82,7 @@ public class ConfigManager
|
||||
private final ScheduledExecutorService executor;
|
||||
private final ConfigInvocationHandler handler = new ConfigInvocationHandler(this);
|
||||
private final Properties properties = new Properties();
|
||||
private final Map<String, Object> configObjectCache = new HashMap<>();
|
||||
private final Map<String, String> pendingChanges = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
@@ -220,6 +222,20 @@ public class ConfigManager
|
||||
}
|
||||
}
|
||||
|
||||
// Attempts to fetch the config value from the cache if present. Otherwise it calls the get value function and caches the result
|
||||
Object getConfigObjectFromCacheOrElse(String groupName, String key, Function<String, Object> getValue)
|
||||
{
|
||||
String configItemKey = groupName + "." + key;
|
||||
return configObjectCache.computeIfAbsent(configItemKey, getValue);
|
||||
}
|
||||
|
||||
// Posts the configchanged event to the event bus and remove the changed key from the cache
|
||||
private void postConfigChanged(ConfigChanged configChanged)
|
||||
{
|
||||
configObjectCache.remove(configChanged.getGroup() + "." + configChanged.getKey());
|
||||
eventBus.post(configChanged);
|
||||
}
|
||||
|
||||
public <T> T getConfig(Class<T> clazz)
|
||||
{
|
||||
if (!Modifier.isPublic(clazz.getModifiers()))
|
||||
@@ -245,6 +261,11 @@ public class ConfigManager
|
||||
return properties.getProperty(groupName + "." + key);
|
||||
}
|
||||
|
||||
public String getConfiguration(String propertyKey)
|
||||
{
|
||||
return properties.getProperty(propertyKey);
|
||||
}
|
||||
|
||||
public <T> T getConfiguration(String groupName, String key, Class<T> clazz)
|
||||
{
|
||||
String value = getConfiguration(groupName, key);
|
||||
@@ -284,7 +305,7 @@ public class ConfigManager
|
||||
configChanged.setOldValue(oldValue);
|
||||
configChanged.setNewValue(value);
|
||||
|
||||
eventBus.post(configChanged);
|
||||
postConfigChanged(configChanged);
|
||||
}
|
||||
|
||||
public void setConfiguration(String groupName, String key, Object value)
|
||||
|
||||
@@ -288,7 +288,7 @@ public enum AgilityShortcut
|
||||
GOBLIN_VILLAGE_WALL(14, "Wall", new WorldPoint(2925, 3523, 0), TIGHTGAP),
|
||||
CORSAIR_COVE_DUNGEON_PILLAR(15, "Pillar Jump", new WorldPoint(1980, 8996, 0), PILLAR_31809),
|
||||
EDGEVILLE_DUNGEON_MONKEYBARS(15, "Monkey Bars", null, MONKEYBARS_23566),
|
||||
TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15
|
||||
TROLLHEIM_ROCKS(15, "Rocks", null, new WorldPoint(2838, 3614, 0), ROCKS_3748), // No fixed world map location, but rocks near death plateau have a requirement of 15
|
||||
YANILLE_UNDERWALL_TUNNEL(16, "Underwall Tunnel", new WorldPoint(2574, 3109, 0), HOLE_16520, CASTLE_WALL),
|
||||
YANILLE_WATCHTOWER_TRELLIS(18, "Trellis", null, TRELLIS_20056),
|
||||
COAL_TRUCKS_LOG_BALANCE(20, "Log Balance", new WorldPoint(2598, 3475, 0), LOG_BALANCE_23274),
|
||||
|
||||
@@ -37,33 +37,66 @@ import net.runelite.client.config.ModifierlessKeybind;
|
||||
@ConfigGroup("antiDrag")
|
||||
public interface AntiDragConfig extends Config
|
||||
{
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "dragDelay",
|
||||
name = "Drag Delay",
|
||||
description = "Configures the inventory drag delay in client ticks (20ms)",
|
||||
position = 1
|
||||
position = 0,
|
||||
keyName = "alwaysOn",
|
||||
name = "Always On",
|
||||
description = "Makes the anti-drag always active and disables the hotkey toggle",
|
||||
disabledBy = "keybind",
|
||||
hide = "keybind"
|
||||
)
|
||||
default int dragDelay()
|
||||
default boolean alwaysOn()
|
||||
{
|
||||
return Constants.GAME_TICK_LENGTH / Constants.CLIENT_TICK_LENGTH; // one game tick
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "keybind",
|
||||
name = "keybind",
|
||||
name = "Toggle with Keybind",
|
||||
description = "Toggle anti drag on and off, rather than always on.",
|
||||
disabledBy = "alwaysOn",
|
||||
hide = "alwaysOn"
|
||||
)
|
||||
default boolean keybind()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "key",
|
||||
name = "Keybind",
|
||||
description = "The keybind you want to use for antidrag",
|
||||
position = 2
|
||||
position = 2,
|
||||
hidden = true,
|
||||
unhide = "keybind"
|
||||
)
|
||||
default Keybind key()
|
||||
{
|
||||
return new ModifierlessKeybind(KeyEvent.VK_SHIFT, 0);
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "dragDelay",
|
||||
name = "Drag Delay",
|
||||
description = "Configures the inventory drag delay in client ticks (20ms)",
|
||||
position = 3,
|
||||
hidden = true,
|
||||
unhide = "keybind"
|
||||
)
|
||||
default int dragDelay()
|
||||
{
|
||||
return Constants.GAME_TICK_LENGTH / Constants.CLIENT_TICK_LENGTH; // one game tick
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "reqfocus",
|
||||
name = "Reset on focus loss",
|
||||
description = "Disable antidrag when losing focus (like alt tabbing)",
|
||||
position = 3
|
||||
position = 4,
|
||||
hidden = true,
|
||||
unhide = "keybind"
|
||||
)
|
||||
default boolean reqfocus()
|
||||
{
|
||||
@@ -74,7 +107,9 @@ public interface AntiDragConfig extends Config
|
||||
keyName = "overlay",
|
||||
name = "Enable overlay",
|
||||
description = "Do you really need a description?",
|
||||
position = 4
|
||||
position = 5,
|
||||
hidden = true,
|
||||
unhide = "keybind"
|
||||
)
|
||||
default boolean overlay()
|
||||
{
|
||||
@@ -87,8 +122,8 @@ public interface AntiDragConfig extends Config
|
||||
name = "Overlay color",
|
||||
description = "Change the overlay color, duh",
|
||||
hidden = true,
|
||||
unhide = "overlay",
|
||||
position = 5
|
||||
unhide = "keybind",
|
||||
position = 6
|
||||
)
|
||||
default Color color()
|
||||
{
|
||||
@@ -99,7 +134,9 @@ public interface AntiDragConfig extends Config
|
||||
keyName = "changeCursor",
|
||||
name = "Change Cursor",
|
||||
description = "Change cursor when you have anti-drag enabled.",
|
||||
position = 6
|
||||
position = 7,
|
||||
hidden = true,
|
||||
unhide = "keybind"
|
||||
)
|
||||
default boolean changeCursor()
|
||||
{
|
||||
@@ -111,8 +148,8 @@ public interface AntiDragConfig extends Config
|
||||
name = "Cursor",
|
||||
description = "Select which cursor you wish to use",
|
||||
hidden = true,
|
||||
unhide = "changeCursor",
|
||||
position = 7
|
||||
unhide = "keybind",
|
||||
position = 8
|
||||
)
|
||||
default CustomCursor selectedCursor()
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ package net.runelite.client.plugins.antidrag;
|
||||
import com.google.inject.Provides;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.FocusChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
@@ -51,6 +52,7 @@ import net.runelite.client.util.HotkeyListener;
|
||||
public class AntiDragPlugin extends Plugin
|
||||
{
|
||||
private static final int DEFAULT_DELAY = 5;
|
||||
|
||||
private boolean toggleDrag;
|
||||
|
||||
@Inject
|
||||
@@ -83,9 +85,11 @@ public class AntiDragPlugin extends Plugin
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
keyManager.registerKeyListener(hotkeyListener);
|
||||
toggleDrag = false;
|
||||
|
||||
if (config.keybind())
|
||||
{
|
||||
keyManager.registerKeyListener(hotkeyListener);
|
||||
}
|
||||
client.setInventoryDragDelay(config.alwaysOn() ? config.dragDelay() : DEFAULT_DELAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,46 +101,75 @@ public class AntiDragPlugin extends Plugin
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (event.getGroup().equals("antiDrag"))
|
||||
{
|
||||
if (event.getKey().equals("keybind"))
|
||||
{
|
||||
if (config.keybind())
|
||||
{
|
||||
keyManager.registerKeyListener(hotkeyListener);
|
||||
}
|
||||
else
|
||||
{
|
||||
keyManager.unregisterKeyListener(hotkeyListener);
|
||||
}
|
||||
}
|
||||
if (event.getKey().equals("alwaysOn"))
|
||||
{
|
||||
client.setInventoryDragDelay(config.alwaysOn() ? config.dragDelay() : DEFAULT_DELAY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onFocusChanged(FocusChanged focusChanged)
|
||||
{
|
||||
if (!config.alwaysOn())
|
||||
{
|
||||
if (!focusChanged.isFocused() && config.reqfocus())
|
||||
{
|
||||
client.setInventoryDragDelay(DEFAULT_DELAY);
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final HotkeyListener hotkeyListener = new HotkeyListener(() -> config.key())
|
||||
{
|
||||
@Override
|
||||
public void hotkeyPressed()
|
||||
{
|
||||
toggleDrag = !toggleDrag;
|
||||
if (toggleDrag)
|
||||
if (!config.alwaysOn())
|
||||
{
|
||||
if (config.overlay())
|
||||
toggleDrag = !toggleDrag;
|
||||
if (toggleDrag)
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
}
|
||||
if (config.changeCursor())
|
||||
{
|
||||
CustomCursor selectedCursor = config.selectedCursor();
|
||||
clientUI.setCursor(selectedCursor.getCursorImage(), selectedCursor.toString());
|
||||
}
|
||||
if (config.overlay())
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
}
|
||||
if (config.changeCursor())
|
||||
{
|
||||
CustomCursor selectedCursor = config.selectedCursor();
|
||||
clientUI.setCursor(selectedCursor.getCursorImage(), selectedCursor.toString());
|
||||
}
|
||||
|
||||
client.setInventoryDragDelay(config.dragDelay());
|
||||
}
|
||||
else
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
client.setInventoryDragDelay(DEFAULT_DELAY);
|
||||
if (config.changeCursor())
|
||||
client.setInventoryDragDelay(config.dragDelay());
|
||||
}
|
||||
else
|
||||
{
|
||||
net.runelite.client.plugins.customcursor.CustomCursor selectedCursor = configManager.getConfig(CustomCursorConfig.class).selectedCursor();
|
||||
clientUI.setCursor(selectedCursor.getCursorImage(), selectedCursor.toString());
|
||||
overlayManager.remove(overlay);
|
||||
client.setInventoryDragDelay(DEFAULT_DELAY);
|
||||
if (config.changeCursor())
|
||||
{
|
||||
net.runelite.client.plugins.customcursor.CustomCursor selectedCursor = configManager.getConfig(CustomCursorConfig.class).selectedCursor();
|
||||
clientUI.setCursor(selectedCursor.getCursorImage(), selectedCursor.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Subscribe
|
||||
public void onFocusChanged(FocusChanged focusChanged)
|
||||
{
|
||||
if (!focusChanged.isFocused() && config.reqfocus())
|
||||
{
|
||||
client.setInventoryDragDelay(DEFAULT_DELAY);
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +27,8 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.aoewarnings;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
@@ -38,13 +36,11 @@ import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
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.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
@@ -62,7 +58,7 @@ public class AoeWarningOverlay extends Overlay
|
||||
private final AoeWarningConfig config;
|
||||
|
||||
@Inject
|
||||
public AoeWarningOverlay(@Nullable Client client, AoeWarningPlugin plugin, AoeWarningConfig config)
|
||||
public AoeWarningOverlay(Client client, AoeWarningPlugin plugin, AoeWarningConfig config)
|
||||
{
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.UNDER_WIDGETS);
|
||||
@@ -74,24 +70,25 @@ public class AoeWarningOverlay extends Overlay
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
WorldPoint lp = client.getLocalPlayer().getWorldLocation();
|
||||
for (WorldPoint point : plugin.getLightningTrail())
|
||||
{
|
||||
drawTile(graphics, point, new Color(0, 150, 200), 2, 150, 50);
|
||||
OverlayUtil.drawTile(graphics, client, point, lp, new Color(0, 150, 200), 2, 150, 50);
|
||||
}
|
||||
|
||||
for (WorldPoint point : plugin.getAcidTrail())
|
||||
{
|
||||
drawTile(graphics, point, new Color(69, 241, 44), 2, 150, 50);
|
||||
OverlayUtil.drawTile(graphics, client, point, lp, new Color(69, 241, 44), 2, 150, 50);
|
||||
}
|
||||
|
||||
for (WorldPoint point : plugin.getCrystalSpike())
|
||||
{
|
||||
drawTile(graphics, point, new Color(255, 0, 84), 2, 150, 50);
|
||||
OverlayUtil.drawTile(graphics, client, point, lp, new Color(255, 0, 84), 2, 150, 50);
|
||||
}
|
||||
|
||||
for (WorldPoint point : plugin.getWintertodtSnowFall())
|
||||
{
|
||||
drawTile(graphics, point, new Color(255, 0, 84), 2, 150, 50);
|
||||
OverlayUtil.drawTile(graphics, client, point, lp, new Color(255, 0, 84), 2, 150, 50);
|
||||
}
|
||||
|
||||
Instant now = Instant.now();
|
||||
@@ -164,7 +161,8 @@ public class AoeWarningOverlay extends Overlay
|
||||
{
|
||||
if (tickProgress >= 0)
|
||||
{
|
||||
renderTextLocation(graphics, Integer.toString(tickProgress), config.textSize(), config.fontStyle().getFont(), color, centerPoint(tilePoly.getBounds()));
|
||||
OverlayUtil.renderTextLocation(graphics, Integer.toString(tickProgress), plugin.getTextSize(),
|
||||
plugin.getFontStyle(), color, centerPoint(tilePoly.getBounds()), plugin.isShadows(), 0);
|
||||
}
|
||||
}
|
||||
graphics.setColor(new Color(setAlphaComponent(config.overlayColor().getRGB(), fillAlpha), true));
|
||||
@@ -173,50 +171,6 @@ public class AoeWarningOverlay extends Overlay
|
||||
return null;
|
||||
}
|
||||
|
||||
private void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha)
|
||||
{
|
||||
WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
|
||||
if (point.distanceTo(playerLocation) >= 32)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LocalPoint lp = LocalPoint.fromWorld(client, point);
|
||||
if (lp == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Polygon poly = Perspective.getCanvasTilePoly(client, lp);
|
||||
if (poly == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha));
|
||||
graphics.setStroke(new BasicStroke(strokeWidth));
|
||||
graphics.draw(poly);
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
|
||||
graphics.fill(poly);
|
||||
}
|
||||
|
||||
private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, Point canvasPoint)
|
||||
{
|
||||
graphics.setFont(new Font("Arial", fontStyle, fontSize));
|
||||
if (canvasPoint != null)
|
||||
{
|
||||
final Point canvasCenterPoint = new Point(
|
||||
canvasPoint.getX(),
|
||||
canvasPoint.getY());
|
||||
final Point canvasCenterPoint_shadow = new Point(
|
||||
canvasPoint.getX() + 1,
|
||||
canvasPoint.getY() + 1);
|
||||
if (config.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);
|
||||
|
||||
@@ -41,6 +41,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.GraphicID;
|
||||
import net.runelite.api.GraphicsObject;
|
||||
import net.runelite.api.NullObjectID;
|
||||
import net.runelite.api.ObjectID;
|
||||
@@ -48,6 +49,7 @@ import net.runelite.api.Projectile;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
@@ -72,40 +74,35 @@ import net.runelite.client.ui.overlay.OverlayManager;
|
||||
@Slf4j
|
||||
public class AoeWarningPlugin extends Plugin
|
||||
{
|
||||
|
||||
@Getter
|
||||
private final Map<WorldPoint, CrystalBomb> bombs = new HashMap<>();
|
||||
private final Map<Projectile, AoeProjectile> projectiles = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
public AoeWarningConfig config;
|
||||
|
||||
@Inject
|
||||
private Notifier notifier;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private AoeWarningOverlay coreOverlay;
|
||||
|
||||
@Inject
|
||||
private BombOverlay bombOverlay;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<WorldPoint> LightningTrail = new ArrayList<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<WorldPoint> AcidTrail = new ArrayList<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<WorldPoint> CrystalSpike = new ArrayList<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<WorldPoint> WintertodtSnowFall = new ArrayList<>();
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private boolean shadows;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int textSize;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int fontStyle;
|
||||
|
||||
@Provides
|
||||
AoeWarningConfig getConfig(ConfigManager configManager)
|
||||
@@ -123,10 +120,7 @@ public class AoeWarningPlugin extends Plugin
|
||||
{
|
||||
overlayManager.add(coreOverlay);
|
||||
overlayManager.add(bombOverlay);
|
||||
LightningTrail.clear();
|
||||
AcidTrail.clear();
|
||||
CrystalSpike.clear();
|
||||
WintertodtSnowFall.clear();
|
||||
reset(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -134,10 +128,29 @@ public class AoeWarningPlugin extends Plugin
|
||||
{
|
||||
overlayManager.remove(coreOverlay);
|
||||
overlayManager.remove(bombOverlay);
|
||||
LightningTrail.clear();
|
||||
AcidTrail.clear();
|
||||
CrystalSpike.clear();
|
||||
WintertodtSnowFall.clear();
|
||||
reset(false);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (!event.getGroup().equals("aoe"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.getKey())
|
||||
{
|
||||
case "fontStyle":
|
||||
fontStyle = config.fontStyle().getFont();
|
||||
break;
|
||||
case "textSize":
|
||||
textSize = config.textSize();
|
||||
break;
|
||||
case "shadows":
|
||||
shadows = config.shadows();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -172,12 +185,12 @@ public class AoeWarningPlugin extends Plugin
|
||||
public void onGameObjectSpawned(GameObjectSpawned event)
|
||||
{
|
||||
final GameObject gameObject = event.getGameObject();
|
||||
final WorldPoint bombLocation = gameObject.getWorldLocation();
|
||||
final WorldPoint wp = gameObject.getWorldLocation();
|
||||
|
||||
switch (gameObject.getId())
|
||||
{
|
||||
case ObjectID.CRYSTAL_BOMB:
|
||||
bombs.put(bombLocation, new CrystalBomb(gameObject, client.getTickCount()));
|
||||
bombs.put(wp, new CrystalBomb(gameObject, client.getTickCount()));
|
||||
|
||||
if (config.aoeNotifyAll() || config.bombDisplayNotifyEnabled())
|
||||
{
|
||||
@@ -185,17 +198,16 @@ public class AoeWarningPlugin extends Plugin
|
||||
}
|
||||
break;
|
||||
case ObjectID.ACID_POOL:
|
||||
AcidTrail.add(bombLocation);
|
||||
AcidTrail.add(wp);
|
||||
break;
|
||||
case ObjectID.SMALL_CRYSTALS:
|
||||
//todo
|
||||
CrystalSpike.add(bombLocation);
|
||||
CrystalSpike.add(wp);
|
||||
break;
|
||||
case NullObjectID.NULL_26690:
|
||||
//Wintertodt Snowfall
|
||||
if (config.isWintertodtEnabled())
|
||||
{
|
||||
WintertodtSnowFall.add(bombLocation);
|
||||
WintertodtSnowFall.add(wp);
|
||||
|
||||
if (config.aoeNotifyAll() || config.isWintertodtNotifyEnabled())
|
||||
{
|
||||
@@ -210,25 +222,23 @@ public class AoeWarningPlugin extends Plugin
|
||||
public void onGameObjectDespawned(GameObjectDespawned event)
|
||||
{
|
||||
GameObject gameObject = event.getGameObject();
|
||||
WorldPoint bombLocation = gameObject.getWorldLocation();
|
||||
WorldPoint wp = gameObject.getWorldLocation();
|
||||
switch (gameObject.getId())
|
||||
{
|
||||
case ObjectID.CRYSTAL_BOMB:
|
||||
//might as well check the ObjectID to save some time.
|
||||
purgeBombs(bombs);
|
||||
break;
|
||||
case ObjectID.ACID_POOL:
|
||||
AcidTrail.remove(bombLocation);
|
||||
AcidTrail.remove(wp);
|
||||
break;
|
||||
case ObjectID.SMALL_CRYSTALS:
|
||||
//todo
|
||||
CrystalSpike.remove(bombLocation);
|
||||
CrystalSpike.remove(wp);
|
||||
break;
|
||||
case NullObjectID.NULL_26690:
|
||||
//Wintertodt Snowfall
|
||||
if (config.isWintertodtEnabled())
|
||||
{
|
||||
WintertodtSnowFall.remove(bombLocation);
|
||||
WintertodtSnowFall.remove(wp);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -251,7 +261,7 @@ public class AoeWarningPlugin extends Plugin
|
||||
LightningTrail.clear();
|
||||
for (GraphicsObject o : client.getGraphicsObjects())
|
||||
{
|
||||
if (o.getId() == 1356)
|
||||
if (o.getId() == GraphicID.OLM_LIGHTNING)
|
||||
{
|
||||
LightningTrail.add(WorldPoint.fromLocal(client, o.getLocation()));
|
||||
|
||||
@@ -281,6 +291,12 @@ public class AoeWarningPlugin extends Plugin
|
||||
Map.Entry<WorldPoint, CrystalBomb> entry = it.next();
|
||||
WorldPoint world = entry.getKey();
|
||||
LocalPoint local = LocalPoint.fromWorld(client, world);
|
||||
|
||||
if (local == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Tile tile = tiles[world.getPlane()][local.getSceneX()][local.getSceneY()];
|
||||
GameObject[] objects = tile.getGameObjects();
|
||||
boolean containsObjects = false;
|
||||
@@ -391,4 +407,20 @@ public class AoeWarningPlugin extends Plugin
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void reset(boolean setConfig)
|
||||
{
|
||||
LightningTrail.clear();
|
||||
AcidTrail.clear();
|
||||
CrystalSpike.clear();
|
||||
WintertodtSnowFall.clear();
|
||||
bombs.clear();
|
||||
projectiles.clear();
|
||||
if (setConfig)
|
||||
{
|
||||
fontStyle = config.fontStyle().getFont();
|
||||
textSize = config.textSize();
|
||||
shadows = config.shadows();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,10 @@ public class BombOverlay extends Overlay
|
||||
{
|
||||
final Player localPlayer = client.getLocalPlayer();
|
||||
LocalPoint localLoc = LocalPoint.fromWorld(client, bomb.getWorldLocation());
|
||||
if (localLoc == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
double distance_x = Math.abs(bomb.getWorldLocation().getX() - localPlayer.getWorldLocation().getX());
|
||||
double distance_y = Math.abs(bomb.getWorldLocation().getY() - localPlayer.getWorldLocation().getY());
|
||||
Color color_code = Color.decode(SAFE);
|
||||
@@ -142,7 +146,7 @@ public class BombOverlay extends Overlay
|
||||
{
|
||||
color_code = Color.decode(CAUTION);
|
||||
}
|
||||
LocalPoint CenterPoint = new LocalPoint(localLoc.getX() + 0, localLoc.getY() + 0);
|
||||
LocalPoint CenterPoint = new LocalPoint(localLoc.getX(), localLoc.getY());
|
||||
Polygon poly = Perspective.getCanvasTileAreaPoly(client, CenterPoint, BOMB_AOE);
|
||||
|
||||
if (poly != null)
|
||||
|
||||
@@ -174,7 +174,7 @@ class BarbarianAssaultMenu
|
||||
return config.removeIncorrectCalls() && !hornUpdated;
|
||||
|
||||
default:
|
||||
return config.removeUnusedMenus();
|
||||
return role != null && config.removeUnusedMenus();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -79,11 +79,11 @@ public enum Menus
|
||||
|
||||
ATTACK_PENANCE_QUEEN(null, new ComparableEntry("attack", "penance queen", -1, -1, true, false)),
|
||||
ATTACK_QUEEN_SPAWN(null, new ComparableEntry("attack", "queen spawn", -1, -1, true, false)),
|
||||
DROP_HORN(null, new ComparableEntry("drop", "horn", -1, -1, true, false)),
|
||||
EXAMINE_HORN(null, new ComparableEntry("examine", "horn", -1, -1, true, false)),
|
||||
DROP_HORN(null, new ComparableEntry("drop", "r horn", -1, -1, true, false)),
|
||||
EXAMINE_HORN(null, new ComparableEntry("examine", "r horn", -1, -1, true, false)),
|
||||
LIGHT_LOGS(null, new ComparableEntry("light", "logs", -1, -1, true, true)),
|
||||
MEDIC_HORN(null, new ComparableEntry("medic", "horn", -1, -1, true, false)),
|
||||
USE_HORN(null, new ComparableEntry("use", "horn", -1, -1, true, false));
|
||||
MEDIC_HORN(null, new ComparableEntry("medic", "r horn", -1, -1, true, false)),
|
||||
USE_HORN(null, new ComparableEntry("use", "r horn", -1, -1, true, false));
|
||||
|
||||
@Getter
|
||||
private final Role role;
|
||||
|
||||
@@ -82,11 +82,22 @@ public interface BoostsConfig extends Config
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "boldIconFont",
|
||||
name = "Bold Font for Icons",
|
||||
description = "",
|
||||
position = 5
|
||||
)
|
||||
default boolean boldIconFont()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "displayNextBuffChange",
|
||||
name = "Display next buff change",
|
||||
description = "Configures whether or not to display when the next buffed stat change will be",
|
||||
position = 5
|
||||
position = 6
|
||||
)
|
||||
default DisplayChangeMode displayNextBuffChange()
|
||||
{
|
||||
@@ -97,7 +108,7 @@ public interface BoostsConfig extends Config
|
||||
keyName = "displayNextDebuffChange",
|
||||
name = "Display next debuff change",
|
||||
description = "Configures whether or not to display when the next debuffed stat change will be",
|
||||
position = 6
|
||||
position = 7
|
||||
)
|
||||
default DisplayChangeMode displayNextDebuffChange()
|
||||
{
|
||||
@@ -108,7 +119,7 @@ public interface BoostsConfig extends Config
|
||||
keyName = "boostThreshold",
|
||||
name = "Boost Amount Threshold",
|
||||
description = "The amount of levels boosted to send a notification at. A value of 0 will disable notification.",
|
||||
position = 7
|
||||
position = 8
|
||||
)
|
||||
default int boostThreshold()
|
||||
{
|
||||
@@ -119,7 +130,7 @@ public interface BoostsConfig extends Config
|
||||
keyName = "groupNotifications",
|
||||
name = "Group Notifications",
|
||||
description = "Configures whether or not to group notifications for multiple skills into a single notification",
|
||||
position = 8
|
||||
position = 9
|
||||
)
|
||||
default boolean groupNotifications()
|
||||
{
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.runelite.client.ui.overlay.components.ComponentOrientation;
|
||||
import net.runelite.client.ui.overlay.components.ImageComponent;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
@@ -50,7 +51,12 @@ class CombatIconsOverlay extends Overlay
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if (config.boldIconFont())
|
||||
{
|
||||
graphics.setFont(FontManager.getRunescapeBoldFont());
|
||||
}
|
||||
|
||||
panelComponent.getChildren().clear();
|
||||
panelComponent.setPreferredSize(new Dimension(28, 0));
|
||||
panelComponent.setWrapping(2);
|
||||
|
||||
@@ -110,6 +110,17 @@ public interface ChatCommandsConfig extends Config
|
||||
|
||||
@ConfigItem(
|
||||
position = 7,
|
||||
keyName = "duels",
|
||||
name = "Duels Command",
|
||||
description = "Configures whether the duel arena command is enabled<br> !duels"
|
||||
)
|
||||
default boolean duels()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
keyName = "clearShortcuts",
|
||||
name = "Clear shortcuts",
|
||||
description = "Enable shortcuts (ctrl+w and backspace) for clearing the chatbox"
|
||||
@@ -118,4 +129,4 @@ public interface ChatCommandsConfig extends Config
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,7 @@ import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
import static net.runelite.client.util.Text.sanitize;
|
||||
import net.runelite.http.api.chat.ChatClient;
|
||||
import net.runelite.http.api.chat.Duels;
|
||||
import net.runelite.http.api.hiscore.HiscoreClient;
|
||||
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
||||
import net.runelite.http.api.hiscore.HiscoreResult;
|
||||
@@ -89,6 +90,8 @@ public class ChatCommandsPlugin extends Plugin
|
||||
private static final Pattern BARROWS_PATTERN = Pattern.compile("Your Barrows chest count is: <col=ff0000>(\\d+)</col>");
|
||||
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("Fight duration: <col=ff0000>[0-9:]+</col>. Personal best: ([0-9:]+)");
|
||||
private static final Pattern NEW_PB_PATTERN = Pattern.compile("Fight duration: <col=ff0000>([0-9:]+)</col> \\(new personal best\\)");
|
||||
private static final Pattern DUEL_ARENA_WINS_PATTERN = Pattern.compile("You (were defeated|won)! You have(?: now)? won (\\d+) duels?");
|
||||
private static final Pattern DUEL_ARENA_LOSSES_PATTERN = Pattern.compile("You have(?: now)? lost (\\d+) duels?");
|
||||
private static final String TOTAL_LEVEL_COMMAND_STRING = "!total";
|
||||
private static final String PRICE_COMMAND_STRING = "!price";
|
||||
private static final String LEVEL_COMMAND_STRING = "!lvl";
|
||||
@@ -98,6 +101,7 @@ public class ChatCommandsPlugin extends Plugin
|
||||
private static final String QP_COMMAND_STRING = "!qp";
|
||||
private static final String GC_COMMAND_STRING = "!gc";
|
||||
private static final String PB_COMMAND = "!pb";
|
||||
private static final String DUEL_ARENA_COMMAND = "!duels";
|
||||
|
||||
private final HiscoreClient hiscoreClient = new HiscoreClient();
|
||||
private final ChatClient chatClient = new ChatClient();
|
||||
@@ -148,6 +152,7 @@ public class ChatCommandsPlugin extends Plugin
|
||||
chatCommandManager.registerCommandAsync(QP_COMMAND_STRING, this::questPointsLookup, this::questPointsSubmit);
|
||||
chatCommandManager.registerCommandAsync(GC_COMMAND_STRING, this::gambleCountLookup, this::gambleCountSubmit);
|
||||
chatCommandManager.registerCommandAsync(PB_COMMAND, this::personalBestLookup, this::personalBestSubmit);
|
||||
chatCommandManager.registerCommandAsync(DUEL_ARENA_COMMAND, this::duelArenaLookup, this::duelArenaSubmit);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,6 +171,7 @@ public class ChatCommandsPlugin extends Plugin
|
||||
chatCommandManager.unregisterCommand(QP_COMMAND_STRING);
|
||||
chatCommandManager.unregisterCommand(PB_COMMAND);
|
||||
chatCommandManager.unregisterCommand(GC_COMMAND_STRING);
|
||||
chatCommandManager.unregisterCommand(DUEL_ARENA_COMMAND);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@@ -203,7 +209,9 @@ public class ChatCommandsPlugin extends Plugin
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage chatMessage)
|
||||
{
|
||||
if (chatMessage.getType() != ChatMessageType.GAMEMESSAGE && chatMessage.getType() != ChatMessageType.SPAM)
|
||||
if (chatMessage.getType() != ChatMessageType.TRADE
|
||||
&& chatMessage.getType() != ChatMessageType.GAMEMESSAGE
|
||||
&& chatMessage.getType() != ChatMessageType.SPAM)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -239,6 +247,43 @@ public class ChatCommandsPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
matcher = DUEL_ARENA_WINS_PATTERN.matcher(message);
|
||||
if (matcher.find())
|
||||
{
|
||||
final int oldWins = getKc("Duel Arena Wins");
|
||||
final int wins = Integer.parseInt(matcher.group(2));
|
||||
final String result = matcher.group(1);
|
||||
int winningStreak = getKc("Duel Arena Win Streak");
|
||||
int losingStreak = getKc("Duel Arena Lose Streak");
|
||||
|
||||
if (result.equals("won") && wins > oldWins)
|
||||
{
|
||||
losingStreak = 0;
|
||||
winningStreak += 1;
|
||||
}
|
||||
else if (result.equals("were defeated"))
|
||||
{
|
||||
losingStreak += 1;
|
||||
winningStreak = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.warn("unrecognized duel streak chat message: {}", message);
|
||||
}
|
||||
|
||||
setKc("Duel Arena Wins", wins);
|
||||
setKc("Duel Arena Win Streak", winningStreak);
|
||||
setKc("Duel Arena Lose Streak", losingStreak);
|
||||
}
|
||||
|
||||
matcher = DUEL_ARENA_LOSSES_PATTERN.matcher(message);
|
||||
if (matcher.find())
|
||||
{
|
||||
int losses = Integer.parseInt(matcher.group(1));
|
||||
|
||||
setKc("Duel Arena Losses", losses);
|
||||
}
|
||||
|
||||
matcher = BARROWS_PATTERN.matcher(message);
|
||||
if (matcher.find())
|
||||
{
|
||||
@@ -419,6 +464,96 @@ public class ChatCommandsPlugin extends Plugin
|
||||
client.refreshChat();
|
||||
}
|
||||
|
||||
private boolean duelArenaSubmit(ChatInput chatInput, String value)
|
||||
{
|
||||
final int wins = getKc("Duel Arena Wins");
|
||||
final int losses = getKc("Duel Arena Losses");
|
||||
final int winningStreak = getKc("Duel Arena Win Streak");
|
||||
final int losingStreak = getKc("Duel Arena Lose Streak");
|
||||
|
||||
if (wins <= 0 && losses <= 0 && winningStreak <= 0 && losingStreak <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final String playerName = client.getLocalPlayer().getName();
|
||||
|
||||
executor.execute(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
chatClient.submitDuels(playerName, wins, losses, winningStreak, losingStreak);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
log.warn("unable to submit duels", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
chatInput.resume();
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void duelArenaLookup(ChatMessage chatMessage, String message)
|
||||
{
|
||||
if (!config.duels())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ChatMessageType type = chatMessage.getType();
|
||||
|
||||
final String player;
|
||||
if (type == ChatMessageType.PRIVATECHATOUT)
|
||||
{
|
||||
player = client.getLocalPlayer().getName();
|
||||
}
|
||||
else
|
||||
{
|
||||
player = sanitize(chatMessage.getName());
|
||||
}
|
||||
|
||||
Duels duels;
|
||||
try
|
||||
{
|
||||
duels = chatClient.getDuels(player);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
log.debug("unable to lookup duels", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
final int wins = duels.getWins();
|
||||
final int losses = duels.getLosses();
|
||||
final int winningStreak = duels.getWinningStreak();
|
||||
final int losingStreak = duels.getLosingStreak();
|
||||
|
||||
String response = new ChatMessageBuilder()
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append("Duel Arena wins: ")
|
||||
.append(ChatColorType.HIGHLIGHT)
|
||||
.append(Integer.toString(wins))
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append(" losses: ")
|
||||
.append(ChatColorType.HIGHLIGHT)
|
||||
.append(Integer.toString(losses))
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append(" streak: ")
|
||||
.append(ChatColorType.HIGHLIGHT)
|
||||
.append(Integer.toString((winningStreak != 0 ? winningStreak : -losingStreak)))
|
||||
.build();
|
||||
|
||||
log.debug("Setting response {}", response);
|
||||
final MessageNode messageNode = chatMessage.getMessageNode();
|
||||
messageNode.setRuneLiteFormatMessage(response);
|
||||
chatMessageManager.update(messageNode);
|
||||
client.refreshChat();
|
||||
}
|
||||
|
||||
private void questPointsLookup(ChatMessage chatMessage, String message)
|
||||
{
|
||||
if (!config.qp())
|
||||
@@ -1231,4 +1366,4 @@ public class ChatCommandsPlugin extends Plugin
|
||||
return WordUtils.capitalize(boss);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package net.runelite.client.plugins.chattranslation;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("chattranslation")
|
||||
public interface ChatTranslationConfig extends Config
|
||||
{
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "translateOptionVisable",
|
||||
name = "Show 'Translate' menu option",
|
||||
description = "Adds 'Translate' to the right-click menu in the Chatbox.",
|
||||
position = 0,
|
||||
group = "Public Chat Translation"
|
||||
)
|
||||
default boolean translateOptionVisable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "publicChat",
|
||||
name = "Translate incoming Messages",
|
||||
description = "Would you like to Translate Public Chat?",
|
||||
position = 1,
|
||||
group = "Public Chat Translation",
|
||||
hidden = true,
|
||||
unhide = "translateOptionVisable"
|
||||
)
|
||||
default boolean publicChat()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "playerNames",
|
||||
name = "Translated Player list:",
|
||||
description = "Players you add to this list will be Translated in Public chat.",
|
||||
position = 2,
|
||||
group = "Public Chat Translation",
|
||||
hidden = true,
|
||||
unhide = "translateOptionVisable"
|
||||
)
|
||||
default String getPlayerNames()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "publicTargetLanguage",
|
||||
name = "Target Language",
|
||||
description = "Language to translate messages too.",
|
||||
position = 2,
|
||||
group = "Public Chat Translation",
|
||||
hidden = true,
|
||||
unhide = "publicChat"
|
||||
)
|
||||
default Languages publicTargetLanguage()
|
||||
{
|
||||
return Languages.ENGLISH;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "playerChat",
|
||||
name = "Translate outgoing Messages",
|
||||
description = "Would you like to Translate your Messages?",
|
||||
position = 3,
|
||||
group = "Player Message Translation"
|
||||
)
|
||||
default boolean playerChat()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "playerTargetLanguage",
|
||||
name = "Target Language",
|
||||
description = "Language to translate messages too.",
|
||||
position = 4,
|
||||
group = "Player Message Translation",
|
||||
hidden = true,
|
||||
unhide = "playerChat"
|
||||
)
|
||||
default Languages playerTargetLanguage()
|
||||
{
|
||||
return Languages.SPANISH;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
package net.runelite.client.plugins.chattranslation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
import com.google.inject.Provides;
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.PlayerMenuOptionClicked;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.util.Text;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Chat Translator",
|
||||
description = "Translates messages from one Language to another.",
|
||||
tags = {"translate", "language", "english", "spanish", "dutch", "french"},
|
||||
type = PluginType.UTILITY
|
||||
)
|
||||
public class ChatTranslationPlugin extends Plugin implements KeyListener
|
||||
{
|
||||
|
||||
private static final String TRANSLATE = "Translate";
|
||||
|
||||
private static final ImmutableList<String> AFTER_OPTIONS = ImmutableList.of("Message", "Add ignore", "Remove friend", "Kick");
|
||||
|
||||
private ArrayList<String> playerNames = new ArrayList<>();
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private Provider<MenuManager> menuManager;
|
||||
|
||||
@Inject
|
||||
private ChatMessageManager chatMessageManager;
|
||||
|
||||
@Inject
|
||||
private KeyManager keyManager;
|
||||
|
||||
@Inject
|
||||
private ChatTranslationConfig config;
|
||||
|
||||
@Provides
|
||||
ChatTranslationConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(ChatTranslationConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
if (config.translateOptionVisable())
|
||||
{
|
||||
menuManager.get().addPlayerMenuItem(TRANSLATE);
|
||||
}
|
||||
}
|
||||
keyManager.registerKeyListener(this);
|
||||
|
||||
playerNames.addAll(Text.fromCSV(config.getPlayerNames()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
if (config.translateOptionVisable())
|
||||
{
|
||||
menuManager.get().removePlayerMenuItem(TRANSLATE);
|
||||
}
|
||||
}
|
||||
keyManager.unregisterKeyListener(this);
|
||||
|
||||
playerNames.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (event.getGroup().equals("chattranslation"))
|
||||
{
|
||||
if (event.getKey().equals("playerNames"))
|
||||
{
|
||||
for (String names : Text.fromCSV(config.getPlayerNames()))
|
||||
{
|
||||
if (!playerNames.contains(Text.toJagexName(names)))
|
||||
{
|
||||
playerNames.add(Text.toJagexName(names));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
if (!config.translateOptionVisable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int groupId = WidgetInfo.TO_GROUP(event.getActionParam1());
|
||||
String option = event.getOption();
|
||||
|
||||
if (groupId == WidgetInfo.CHATBOX.getGroupId())
|
||||
{
|
||||
boolean after;
|
||||
|
||||
if (!AFTER_OPTIONS.contains(option))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final MenuEntry menuEntry = new MenuEntry();
|
||||
menuEntry.setOption(TRANSLATE);
|
||||
menuEntry.setTarget(event.getTarget());
|
||||
menuEntry.setType(MenuAction.RUNELITE.getId());
|
||||
menuEntry.setParam0(event.getActionParam0());
|
||||
menuEntry.setParam1(event.getActionParam1());
|
||||
menuEntry.setIdentifier(event.getIdentifier());
|
||||
|
||||
MenuEntry[] newMenu = ObjectArrays.concat(menuEntry, client.getMenuEntries());
|
||||
int menuEntryCount = newMenu.length;
|
||||
ArrayUtils.swap(newMenu, menuEntryCount - 1, menuEntryCount - 2);
|
||||
client.setMenuEntries(newMenu);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerMenuOptionClicked(PlayerMenuOptionClicked event)
|
||||
{
|
||||
if (event.getMenuOption().equals(TRANSLATE))
|
||||
{
|
||||
String name = Text.toJagexName(event.getMenuTarget());
|
||||
if (!playerNames.contains(name))
|
||||
{
|
||||
playerNames.add(name);
|
||||
}
|
||||
|
||||
configManager.setConfiguration("chattranslation", "playerNames", Text.toCSV(playerNames));
|
||||
configManager.sendConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage chatMessage)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOADING && client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
switch (chatMessage.getType())
|
||||
{
|
||||
case PUBLICCHAT:
|
||||
case MODCHAT:
|
||||
if (!config.publicChat())
|
||||
{
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (String nameList : playerNames)
|
||||
{
|
||||
if (nameList.contains(Text.toJagexName(chatMessage.getName())))
|
||||
{
|
||||
String message = chatMessage.getMessage();
|
||||
|
||||
Translator translator = new Translator();
|
||||
|
||||
try
|
||||
{
|
||||
//Automatically check language of message and translate to selected language.
|
||||
String translation = translator.translate("auto", config.publicTargetLanguage().toString(), message);
|
||||
if (translation != null)
|
||||
{
|
||||
final MessageNode messageNode = chatMessage.getMessageNode();
|
||||
messageNode.setRuneLiteFormatMessage(translation);
|
||||
chatMessageManager.update(messageNode);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
client.refreshChat();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent event)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOADING && client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!config.playerChat())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widget chatboxParent = client.getWidget(WidgetInfo.CHATBOX_PARENT);
|
||||
|
||||
if (chatboxParent != null && chatboxParent.getOnKeyListener() != null)
|
||||
{
|
||||
if (event.getKeyCode() == 0xA)
|
||||
{
|
||||
event.consume();
|
||||
|
||||
Translator translator = new Translator();
|
||||
String message = client.getVar(VarClientStr.CHATBOX_TYPED_TEXT);
|
||||
|
||||
try
|
||||
{
|
||||
//Automatically check language of message and translate to selected language.
|
||||
String translation = translator.translate("auto", config.playerTargetLanguage().toString(), message);
|
||||
if (translation != null)
|
||||
{
|
||||
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, translation);
|
||||
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
client.runScript(96, 0, translation);
|
||||
});
|
||||
}
|
||||
client.setVar(VarClientStr.CHATBOX_TYPED_TEXT, "");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e)
|
||||
{
|
||||
// Nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e)
|
||||
{
|
||||
// Nothing.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.runelite.client.plugins.chattranslation;
|
||||
|
||||
public enum Languages
|
||||
{
|
||||
|
||||
ENGLISH("en"),
|
||||
DUTCH("nl"),
|
||||
SPANISH("es"),
|
||||
FRENCH("fr");
|
||||
|
||||
private final String shortName;
|
||||
|
||||
Languages(String shortName)
|
||||
{
|
||||
this.shortName = shortName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return shortName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.runelite.client.plugins.chattranslation;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
public class Translator
|
||||
{
|
||||
|
||||
public String translate(String source, String target, String message) throws Exception
|
||||
{
|
||||
|
||||
String url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=" + source + "&tl=" + target + "&dt=t&q=" + URLEncoder.encode(message, "UTF-8");
|
||||
|
||||
URL obj = new URL(url);
|
||||
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||
con.setRequestProperty("User-Agent", "Mozilla/5.0");
|
||||
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null)
|
||||
{
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
return parseResult(response.toString());
|
||||
}
|
||||
|
||||
private String parseResult(String inputJson) throws Exception
|
||||
{
|
||||
//TODO: find a way to do this using google.gson
|
||||
JSONArray jsonArray = new JSONArray(inputJson);
|
||||
JSONArray jsonArray2 = (JSONArray) jsonArray.get(0);
|
||||
JSONArray jsonArray3 = (JSONArray) jsonArray2.get(0);
|
||||
|
||||
return jsonArray3.get(0).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -80,7 +80,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new CrypticClue("Speak to the bartender of the Blue Moon Inn in Varrock.", "Bartender", new WorldPoint(3226, 3399, 0), "Talk to the bartender in Blue Moon Inn in Varrock."),
|
||||
new CrypticClue("This aviator is at the peak of his profession.", "Captain Bleemadge", new WorldPoint(2846, 1749, 0), "Captain Bleemadge, the gnome glider pilot, is found at the top of White Wolf Mountain."),
|
||||
new CrypticClue("Search the crates in the shed just north of East Ardougne.", CRATE_355, new WorldPoint(2617, 3347, 0), "The crates in the shed north of the northern Ardougne bank."),
|
||||
new CrypticClue("I wouldn't wear this jean on my legs.", "Father Jean", new WorldPoint(1697, 3574, 0), "Talk to father Jean in the Hosidius church"),
|
||||
new CrypticClue("I wouldn't wear this jean on my legs.", "Father Jean", new WorldPoint(1734, 3576, 0), "Talk to father Jean in the Hosidius church"),
|
||||
new CrypticClue("Search the crate in the Toad and Chicken pub.", CRATE_354, new WorldPoint(2913, 3536, 0), "The Toad and Chicken pub is located in Burthorpe."),
|
||||
new CrypticClue("Search chests found in the upstairs of shops in Port Sarim.", CLOSED_CHEST_375, new WorldPoint(3016, 3205, 1), "Search the chest in the upstairs of Wydin's Food Store, on the east wall."),
|
||||
new CrypticClue("Right on the blessed border, cursed by the evil ones. On the spot inaccessible by both; I will be waiting. The bugs' imminent possession holds the answer.", new WorldPoint(3410, 3324, 0), "B I P. Dig right under the fairy ring."),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Eadgars Ruse <https://github.com/Eadgars-Ruse>
|
||||
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,21 +25,19 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.cluescrolls.clues;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
@@ -47,35 +46,45 @@ import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin;
|
||||
import static net.runelite.client.plugins.cluescrolls.ClueScrollWorldOverlay.IMAGE_Z_OFFSET;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdArea;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdLocation;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdSolver;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdTemperature;
|
||||
import net.runelite.client.plugins.cluescrolls.clues.hotcold.HotColdTemperatureChange;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
import net.runelite.client.ui.overlay.components.LineComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
|
||||
@EqualsAndHashCode(callSuper = false, exclude = { "hotColdSolver", "location" })
|
||||
@Getter
|
||||
@Slf4j
|
||||
public class HotColdClue extends ClueScroll implements LocationClueScroll, LocationsClueScroll, TextClueScroll, NpcClueScroll
|
||||
{
|
||||
private static final Pattern INITIAL_STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is (.*)");
|
||||
private static final Pattern STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is (.*), (.*) last time\\.");
|
||||
private static final Pattern FINAL_STRANGE_DEVICE_MESSAGE = Pattern.compile("The device is visibly shaking.*");
|
||||
private static final HotColdClue CLUE =
|
||||
new HotColdClue("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Jorral may have a clue.",
|
||||
"Jorral",
|
||||
"Speak to Jorral to receive a strange device.");
|
||||
private static final int HOT_COLD_PANEL_WIDTH = 200;
|
||||
private static final HotColdClue BEGINNER_CLUE = new HotColdClue("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Reldo may have a clue.",
|
||||
"Reldo",
|
||||
"Speak to Reldo to receive a strange device.");
|
||||
private static final HotColdClue MASTER_CLUE = new HotColdClue("Buried beneath the ground, who knows where it's found. Lucky for you, A man called Jorral may have a clue.",
|
||||
"Jorral",
|
||||
"Speak to Jorral to receive a strange device.");
|
||||
|
||||
// list of potential places to dig
|
||||
private List<HotColdLocation> digLocations = new ArrayList<>();
|
||||
private final String text;
|
||||
private final String npc;
|
||||
private final String solution;
|
||||
@Nullable
|
||||
private HotColdSolver hotColdSolver;
|
||||
private WorldPoint location;
|
||||
private WorldPoint lastWorldPoint;
|
||||
|
||||
public static HotColdClue forText(String text)
|
||||
{
|
||||
if (CLUE.text.equalsIgnoreCase(text))
|
||||
if (BEGINNER_CLUE.text.equalsIgnoreCase(text))
|
||||
{
|
||||
return CLUE;
|
||||
BEGINNER_CLUE.reset();
|
||||
return BEGINNER_CLUE;
|
||||
}
|
||||
else if (MASTER_CLUE.text.equalsIgnoreCase(text))
|
||||
{
|
||||
MASTER_CLUE.reset();
|
||||
return MASTER_CLUE;
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -87,24 +96,35 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
|
||||
this.npc = npc;
|
||||
this.solution = solution;
|
||||
setRequiresSpade(true);
|
||||
initializeSolver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldPoint[] getLocations()
|
||||
{
|
||||
return Lists.transform(digLocations, HotColdLocation::getWorldPoint).toArray(new WorldPoint[0]);
|
||||
if (hotColdSolver == null)
|
||||
{
|
||||
return new WorldPoint[0];
|
||||
}
|
||||
|
||||
return hotColdSolver.getPossibleLocations().stream().map(HotColdLocation::getWorldPoint).toArray(WorldPoint[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeOverlayHint(PanelComponent panelComponent, ClueScrollPlugin plugin)
|
||||
{
|
||||
if (hotColdSolver == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text("Hot/Cold Clue")
|
||||
.build());
|
||||
panelComponent.setPreferredSize(new Dimension(200, 0));
|
||||
panelComponent.setPreferredSize(new Dimension(HOT_COLD_PANEL_WIDTH, 0));
|
||||
|
||||
// strange device has not been tested yet, show how to get it
|
||||
if (lastWorldPoint == null && location == null)
|
||||
if (hotColdSolver.getLastWorldPoint() == null && location == null)
|
||||
{
|
||||
if (getNpc() != null)
|
||||
{
|
||||
@@ -131,7 +151,9 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Possible areas:")
|
||||
.build());
|
||||
Map<HotColdArea, Integer> locationCounts = new HashMap<>();
|
||||
|
||||
final Map<HotColdArea, Integer> locationCounts = new EnumMap<>(HotColdArea.class);
|
||||
final Collection<HotColdLocation> digLocations = hotColdSolver.getPossibleLocations();
|
||||
|
||||
for (HotColdLocation hotColdLocation : digLocations)
|
||||
{
|
||||
@@ -159,17 +181,16 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
|
||||
}
|
||||
else
|
||||
{
|
||||
for (HotColdArea s : locationCounts.keySet())
|
||||
for (HotColdArea area : locationCounts.keySet())
|
||||
{
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left(s.getName() + ":")
|
||||
.left(area.getName() + ':')
|
||||
.build());
|
||||
|
||||
for (HotColdLocation hotColdLocation : digLocations)
|
||||
{
|
||||
if (hotColdLocation.getHotColdArea() == s)
|
||||
if (hotColdLocation.getHotColdArea() == area)
|
||||
{
|
||||
Rectangle2D r = hotColdLocation.getRect();
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("- " + hotColdLocation.getArea())
|
||||
.leftColor(Color.LIGHT_GRAY)
|
||||
@@ -184,8 +205,13 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
|
||||
@Override
|
||||
public void makeWorldOverlayHint(Graphics2D graphics, ClueScrollPlugin plugin)
|
||||
{
|
||||
if (hotColdSolver == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// when final location has been found
|
||||
if (this.location != null)
|
||||
if (location != null)
|
||||
{
|
||||
LocalPoint localLocation = LocalPoint.fromWorld(plugin.getClient(), getLocation());
|
||||
|
||||
@@ -197,20 +223,17 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
|
||||
return;
|
||||
}
|
||||
|
||||
// when strange device hasn't been activated yet, show Jorral
|
||||
if (lastWorldPoint == null)
|
||||
// when strange device hasn't been activated yet, show npc who gives you the strange device
|
||||
if (hotColdSolver.getLastWorldPoint() == null && plugin.getNpcsToMark() != null)
|
||||
{
|
||||
// Mark NPC
|
||||
if (plugin.getNpcsToMark() != null)
|
||||
for (NPC npcToMark : plugin.getNpcsToMark())
|
||||
{
|
||||
for (NPC npc : plugin.getNpcsToMark())
|
||||
{
|
||||
OverlayUtil.renderActorOverlayImage(graphics, npc, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET);
|
||||
}
|
||||
OverlayUtil.renderActorOverlayImage(graphics, npcToMark, plugin.getClueScrollImage(), Color.ORANGE, IMAGE_Z_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
// once the number of possible dig locations is below 10, show the dig spots
|
||||
final Collection<HotColdLocation> digLocations = hotColdSolver.getPossibleLocations();
|
||||
if (digLocations.size() < 10)
|
||||
{
|
||||
// Mark potential dig locations
|
||||
@@ -231,171 +254,87 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
|
||||
|
||||
public boolean update(final String message, final ClueScrollPlugin plugin)
|
||||
{
|
||||
if (!message.startsWith("The device is"))
|
||||
if (hotColdSolver == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Matcher m1 = FINAL_STRANGE_DEVICE_MESSAGE.matcher(message);
|
||||
Matcher m2 = STRANGE_DEVICE_MESSAGE.matcher(message);
|
||||
Matcher m3 = INITIAL_STRANGE_DEVICE_MESSAGE.matcher(message);
|
||||
final Set<HotColdTemperature> temperatureSet;
|
||||
|
||||
// the order that these pattern matchers are checked is important
|
||||
if (m1.find())
|
||||
if (this.equals(BEGINNER_CLUE))
|
||||
{
|
||||
// final location for hot cold clue has been found
|
||||
WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation();
|
||||
|
||||
if (localWorld != null)
|
||||
{
|
||||
markFinalSpot(localWorld);
|
||||
return true;
|
||||
}
|
||||
temperatureSet = HotColdTemperature.BEGINNER_HOT_COLD_TEMPERATURES;
|
||||
}
|
||||
else if (m2.find())
|
||||
else if (this.equals(MASTER_CLUE))
|
||||
{
|
||||
String temperature = m2.group(1);
|
||||
String difference = m2.group(2);
|
||||
WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation();
|
||||
|
||||
if (localWorld != null)
|
||||
{
|
||||
updatePossibleArea(localWorld, temperature, difference);
|
||||
return true;
|
||||
}
|
||||
temperatureSet = HotColdTemperature.MASTER_HOT_COLD_TEMPERATURES;
|
||||
}
|
||||
else if (m3.find())
|
||||
else
|
||||
{
|
||||
String temperature = m3.group(1);
|
||||
WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation();
|
||||
|
||||
if (localWorld != null)
|
||||
{
|
||||
updatePossibleArea(localWorld, temperature, "");
|
||||
return true;
|
||||
}
|
||||
temperatureSet = null;
|
||||
}
|
||||
|
||||
return false;
|
||||
final HotColdTemperature temperature = HotColdTemperature.getFromTemperatureSet(temperatureSet, message);
|
||||
|
||||
if (temperature == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final WorldPoint localWorld = plugin.getClient().getLocalPlayer().getWorldLocation();
|
||||
|
||||
if (localWorld == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((this.equals(BEGINNER_CLUE) && temperature == HotColdTemperature.BEGINNER_VISIBLY_SHAKING)
|
||||
|| (this.equals(MASTER_CLUE) && temperature == HotColdTemperature.MASTER_VISIBLY_SHAKING))
|
||||
{
|
||||
markFinalSpot(localWorld);
|
||||
}
|
||||
else
|
||||
{
|
||||
location = null;
|
||||
|
||||
final HotColdTemperatureChange temperatureChange = HotColdTemperatureChange.of(message);
|
||||
hotColdSolver.signal(localWorld, temperature, temperatureChange);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
this.lastWorldPoint = null;
|
||||
digLocations.clear();
|
||||
initializeSolver();
|
||||
}
|
||||
|
||||
private void updatePossibleArea(WorldPoint currentWp, String temperature, String difference)
|
||||
private void initializeSolver()
|
||||
{
|
||||
this.location = null;
|
||||
final boolean isBeginner;
|
||||
|
||||
if (digLocations.isEmpty())
|
||||
if (this.equals(BEGINNER_CLUE))
|
||||
{
|
||||
digLocations.addAll(Arrays.asList(HotColdLocation.values()));
|
||||
isBeginner = true;
|
||||
}
|
||||
else if (this.equals(MASTER_CLUE))
|
||||
{
|
||||
isBeginner = false;
|
||||
}
|
||||
|
||||
int maxSquaresAway = 5000;
|
||||
int minSquaresAway = 0;
|
||||
|
||||
switch (temperature)
|
||||
else
|
||||
{
|
||||
// when the strange device reads a temperature, that means that the center of the final dig location
|
||||
// is a range of squares away from the player's current location (Chebyshev AKA Chess-board distance)
|
||||
case "ice cold":
|
||||
maxSquaresAway = 5000;
|
||||
minSquaresAway = 500;
|
||||
break;
|
||||
case "very cold":
|
||||
maxSquaresAway = 499;
|
||||
minSquaresAway = 200;
|
||||
break;
|
||||
case "cold":
|
||||
maxSquaresAway = 199;
|
||||
minSquaresAway = 150;
|
||||
break;
|
||||
case "warm":
|
||||
maxSquaresAway = 149;
|
||||
minSquaresAway = 100;
|
||||
break;
|
||||
case "hot":
|
||||
maxSquaresAway = 99;
|
||||
minSquaresAway = 70;
|
||||
break;
|
||||
case "very hot":
|
||||
maxSquaresAway = 69;
|
||||
minSquaresAway = 30;
|
||||
break;
|
||||
case "incredibly hot":
|
||||
maxSquaresAway = 29;
|
||||
minSquaresAway = 5;
|
||||
break;
|
||||
log.warn("Hot cold solver could not be initialized, clue type is unknown; text: {}, npc: {}, solution: {}",
|
||||
text, npc, solution);
|
||||
hotColdSolver = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// rectangle r1 encompasses all of the points that are within the max possible distance from the player
|
||||
Point p1 = new Point(currentWp.getX() - maxSquaresAway, currentWp.getY() - maxSquaresAway);
|
||||
Rectangle r1 = new Rectangle((int) p1.getX(), (int) p1.getY(), 2 * maxSquaresAway + 1, 2 * maxSquaresAway + 1);
|
||||
// rectangle r2 encompasses all of the points that are within the min possible distance from the player
|
||||
Point p2 = new Point(currentWp.getX() - minSquaresAway, currentWp.getY() - minSquaresAway);
|
||||
Rectangle r2 = new Rectangle((int) p2.getX(), (int) p2.getY(), 2 * minSquaresAway + 1, 2 * minSquaresAway + 1);
|
||||
|
||||
// eliminate from consideration dig spots that lie entirely within the min range or entirely outside of the max range
|
||||
digLocations.removeIf(entry -> r2.contains(entry.getRect()) || !r1.intersects(entry.getRect()));
|
||||
|
||||
// if a previous world point has been recorded, we can consider the warmer/colder result from the strange device
|
||||
if (lastWorldPoint != null)
|
||||
{
|
||||
switch (difference)
|
||||
{
|
||||
case "but colder than":
|
||||
// eliminate spots that are absolutely warmer
|
||||
digLocations.removeIf(entry -> isFirstPointCloserRect(currentWp, lastWorldPoint, entry.getRect()));
|
||||
break;
|
||||
case "and warmer than":
|
||||
// eliminate spots that are absolutely colder
|
||||
digLocations.removeIf(entry -> isFirstPointCloserRect(lastWorldPoint, currentWp, entry.getRect()));
|
||||
break;
|
||||
case "and the same temperature as":
|
||||
// I couldn't figure out a clean implementation for this case
|
||||
// not necessary for quickly determining final location
|
||||
}
|
||||
}
|
||||
|
||||
lastWorldPoint = currentWp;
|
||||
}
|
||||
|
||||
private boolean isFirstPointCloserRect(WorldPoint firstWp, WorldPoint secondWp, Rectangle2D r)
|
||||
{
|
||||
WorldPoint p1 = new WorldPoint((int) r.getMaxX(), (int) r.getMaxY(), 0);
|
||||
|
||||
if (!isFirstPointCloser(firstWp, secondWp, p1))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WorldPoint p2 = new WorldPoint((int) r.getMaxX(), (int) r.getMinY(), 0);
|
||||
|
||||
if (!isFirstPointCloser(firstWp, secondWp, p2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WorldPoint p3 = new WorldPoint((int) r.getMinX(), (int) r.getMaxY(), 0);
|
||||
|
||||
if (!isFirstPointCloser(firstWp, secondWp, p3))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
WorldPoint p4 = new WorldPoint((int) r.getMinX(), (int) r.getMinY(), 0);
|
||||
return (isFirstPointCloser(firstWp, secondWp, p4));
|
||||
}
|
||||
|
||||
private boolean isFirstPointCloser(WorldPoint firstWp, WorldPoint secondWp, WorldPoint wp)
|
||||
{
|
||||
int firstDistance = firstWp.distanceTo2D(wp);
|
||||
int secondDistance = secondWp.distanceTo2D(wp);
|
||||
return (firstDistance < secondDistance);
|
||||
final Set<HotColdLocation> locations = Arrays.stream(HotColdLocation.values())
|
||||
.filter(l -> l.isBeginnerClue() == isBeginner)
|
||||
.collect(Collectors.toSet());
|
||||
hotColdSolver = new HotColdSolver(locations);
|
||||
}
|
||||
|
||||
private void markFinalSpot(WorldPoint wp)
|
||||
@@ -408,4 +347,4 @@ public class HotColdClue extends ClueScroll implements LocationClueScroll, Locat
|
||||
{
|
||||
return new String[]{npc};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Eadgars Ruse <https://github.com/Eadgars-Ruse>
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,7 +27,6 @@
|
||||
package net.runelite.client.plugins.cluescrolls.clues.hotcold;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
@@ -69,6 +69,8 @@ public enum HotColdLocation
|
||||
DESERT_POLLNIVNEACH(new WorldPoint(3287, 2975, 0), DESERT, "West of Pollnivneach."),
|
||||
DESERT_MTA(new WorldPoint(3350, 3293, 0), DESERT, "Next to Mage Training Arena."),
|
||||
DESERT_SHANTY(new WorldPoint(3294, 3106, 0), DESERT, "South-west of Shantay Pass."),
|
||||
DRAYNOR_MANOR_MUSHROOMS(true, new WorldPoint(3096, 3379, 0), MISTHALIN, "Patch of mushrooms just northwest of Draynor Manor"),
|
||||
DRAYNOR_WHEAT_FIELD(true, new WorldPoint(3120, 3282, 0), MISTHALIN, "Inside the wheat field next to Draynor Village"),
|
||||
FELDIP_HILLS_JIGGIG(new WorldPoint(2413, 3055, 0), FELDIP_HILLS, "West of Jiggig, east of the fairy ring bkp."),
|
||||
FELDIP_HILLS_SW(new WorldPoint(2582, 2895, 0), FELDIP_HILLS, "West of the southeasternmost lake in Feldip Hills."),
|
||||
FELDIP_HILLS_GNOME_GLITER(new WorldPoint(2553, 2972, 0), FELDIP_HILLS, "East of the gnome glider (Lemantolly Undri)."),
|
||||
@@ -91,6 +93,7 @@ public enum HotColdLocation
|
||||
FREMENNIK_PROVINCE_ASTRAL_ALTER(new WorldPoint(2147, 3862, 0), FREMENNIK_PROVINCE, "Astral altar"),
|
||||
FREMENNIK_PROVINCE_LUNAR_VILLAGE(new WorldPoint(2087, 3915, 0), FREMENNIK_PROVINCE, "Lunar Isle, inside the village."),
|
||||
FREMENNIK_PROVINCE_LUNAR_NORTH(new WorldPoint(2106, 3949, 0), FREMENNIK_PROVINCE, "Lunar Isle, north of the village."),
|
||||
ICE_MOUNTAIN(true, new WorldPoint(3007, 3475, 0), MISTHALIN, "Atop Ice Mountain"),
|
||||
KANDARIN_SINCLAR_MANSION(new WorldPoint(2726, 3588, 0), KANDARIN, "North-west of the Sinclair Mansion, near the log balance shortcut."),
|
||||
KANDARIN_CATHERBY(new WorldPoint(2774, 3433, 0), KANDARIN, "Catherby, between the bank and the beehives, near small rock formation."),
|
||||
KANDARIN_GRAND_TREE(new WorldPoint(2444, 3503, 0), KANDARIN, "Grand Tree, just east of the terrorchick gnome enclosure."),
|
||||
@@ -115,6 +118,7 @@ public enum HotColdLocation
|
||||
KARAMJA_KHARAZI_NE(new WorldPoint(2904, 2925, 0), KARAMJA, "North-eastern part of Kharazi Jungle."),
|
||||
KARAMJA_KHARAZI_SW(new WorldPoint(2783, 2898, 0), KARAMJA, "South-western part of Kharazi Jungle."),
|
||||
KARAMJA_CRASH_ISLAND(new WorldPoint(2910, 2737, 0), KARAMJA, "Northern part of Crash Island."),
|
||||
LUMBRIDGE_COW_FIELD(true, new WorldPoint(3174, 3336, 0), MISTHALIN, "Cow field north of Lumbridge"),
|
||||
MISTHALIN_VARROCK_STONE_CIRCLE(new WorldPoint(3225, 3355, 0), MISTHALIN, "South of the stone circle near Varrock's entrance."),
|
||||
MISTHALIN_LUMBRIDGE(new WorldPoint(3238, 3169, 0), MISTHALIN, "Just north-west of the Lumbridge Fishing tutor."),
|
||||
MISTHALIN_LUMBRIDGE_2(new WorldPoint(3170, 3278, 0), MISTHALIN, "North of the pond between Lumbridge and Draynor Village."),
|
||||
@@ -131,6 +135,7 @@ public enum HotColdLocation
|
||||
MORYTANIA_MOS_LES_HARMLESS_BAR(new WorldPoint(3670, 2974, 0), MORYTANIA, "Near Mos Le'Harmless southern bar."),
|
||||
MORYTANIA_DRAGONTOOTH_NORTH(new WorldPoint(3813, 3567, 0), MORYTANIA, "Northern part of Dragontooth Island."),
|
||||
MORYTANIA_DRAGONTOOTH_SOUTH(new WorldPoint(3803, 3532, 0), MORYTANIA, "Southern part of Dragontooth Island."),
|
||||
NORTHEAST_OF_AL_KHARID_MINE(true, new WorldPoint(3332, 3313, 0), MISTHALIN, "Northeast of Al Kharid Mine"),
|
||||
WESTERN_PROVINCE_EAGLES_PEAK(new WorldPoint(2297, 3530, 0), WESTERN_PROVINCE, "North-west of Eagles' Peak."),
|
||||
WESTERN_PROVINCE_PISCATORIS(new WorldPoint(2337, 3689, 0), WESTERN_PROVINCE, "Piscatoris Fishing Colony"),
|
||||
WESTERN_PROVINCE_PISCATORIS_HUNTER_AREA(new WorldPoint(2361, 3566, 0), WESTERN_PROVINCE, "Eastern part of Piscatoris Hunter area, south-west of the Falconry."),
|
||||
@@ -176,12 +181,20 @@ public enum HotColdLocation
|
||||
ZEAH_DAIRY_COW(new WorldPoint(1320, 3718, 0), ZEAH, "North-east of the Kebos Lowlands, east of the dairy cow."),
|
||||
ZEAH_CRIMSON_SWIFTS(new WorldPoint(1186, 3583, 0), ZEAH, "South-west of the Kebos Swamp, below the crimson swifts.");
|
||||
|
||||
private final boolean beginnerClue;
|
||||
private final WorldPoint worldPoint;
|
||||
private final HotColdArea hotColdArea;
|
||||
private final String area;
|
||||
|
||||
public Rectangle2D getRect()
|
||||
HotColdLocation(WorldPoint worldPoint, HotColdArea hotColdArea, String areaDescription)
|
||||
{
|
||||
return new Rectangle(worldPoint.getX() - 4, worldPoint.getY() - 4, 9, 9);
|
||||
this(false, worldPoint, hotColdArea, areaDescription);
|
||||
}
|
||||
|
||||
public Rectangle getRect()
|
||||
{
|
||||
final int digRadius = beginnerClue ? HotColdTemperature.BEGINNER_VISIBLY_SHAKING.getMaxDistance() :
|
||||
HotColdTemperature.MASTER_VISIBLY_SHAKING.getMaxDistance();
|
||||
return new Rectangle(worldPoint.getX() - digRadius, worldPoint.getY() - digRadius, digRadius * 2 + 1, digRadius * 2 + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Eadgars Ruse <https://github.com/Eadgars-Ruse>
|
||||
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.cluescrolls.clues.hotcold;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
|
||||
/**
|
||||
* Solution finder for hot-cold style puzzles.
|
||||
* <p>
|
||||
* These puzzles are established by having some way to test the distance from the solution via "warmth", where being
|
||||
* colder means one is farther away from the target, and being warmer means one is closer to it, with the goal being to
|
||||
* reach the most warm value to discover the solution point. Hot-cold puzzles in Old School Runescape are implemented
|
||||
* with specific set of solution points, so this solver will filter from a provided set of possible solutions as new
|
||||
* signals of temperatures and temperature changes are provided.
|
||||
*/
|
||||
@Getter
|
||||
public class HotColdSolver
|
||||
{
|
||||
private final Set<HotColdLocation> possibleLocations;
|
||||
@Nullable
|
||||
private WorldPoint lastWorldPoint;
|
||||
|
||||
public HotColdSolver(Set<HotColdLocation> possibleLocations)
|
||||
{
|
||||
this.possibleLocations = possibleLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a hot-cold update given a {@link WorldPoint} where a check occurred and the resulting temperature and
|
||||
* temperature change discovered at that point. This will filter the set of possible locations which can be the
|
||||
* solution.
|
||||
*
|
||||
* @param worldPoint The point where a hot-cold check occurred
|
||||
* @param temperature The temperature of the checked point
|
||||
* @param temperatureChange The change of temperature of the checked point compared to the previously-checked point
|
||||
* @return A set of {@link HotColdLocation}s which are still possible after the filtering occurs. This return value
|
||||
* is the same as would be returned by {@code getPossibleLocations()}.
|
||||
*/
|
||||
public Set<HotColdLocation> signal(@Nonnull final WorldPoint worldPoint, @Nonnull final HotColdTemperature temperature, @Nullable final HotColdTemperatureChange temperatureChange)
|
||||
{
|
||||
// when the strange device reads a temperature, that means that the center of the final dig location
|
||||
// is a range of squares away from the player's current location (Chebyshev AKA Chess-board distance)
|
||||
int maxSquaresAway = temperature.getMaxDistance();
|
||||
int minSquaresAway = temperature.getMinDistance();
|
||||
|
||||
// maxDistanceArea encompasses all of the points that are within the max possible distance from the player
|
||||
final Rectangle maxDistanceArea = new Rectangle(
|
||||
worldPoint.getX() - maxSquaresAway,
|
||||
worldPoint.getY() - maxSquaresAway,
|
||||
2 * maxSquaresAway + 1,
|
||||
2 * maxSquaresAway + 1);
|
||||
// minDistanceArea encompasses all of the points that are within the min possible distance from the player
|
||||
final Rectangle minDistanceArea = new Rectangle(
|
||||
worldPoint.getX() - minSquaresAway,
|
||||
worldPoint.getY() - minSquaresAway,
|
||||
2 * minSquaresAway + 1,
|
||||
2 * minSquaresAway + 1);
|
||||
|
||||
// eliminate from consideration dig spots that lie entirely within the min range or entirely outside of the max range
|
||||
possibleLocations.removeIf(entry -> minDistanceArea.contains(entry.getRect()) || !maxDistanceArea.intersects(entry.getRect()));
|
||||
|
||||
// if a previous world point has been recorded, we can consider the warmer/colder result from the strange device
|
||||
if (lastWorldPoint != null && temperatureChange != null)
|
||||
{
|
||||
switch (temperatureChange)
|
||||
{
|
||||
case COLDER:
|
||||
// eliminate spots that are absolutely warmer
|
||||
possibleLocations.removeIf(entry -> isFirstPointCloserRect(worldPoint, lastWorldPoint, entry.getRect()));
|
||||
break;
|
||||
case WARMER:
|
||||
// eliminate spots that are absolutely colder
|
||||
possibleLocations.removeIf(entry -> isFirstPointCloserRect(lastWorldPoint, worldPoint, entry.getRect()));
|
||||
break;
|
||||
case SAME:
|
||||
// I couldn't figure out a clean implementation for this case
|
||||
// not necessary for quickly determining final location
|
||||
}
|
||||
}
|
||||
|
||||
lastWorldPoint = worldPoint;
|
||||
return getPossibleLocations();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the first point passed is closer to each corner of the given rectangle than the second point.
|
||||
*
|
||||
* @param firstPoint First point to test. Return result will be relating to this point's location.
|
||||
* @param secondPoint Second point to test
|
||||
* @param rect Rectangle, whose corner points will be compared to the first and second points passed
|
||||
* @return {@code true} if {@code firstPoint} is closer to each of {@code rect}'s four corner points than
|
||||
* {@code secondPoint}, {@code false} otherwise.
|
||||
* @see WorldPoint#distanceTo2D
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static boolean isFirstPointCloserRect(final WorldPoint firstPoint, final WorldPoint secondPoint, final Rectangle rect)
|
||||
{
|
||||
final WorldPoint nePoint = new WorldPoint((rect.x + rect.width), (rect.y + rect.height), 0);
|
||||
|
||||
if (!isFirstPointCloser(firstPoint, secondPoint, nePoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final WorldPoint sePoint = new WorldPoint((rect.x + rect.width), rect.y, 0);
|
||||
|
||||
if (!isFirstPointCloser(firstPoint, secondPoint, sePoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final WorldPoint nwPoint = new WorldPoint(rect.x, (rect.y + rect.height), 0);
|
||||
|
||||
if (!isFirstPointCloser(firstPoint, secondPoint, nwPoint))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final WorldPoint swPoint = new WorldPoint(rect.x, rect.y, 0);
|
||||
return (isFirstPointCloser(firstPoint, secondPoint, swPoint));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the first point passed is closer to the given point of comparison than the second point.
|
||||
*
|
||||
* @param firstPoint First point to test. Return result will be relating to this point's location.
|
||||
* @param secondPoint Second point to test
|
||||
* @param worldPoint Point to compare to the first and second points passed
|
||||
* @return {@code true} if {@code firstPoint} is closer to {@code worldPoint} than {@code secondPoint},
|
||||
* {@code false} otherwise.
|
||||
* @see WorldPoint#distanceTo2D
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static boolean isFirstPointCloser(final WorldPoint firstPoint, final WorldPoint secondPoint, final WorldPoint worldPoint)
|
||||
{
|
||||
return firstPoint.distanceTo2D(worldPoint) < secondPoint.distanceTo2D(worldPoint);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.cluescrolls.clues.hotcold;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum HotColdTemperature
|
||||
{
|
||||
ICE_COLD("ice cold", 500, 5000),
|
||||
VERY_COLD("very cold", 200, 499),
|
||||
COLD("cold", 150, 199),
|
||||
WARM("warm", 100, 149),
|
||||
HOT("hot", 70, 99),
|
||||
VERY_HOT("very hot", 30, 69),
|
||||
BEGINNER_INCREDIBLY_HOT("incredibly hot", 4, 29),
|
||||
BEGINNER_VISIBLY_SHAKING("visibly shaking", 0, 3),
|
||||
MASTER_INCREDIBLY_HOT("incredibly hot", 5, 29),
|
||||
MASTER_VISIBLY_SHAKING("visibly shaking", 0, 4);
|
||||
|
||||
public static final Set<HotColdTemperature> BEGINNER_HOT_COLD_TEMPERATURES = Sets.immutableEnumSet(
|
||||
ICE_COLD,
|
||||
VERY_COLD,
|
||||
COLD,
|
||||
WARM,
|
||||
HOT,
|
||||
VERY_HOT,
|
||||
BEGINNER_INCREDIBLY_HOT,
|
||||
BEGINNER_VISIBLY_SHAKING
|
||||
);
|
||||
public static final Set<HotColdTemperature> MASTER_HOT_COLD_TEMPERATURES = Sets.immutableEnumSet(
|
||||
ICE_COLD,
|
||||
VERY_COLD,
|
||||
COLD,
|
||||
WARM,
|
||||
HOT,
|
||||
VERY_HOT,
|
||||
MASTER_INCREDIBLY_HOT,
|
||||
MASTER_VISIBLY_SHAKING
|
||||
);
|
||||
|
||||
private final String text;
|
||||
private final int minDistance;
|
||||
private final int maxDistance;
|
||||
|
||||
private static final String DEVICE_USED_START_TEXT = "The device is ";
|
||||
|
||||
/**
|
||||
* Gets the temperature from a set of temperatures corresponding to the passed string.
|
||||
*
|
||||
* @param temperatureSet A set of temperature values to select from
|
||||
* @param message A string containing a temperature value
|
||||
* @return The corresponding enum from the given temperature set.
|
||||
* <p>
|
||||
* Note that in cases where two temperature values in the given set are equally likely to be the given
|
||||
* temperature (say, two temperatures with identical text values), the behavior is undefined.
|
||||
*/
|
||||
@Nullable
|
||||
public static HotColdTemperature getFromTemperatureSet(final Set<HotColdTemperature> temperatureSet, final String message)
|
||||
{
|
||||
if (!message.startsWith(DEVICE_USED_START_TEXT) || temperatureSet == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final List<HotColdTemperature> possibleTemperatures = new ArrayList<>();
|
||||
|
||||
for (final HotColdTemperature temperature : temperatureSet)
|
||||
{
|
||||
if (message.contains(temperature.getText()))
|
||||
{
|
||||
possibleTemperatures.add(temperature);
|
||||
}
|
||||
}
|
||||
|
||||
return possibleTemperatures.stream()
|
||||
// For messages such as "The device is very cold", this will choose the Enum with text of greatest length so
|
||||
// that VERY_COLD would be selected over COLD, though both Enums have matching text for this message.
|
||||
.max(Comparator.comparingInt(x -> (x.getText()).length()))
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Jordan Atwood <nightfirecat@protonmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.cluescrolls.clues.hotcold;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
public enum HotColdTemperatureChange
|
||||
{
|
||||
WARMER("and warmer than"),
|
||||
SAME("and the same temperature as"),
|
||||
COLDER("but colder than");
|
||||
|
||||
private final String text;
|
||||
|
||||
public static HotColdTemperatureChange of(final String message)
|
||||
{
|
||||
if (!message.endsWith(" last time."))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
for (final HotColdTemperatureChange change : values())
|
||||
{
|
||||
if (message.contains(change.text))
|
||||
{
|
||||
return change;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,7 @@ class DevToolsButton extends JButton
|
||||
{
|
||||
super(title);
|
||||
addActionListener((ev) -> setActive(!active));
|
||||
this.setToolTipText(title);
|
||||
}
|
||||
|
||||
void setActive(boolean active)
|
||||
|
||||
@@ -24,20 +24,119 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.fightcave;
|
||||
|
||||
import java.awt.Font;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
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("fightcave")
|
||||
public interface FightCaveConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
position = 0,
|
||||
keyName = "mainConfig",
|
||||
name = "Main Config",
|
||||
description = ""
|
||||
)
|
||||
default Stub mainConfig()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 1,
|
||||
keyName = "waveDisplay",
|
||||
name = "Wave display",
|
||||
description = "Shows monsters that will spawn on the selected wave(s)."
|
||||
description = "Shows monsters that will spawn on the selected wave(s).",
|
||||
parent = "mainConfig"
|
||||
)
|
||||
default WaveDisplayMode waveDisplay()
|
||||
{
|
||||
return WaveDisplayMode.BOTH;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "tickTimersWidget",
|
||||
name = "Tick Timers in Prayer",
|
||||
description = "Adds an overlay to the Praayer Interface with the ticks until next attack for that prayer.",
|
||||
parent = "mainConfig"
|
||||
)
|
||||
default boolean tickTimersWidget()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "text",
|
||||
name = "Text",
|
||||
description = ""
|
||||
)
|
||||
default Stub text()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 4,
|
||||
keyName = "fontStyle",
|
||||
name = "Font Style",
|
||||
description = "Plain | Bold | Italics",
|
||||
parent = "text"
|
||||
)
|
||||
default FontStyle fontStyle()
|
||||
{
|
||||
return FontStyle.BOLD;
|
||||
}
|
||||
|
||||
@Range(
|
||||
min = 14,
|
||||
max = 40
|
||||
)
|
||||
@ConfigItem(
|
||||
position = 5,
|
||||
keyName = "textSize",
|
||||
name = "Text Size",
|
||||
description = "Text Size for Timers.",
|
||||
parent = "text"
|
||||
)
|
||||
default int textSize()
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 6,
|
||||
keyName = "shadows",
|
||||
name = "Shadows",
|
||||
description = "Adds Shadows to text.",
|
||||
parent = "text"
|
||||
)
|
||||
default boolean shadows()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
enum FontStyle
|
||||
{
|
||||
BOLD("Bold", Font.BOLD),
|
||||
ITALIC("Italic", Font.ITALIC),
|
||||
PLAIN("Plain", Font.PLAIN);
|
||||
|
||||
private String name;
|
||||
private int font;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Ganom <https://github.com/Ganom>
|
||||
* Copyright (c) 2019, Lucas <https://github.com/lucwousin>
|
||||
* 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.fightcave;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.awt.Color;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCDefinition;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Prayer;
|
||||
|
||||
@Getter
|
||||
class FightCaveContainer
|
||||
{
|
||||
private NPC npc;
|
||||
private String npcName;
|
||||
private int npcIndex;
|
||||
private int npcSize;
|
||||
private int attackSpeed;
|
||||
private int priority;
|
||||
private ImmutableSet<Integer> animations;
|
||||
@Setter
|
||||
private int ticksUntilAttack;
|
||||
@Setter
|
||||
private Actor npcInteracting;
|
||||
@Setter
|
||||
private AttackStyle attackStyle;
|
||||
|
||||
FightCaveContainer(NPC npc, int attackSpeed)
|
||||
{
|
||||
this.npc = npc;
|
||||
this.npcName = npc.getName();
|
||||
this.npcIndex = npc.getIndex();
|
||||
this.npcInteracting = npc.getInteracting();
|
||||
this.attackStyle = AttackStyle.UNKNOWN;
|
||||
this.attackSpeed = attackSpeed;
|
||||
this.ticksUntilAttack = -1;
|
||||
final NPCDefinition composition = npc.getTransformedDefinition();
|
||||
|
||||
BossMonsters monster = BossMonsters.of(npc.getId());
|
||||
|
||||
if (monster == null)
|
||||
{
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
this.animations = monster.animations;
|
||||
this.attackStyle = monster.attackStyle;
|
||||
this.priority = monster.priority;
|
||||
|
||||
if (composition != null)
|
||||
{
|
||||
this.npcSize = composition.getSize();
|
||||
}
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
enum BossMonsters
|
||||
{
|
||||
TOK_XIL1(NpcID.TOKXIL_3121, AttackStyle.RANGE, ImmutableSet.of(AnimationID.TOK_XIL_RANGE_ATTACK, AnimationID.TOK_XIL_MELEE_ATTACK), 1),
|
||||
TOK_XIL2(NpcID.TOKXIL_3122, AttackStyle.RANGE, ImmutableSet.of(AnimationID.TOK_XIL_RANGE_ATTACK, AnimationID.TOK_XIL_MELEE_ATTACK), 1),
|
||||
KETZEK1(NpcID.KETZEK, AttackStyle.MAGE, ImmutableSet.of(AnimationID.KET_ZEK_MAGE_ATTACK, AnimationID.KET_ZEK_MELEE_ATTACK), 0),
|
||||
KETZEK2(NpcID.KETZEK_3126, AttackStyle.MAGE, ImmutableSet.of(AnimationID.KET_ZEK_MAGE_ATTACK, AnimationID.KET_ZEK_MELEE_ATTACK), 0),
|
||||
YTMEJKOT1(NpcID.YTMEJKOT, AttackStyle.MELEE, ImmutableSet.of(AnimationID.MEJ_KOT_HEAL_ATTACK, AnimationID.MEJ_KOT_MELEE_ATTACK), 2),
|
||||
YTMEJKOT2(NpcID.YTMEJKOT_3124, AttackStyle.MELEE, ImmutableSet.of(AnimationID.MEJ_KOT_HEAL_ATTACK, AnimationID.MEJ_KOT_MELEE_ATTACK), 2),
|
||||
TZTOKJAD1(NpcID.TZTOKJAD, AttackStyle.UNKNOWN, ImmutableSet.of(AnimationID.TZTOK_JAD_MAGIC_ATTACK, AnimationID.TZTOK_JAD_RANGE_ATTACK, AnimationID.TZTOK_JAD_MELEE_ATTACK), 0),
|
||||
TZTOKJAD2(NpcID.TZTOKJAD_6506, AttackStyle.UNKNOWN, ImmutableSet.of(AnimationID.TZTOK_JAD_MAGIC_ATTACK, AnimationID.TZTOK_JAD_RANGE_ATTACK, AnimationID.TZTOK_JAD_MELEE_ATTACK), 0);
|
||||
|
||||
private static ImmutableMap<Integer, BossMonsters> idMap;
|
||||
|
||||
static
|
||||
{
|
||||
ImmutableMap.Builder<Integer, BossMonsters> builder = ImmutableMap.builder();
|
||||
|
||||
for (BossMonsters monster : values())
|
||||
{
|
||||
builder.put(monster.npcID, monster);
|
||||
}
|
||||
|
||||
idMap = builder.build();
|
||||
}
|
||||
|
||||
private final int npcID;
|
||||
private final AttackStyle attackStyle;
|
||||
private final ImmutableSet<Integer> animations;
|
||||
private final int priority;
|
||||
|
||||
static BossMonsters of(int npcID)
|
||||
{
|
||||
return idMap.get(npcID);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@AllArgsConstructor
|
||||
enum AttackStyle
|
||||
{
|
||||
MAGE("Mage", Color.CYAN, Prayer.PROTECT_FROM_MAGIC),
|
||||
RANGE("Range", Color.GREEN, Prayer.PROTECT_FROM_MISSILES),
|
||||
MELEE("Melee", Color.RED, Prayer.PROTECT_FROM_MELEE),
|
||||
UNKNOWN("Unknown", Color.WHITE, null);
|
||||
|
||||
private String name;
|
||||
private Color color;
|
||||
private Prayer prayer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* 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.fightcave;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Point;
|
||||
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.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
|
||||
public class FightCaveOverlay extends Overlay
|
||||
{
|
||||
private FightCavePlugin plugin;
|
||||
private FightCaveConfig config;
|
||||
private Client client;
|
||||
private SpriteManager spriteManager;
|
||||
|
||||
@Inject
|
||||
FightCaveOverlay(Client client, FightCavePlugin plugin, FightCaveConfig config, SpriteManager spriteManager)
|
||||
{
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.spriteManager = spriteManager;
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setPriority(OverlayPriority.HIGHEST);
|
||||
setLayer(OverlayLayer.ALWAYS_ON_TOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
for (FightCaveContainer npc : plugin.getFightCaveContainer())
|
||||
{
|
||||
if (npc.getNpc() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final int ticksLeft = npc.getTicksUntilAttack();
|
||||
final FightCaveContainer.AttackStyle attackStyle = npc.getAttackStyle();
|
||||
|
||||
if (ticksLeft <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final String ticksLeftStr = String.valueOf(ticksLeft);
|
||||
final int font = config.fontStyle().getFont();
|
||||
final boolean shadows = config.shadows();
|
||||
Color color = (ticksLeft <= 1 ? Color.WHITE : attackStyle.getColor());
|
||||
final Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, Integer.toString(ticksLeft), 0);
|
||||
|
||||
if (npc.getNpcName().equals("TzTok-Jad"))
|
||||
{
|
||||
color = (ticksLeft <= 1 || ticksLeft == 8 ? attackStyle.getColor() : Color.WHITE);
|
||||
|
||||
BufferedImage pray = getPrayerImage(npc.getAttackStyle());
|
||||
|
||||
if (pray == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
renderImageLocation(graphics, npc.getNpc().getCanvasImageLocation(ImageUtil.resizeImage(pray, 36, 36), 0), pray, 12, 30);
|
||||
}
|
||||
|
||||
OverlayUtil.renderTextLocation(graphics, ticksLeftStr, config.textSize(), font, color, canvasPoint, shadows, 0);
|
||||
}
|
||||
|
||||
if (config.tickTimersWidget())
|
||||
{
|
||||
|
||||
if (!plugin.getMageTicks().isEmpty())
|
||||
{
|
||||
widgetHandler(graphics,
|
||||
Prayer.PROTECT_FROM_MAGIC,
|
||||
plugin.getMageTicks().get(0) == 1 ? Color.WHITE : Color.CYAN,
|
||||
Integer.toString(plugin.getMageTicks().get(0)),
|
||||
config.shadows()
|
||||
);
|
||||
}
|
||||
if (!plugin.getRangedTicks().isEmpty())
|
||||
{
|
||||
widgetHandler(graphics,
|
||||
Prayer.PROTECT_FROM_MISSILES,
|
||||
plugin.getRangedTicks().get(0) == 1 ? Color.WHITE : Color.GREEN,
|
||||
Integer.toString(plugin.getRangedTicks().get(0)),
|
||||
config.shadows()
|
||||
);
|
||||
}
|
||||
if (!plugin.getMeleeTicks().isEmpty())
|
||||
{
|
||||
widgetHandler(graphics,
|
||||
Prayer.PROTECT_FROM_MELEE,
|
||||
plugin.getMeleeTicks().get(0) == 1 ? Color.WHITE : Color.RED,
|
||||
Integer.toString(plugin.getMeleeTicks().get(0)),
|
||||
config.shadows()
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void widgetHandler(Graphics2D graphics, Prayer prayer, Color color, String ticks, boolean shadows)
|
||||
{
|
||||
if (prayer != null)
|
||||
{
|
||||
Rectangle bounds = OverlayUtil.renderPrayerOverlay(graphics, client, prayer, color);
|
||||
|
||||
if (bounds != null)
|
||||
{
|
||||
renderTextLocation(graphics, ticks, 16, config.fontStyle().getFont(), color, centerPoint(bounds), shadows);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage getPrayerImage(FightCaveContainer.AttackStyle attackStyle)
|
||||
{
|
||||
switch (attackStyle)
|
||||
{
|
||||
case MAGE:
|
||||
return spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MAGIC, 0);
|
||||
case MELEE:
|
||||
return spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MELEE, 0);
|
||||
case RANGE:
|
||||
return spriteManager.getSprite(SpriteID.PRAYER_PROTECT_FROM_MISSILES, 0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderImageLocation(Graphics2D graphics, Point imgLoc, BufferedImage image, int xOffset, int yOffset)
|
||||
{
|
||||
int x = imgLoc.getX() + xOffset;
|
||||
int y = imgLoc.getY() - yOffset;
|
||||
|
||||
graphics.drawImage(image, x, y, null);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -27,22 +27,23 @@ package net.runelite.client.plugins.fightcave;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
@@ -50,6 +51,7 @@ import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.NPCManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
@@ -64,59 +66,16 @@ import org.apache.commons.lang3.ArrayUtils;
|
||||
enabledByDefault = false
|
||||
)
|
||||
|
||||
@Slf4j
|
||||
public class FightCavePlugin extends Plugin
|
||||
{
|
||||
static final int MAX_WAVE = 63;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
static final List<EnumMap<WaveMonster, Integer>> WAVES = new ArrayList<>();
|
||||
private static final Pattern WAVE_PATTERN = Pattern.compile(".*Wave: (\\d+).*");
|
||||
private static final int FIGHT_CAVE_REGION = 9551;
|
||||
private static final int MAX_MONSTERS_OF_TYPE_PER_WAVE = 2;
|
||||
|
||||
static final int MAX_WAVE = 63;
|
||||
|
||||
@Getter
|
||||
static final List<EnumMap<WaveMonster, Integer>> WAVES = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
private int currentWave = -1;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private WaveOverlay waveOverlay;
|
||||
|
||||
@Inject
|
||||
private JadOverlay jadOverlay;
|
||||
|
||||
@Inject
|
||||
private TimersOverlay timersOverlay;
|
||||
|
||||
@Inject
|
||||
private ConfigManager externalConfig;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Map<NPC, NPCContainer> Rangers = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Map<NPC, NPCContainer> Magers = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Map<NPC, NPCContainer> Meleers = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Map<NPC, NPCContainer> Drainers = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Map<NPC, NPCContainer> Ignore = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Nullable
|
||||
private JadAttack attack;
|
||||
|
||||
private NPC jad;
|
||||
|
||||
static
|
||||
{
|
||||
final WaveMonster[] waveMonsters = WaveMonster.values();
|
||||
@@ -157,6 +116,36 @@ public class FightCavePlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
@Inject
|
||||
private NPCManager npcManager;
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
@Inject
|
||||
private WaveOverlay waveOverlay;
|
||||
@Inject
|
||||
private FightCaveOverlay fightCaveOverlay;
|
||||
@Inject
|
||||
private FightCaveConfig config;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Set<FightCaveContainer> fightCaveContainer = new HashSet<>();
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int currentWave = -1;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private boolean validRegion;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<Integer> mageTicks = new ArrayList<>();
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<Integer> rangedTicks = new ArrayList<>();
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<Integer> meleeTicks = new ArrayList<>();
|
||||
|
||||
static String formatMonsterQuantity(final WaveMonster monster, final int quantity)
|
||||
{
|
||||
return String.format("%dx %s", quantity, monster);
|
||||
}
|
||||
|
||||
@Provides
|
||||
FightCaveConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
@@ -166,21 +155,41 @@ public class FightCavePlugin extends Plugin
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
overlayManager.add(waveOverlay);
|
||||
overlayManager.add(jadOverlay);
|
||||
overlayManager.add(timersOverlay);
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
if (regionCheck())
|
||||
{
|
||||
validRegion = true;
|
||||
overlayManager.add(waveOverlay);
|
||||
overlayManager.add(fightCaveOverlay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
overlayManager.remove(waveOverlay);
|
||||
overlayManager.remove(fightCaveOverlay);
|
||||
currentWave = -1;
|
||||
overlayManager.remove(timersOverlay);
|
||||
overlayManager.remove(jadOverlay);
|
||||
jad = null;
|
||||
attack = null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (!validRegion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final Matcher waveMatcher = WAVE_PATTERN.matcher(event.getMessage());
|
||||
|
||||
if (event.getType() != ChatMessageType.GAMEMESSAGE || !waveMatcher.matches())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentWave = Integer.parseInt(waveMatcher.group(1));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -191,98 +200,43 @@ public class FightCavePlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
if (!inFightCave())
|
||||
if (regionCheck())
|
||||
{
|
||||
currentWave = -1;
|
||||
validRegion = true;
|
||||
overlayManager.add(waveOverlay);
|
||||
overlayManager.add(fightCaveOverlay);
|
||||
}
|
||||
else
|
||||
{
|
||||
validRegion = false;
|
||||
overlayManager.remove(fightCaveOverlay);
|
||||
overlayManager.remove(fightCaveOverlay);
|
||||
}
|
||||
|
||||
fightCaveContainer.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick Event)
|
||||
{
|
||||
for (NPCContainer ranger : getRangers().values())
|
||||
{
|
||||
ranger.setTicksUntilAttack(ranger.getTicksUntilAttack() - 1);
|
||||
if (ranger.getNpc().getAnimation() == 2633)
|
||||
{
|
||||
if (ranger.getTicksUntilAttack() < 1)
|
||||
{
|
||||
ranger.setTicksUntilAttack(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (NPCContainer meleer : getMeleers().values())
|
||||
{
|
||||
meleer.setTicksUntilAttack(meleer.getTicksUntilAttack() - 1);
|
||||
if (meleer.getNpc().getAnimation() == 2637 || meleer.getNpc().getAnimation() == 2639)
|
||||
{
|
||||
if (meleer.getTicksUntilAttack() < 1)
|
||||
{
|
||||
meleer.setTicksUntilAttack(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (NPCContainer mager : getMagers().values())
|
||||
{
|
||||
mager.setTicksUntilAttack(mager.getTicksUntilAttack() - 1);
|
||||
if (mager.getNpc().getAnimation() == 2647)
|
||||
{
|
||||
if (mager.getTicksUntilAttack() < 1)
|
||||
{
|
||||
mager.setTicksUntilAttack(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
final Matcher waveMatcher = WAVE_PATTERN.matcher(event.getMessage());
|
||||
|
||||
if (event.getType() != ChatMessageType.GAMEMESSAGE
|
||||
|| !inFightCave()
|
||||
|| !waveMatcher.matches())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
currentWave = Integer.parseInt(waveMatcher.group(1));
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
if (!validRegion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NPC npc = event.getNpc();
|
||||
|
||||
switch (npc.getId())
|
||||
{
|
||||
case NpcID.TZKIH_3116:
|
||||
case NpcID.TZKIH_3117:
|
||||
Drainers.put(npc, new NPCContainer(npc));
|
||||
break;
|
||||
case NpcID.TZKEK_3118:
|
||||
case NpcID.TZKEK_3119:
|
||||
case NpcID.TZKEK_3120:
|
||||
Ignore.put(npc, new NPCContainer(npc));
|
||||
break;
|
||||
case NpcID.TOKXIL_3121:
|
||||
case NpcID.TOKXIL_3122:
|
||||
Rangers.put(npc, new NPCContainer(npc));
|
||||
break;
|
||||
case NpcID.YTMEJKOT:
|
||||
case NpcID.YTMEJKOT_3124:
|
||||
Meleers.put(npc, new NPCContainer(npc));
|
||||
break;
|
||||
case NpcID.KETZEK:
|
||||
case NpcID.KETZEK_3126:
|
||||
Magers.put(npc, new NPCContainer(npc));
|
||||
break;
|
||||
case NpcID.TZTOKJAD:
|
||||
case NpcID.TZTOKJAD_6506:
|
||||
jad = npc;
|
||||
fightCaveContainer.add(new FightCaveContainer(npc, npcManager.getAttackSpeed(npc.getId())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -290,55 +244,106 @@ public class FightCavePlugin extends Plugin
|
||||
@Subscribe
|
||||
public void onNpcDespawned(NpcDespawned event)
|
||||
{
|
||||
if (Rangers.remove(event.getNpc()) != null && Rangers.isEmpty())
|
||||
{
|
||||
Rangers.clear();
|
||||
}
|
||||
if (Meleers.remove(event.getNpc()) != null && Meleers.isEmpty())
|
||||
{
|
||||
Meleers.clear();
|
||||
}
|
||||
if (Magers.remove(event.getNpc()) != null && Magers.isEmpty())
|
||||
{
|
||||
Magers.clear();
|
||||
}
|
||||
if (Drainers.remove(event.getNpc()) != null && Drainers.isEmpty())
|
||||
{
|
||||
Drainers.clear();
|
||||
}
|
||||
if (Ignore.remove(event.getNpc()) != null && Ignore.isEmpty())
|
||||
{
|
||||
Ignore.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onAnimationChanged(AnimationChanged event)
|
||||
{
|
||||
if (event.getActor() != jad)
|
||||
if (!validRegion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (jad.getAnimation() == JadAttack.MAGIC.getAnimation())
|
||||
{
|
||||
attack = JadAttack.MAGIC;
|
||||
}
|
||||
NPC npc = event.getNpc();
|
||||
|
||||
else if (jad.getAnimation() == JadAttack.RANGE.getAnimation())
|
||||
switch (npc.getId())
|
||||
{
|
||||
attack = JadAttack.RANGE;
|
||||
case NpcID.TOKXIL_3121:
|
||||
case NpcID.TOKXIL_3122:
|
||||
case NpcID.YTMEJKOT:
|
||||
case NpcID.YTMEJKOT_3124:
|
||||
case NpcID.KETZEK:
|
||||
case NpcID.KETZEK_3126:
|
||||
case NpcID.TZTOKJAD:
|
||||
case NpcID.TZTOKJAD_6506:
|
||||
fightCaveContainer.removeIf(c -> c.getNpc() == npc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean inFightCave()
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick Event)
|
||||
{
|
||||
if (!validRegion)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mageTicks.clear();
|
||||
rangedTicks.clear();
|
||||
meleeTicks.clear();
|
||||
|
||||
for (FightCaveContainer npc : fightCaveContainer)
|
||||
{
|
||||
if (npc.getTicksUntilAttack() >= 0)
|
||||
{
|
||||
npc.setTicksUntilAttack(npc.getTicksUntilAttack() - 1);
|
||||
}
|
||||
|
||||
for (int anims : npc.getAnimations())
|
||||
{
|
||||
if (anims == npc.getNpc().getAnimation())
|
||||
{
|
||||
if (npc.getTicksUntilAttack() < 1)
|
||||
{
|
||||
npc.setTicksUntilAttack(npc.getAttackSpeed());
|
||||
}
|
||||
|
||||
switch (anims)
|
||||
{
|
||||
case AnimationID.TZTOK_JAD_RANGE_ATTACK:
|
||||
npc.setAttackStyle(FightCaveContainer.AttackStyle.RANGE);
|
||||
break;
|
||||
case AnimationID.TZTOK_JAD_MAGIC_ATTACK:
|
||||
npc.setAttackStyle(FightCaveContainer.AttackStyle.MAGE);
|
||||
break;
|
||||
case AnimationID.TZTOK_JAD_MELEE_ATTACK:
|
||||
npc.setAttackStyle(FightCaveContainer.AttackStyle.MELEE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (npc.getNpcName().equals("TzTok-Jad"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (npc.getAttackStyle())
|
||||
{
|
||||
case RANGE:
|
||||
if (npc.getTicksUntilAttack() > 0)
|
||||
{
|
||||
rangedTicks.add(npc.getTicksUntilAttack());
|
||||
}
|
||||
break;
|
||||
case MELEE:
|
||||
if (npc.getTicksUntilAttack() > 0)
|
||||
{
|
||||
meleeTicks.add(npc.getTicksUntilAttack());
|
||||
}
|
||||
break;
|
||||
case MAGE:
|
||||
if (npc.getTicksUntilAttack() > 0)
|
||||
{
|
||||
mageTicks.add(npc.getTicksUntilAttack());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(mageTicks);
|
||||
Collections.sort(rangedTicks);
|
||||
Collections.sort(meleeTicks);
|
||||
}
|
||||
|
||||
private boolean regionCheck()
|
||||
{
|
||||
return ArrayUtils.contains(client.getMapRegions(), FIGHT_CAVE_REGION);
|
||||
}
|
||||
|
||||
static String formatMonsterQuantity(final WaveMonster monster, final int quantity)
|
||||
{
|
||||
return String.format("%dx %s", quantity, monster);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,184 +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.fightcave;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCDefinition;
|
||||
import net.runelite.api.Perspective;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
public class TimersOverlay extends Overlay
|
||||
{
|
||||
private FightCavePlugin plugin;
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
TimersOverlay(FightCavePlugin plugin, Client client)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setPriority(OverlayPriority.HIGHEST);
|
||||
setLayer(OverlayLayer.ALWAYS_ON_TOP);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
for (NPCContainer npc : plugin.getDrainers().values())
|
||||
{
|
||||
renderNpcOverlay(graphics, npc.getNpc(), Color.RED, 255, 20);
|
||||
String str = "drainer";
|
||||
Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, str, 0);
|
||||
renderTextLocation(graphics, str, 12, Color.WHITE, canvasPoint);
|
||||
}
|
||||
|
||||
for (NPCContainer npc : plugin.getIgnore().values())
|
||||
{
|
||||
renderNpcOverlay(graphics, npc.getNpc(), Color.BLACK, 50, 5);
|
||||
String str = "ignore";
|
||||
Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, str, 0);
|
||||
renderTextLocation(graphics, str, 10, Color.WHITE, canvasPoint);
|
||||
}
|
||||
|
||||
Color tickcolor;
|
||||
|
||||
for (NPCContainer npc : plugin.getRangers().values())
|
||||
{
|
||||
renderNpcOverlay(graphics, npc.getNpc(), Color.GREEN, 100, 10);
|
||||
final int ticksLeft = npc.getTicksUntilAttack();
|
||||
if (ticksLeft > 0)
|
||||
{
|
||||
if (ticksLeft == 1)
|
||||
{
|
||||
tickcolor = Color.GREEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
tickcolor = Color.WHITE;
|
||||
}
|
||||
final String ticksLeftStr = String.valueOf(ticksLeft);
|
||||
Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0);
|
||||
renderTextLocation(graphics, ticksLeftStr, 32, tickcolor, canvasPoint);
|
||||
}
|
||||
}
|
||||
|
||||
for (NPCContainer npc : plugin.getMagers().values())
|
||||
{
|
||||
renderNpcOverlay(graphics, npc.getNpc(), Color.CYAN, 100, 10);
|
||||
final int ticksLeft = npc.getTicksUntilAttack();
|
||||
if (ticksLeft > 0)
|
||||
{
|
||||
if (ticksLeft == 1)
|
||||
{
|
||||
tickcolor = Color.CYAN;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
tickcolor = Color.WHITE;
|
||||
}
|
||||
final String ticksLeftStr = String.valueOf(ticksLeft);
|
||||
Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0);
|
||||
renderTextLocation(graphics, ticksLeftStr, 32, tickcolor, canvasPoint);
|
||||
}
|
||||
}
|
||||
|
||||
for (NPCContainer npc : plugin.getMeleers().values())
|
||||
{
|
||||
renderNpcOverlay(graphics, npc.getNpc(), Color.RED, 100, 10);
|
||||
final int ticksLeft = npc.getTicksUntilAttack();
|
||||
if (ticksLeft > 0)
|
||||
{
|
||||
if (ticksLeft == 1)
|
||||
{
|
||||
tickcolor = Color.RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
tickcolor = Color.WHITE;
|
||||
}
|
||||
final String ticksLeftStr = String.valueOf(ticksLeft);
|
||||
Point canvasPoint = npc.getNpc().getCanvasTextLocation(graphics, ticksLeftStr, 0);
|
||||
renderTextLocation(graphics, ticksLeftStr, 32, tickcolor, canvasPoint);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderNpcOverlay(Graphics2D graphics, NPC actor, Color color, int outlineAlpha, int fillAlpha)
|
||||
{
|
||||
int size = 1;
|
||||
NPCDefinition composition = actor.getTransformedDefinition();
|
||||
if (composition != null)
|
||||
{
|
||||
size = composition.getSize();
|
||||
}
|
||||
LocalPoint lp = actor.getLocalLocation();
|
||||
Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size);
|
||||
|
||||
if (tilePoly != null)
|
||||
{
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha));
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.draw(tilePoly);
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), fillAlpha));
|
||||
graphics.fill(tilePoly);
|
||||
}
|
||||
}
|
||||
|
||||
private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, Color fontColor, Point canvasPoint)
|
||||
{
|
||||
graphics.setFont(new Font("Arial", Font.BOLD, fontSize));
|
||||
if (canvasPoint != null)
|
||||
{
|
||||
final Point canvasCenterPoint = new Point(
|
||||
canvasPoint.getX(),
|
||||
canvasPoint.getY());
|
||||
final Point canvasCenterPoint_shadow = new Point(
|
||||
canvasPoint.getX() + 1,
|
||||
canvasPoint.getY() + 1);
|
||||
OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK);
|
||||
OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,12 +29,12 @@ import lombok.AllArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
enum WaveMonster
|
||||
{
|
||||
TZ_KIH("Tz-Kih", 22),
|
||||
TZ_KEK("Tz-Kek", 45),
|
||||
TOK_XIL("Tok-Xil", 90),
|
||||
YT_MEJKOT("Yt-MejKot", 180),
|
||||
KET_ZEK("Ket-Zek", 360),
|
||||
TZKOK_JAD("TzTok-Jad", 702);
|
||||
TZ_KIH("Drainer", 22),
|
||||
TZ_KEK("Blob", 45),
|
||||
TOK_XIL("Range", 90),
|
||||
YT_MEJKOT("Melee", 180),
|
||||
KET_ZEK("Mage", 360),
|
||||
TZKOK_JAD("Jad", 702);
|
||||
|
||||
private final String name;
|
||||
private final int level;
|
||||
|
||||
@@ -37,8 +37,8 @@ import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
import net.runelite.client.ui.overlay.components.table.TableAlignment;
|
||||
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
|
||||
class WaveOverlay extends Overlay
|
||||
{
|
||||
@@ -46,22 +46,38 @@ class WaveOverlay extends Overlay
|
||||
|
||||
private final FightCaveConfig config;
|
||||
private final FightCavePlugin plugin;
|
||||
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
|
||||
@Inject
|
||||
private WaveOverlay(FightCaveConfig config, FightCavePlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.TOP_RIGHT);
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
setPosition(OverlayPosition.TOP_RIGHT);
|
||||
}
|
||||
|
||||
private static Collection<String> buildWaveLines(final Map<WaveMonster, Integer> wave)
|
||||
{
|
||||
final List<Map.Entry<WaveMonster, Integer>> monsters = new ArrayList<>(wave.entrySet());
|
||||
monsters.sort(Map.Entry.comparingByKey());
|
||||
final List<String> outputLines = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<WaveMonster, Integer> monsterEntry : monsters)
|
||||
{
|
||||
final WaveMonster monster = monsterEntry.getKey();
|
||||
final int quantity = monsterEntry.getValue();
|
||||
final String line = FightCavePlugin.formatMonsterQuantity(monster, quantity);
|
||||
|
||||
outputLines.add(line);
|
||||
}
|
||||
|
||||
return outputLines;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (!plugin.inFightCave()
|
||||
|| plugin.getCurrentWave() < 0)
|
||||
if (!plugin.isValidRegion() || plugin.getCurrentWave() < 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -108,26 +124,8 @@ class WaveOverlay extends Overlay
|
||||
}
|
||||
|
||||
if (!tableComponent.isEmpty())
|
||||
{
|
||||
panelComponent.getChildren().add(tableComponent);
|
||||
}
|
||||
}
|
||||
|
||||
private static Collection<String> buildWaveLines(final Map<WaveMonster, Integer> wave)
|
||||
{
|
||||
final List<Map.Entry<WaveMonster, Integer>> monsters = new ArrayList<>(wave.entrySet());
|
||||
monsters.sort(Map.Entry.comparingByKey());
|
||||
final List<String> outputLines = new ArrayList<>();
|
||||
|
||||
for (Map.Entry<WaveMonster, Integer> monsterEntry : monsters)
|
||||
{
|
||||
final WaveMonster monster = monsterEntry.getKey();
|
||||
final int quantity = monsterEntry.getValue();
|
||||
final String line = FightCavePlugin.formatMonsterQuantity(monster, quantity);
|
||||
|
||||
outputLines.add(line);
|
||||
panelComponent.getChildren().add(tableComponent);
|
||||
}
|
||||
|
||||
return outputLines;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,17 +54,17 @@ public class FreezeTimersOverlay extends Overlay
|
||||
private final BufferedImage FREEZE_IMAGE = ImageUtil.getResourceStreamFromClass(getClass(), "freeze.png");
|
||||
private final BufferedImage TB_IMAGE = ImageUtil.getResourceStreamFromClass(getClass(), "teleblock.png");
|
||||
private final BufferedImage VENG_IMAGE = ImageUtil.getResourceStreamFromClass(getClass(), "veng.png");
|
||||
@Inject
|
||||
private Timers timers;
|
||||
private boolean lock;
|
||||
private long finishedAtTest;
|
||||
|
||||
|
||||
@Inject
|
||||
public FreezeTimersOverlay(FreezeTimersConfig config, Client client)
|
||||
public FreezeTimersOverlay(FreezeTimersConfig config, Client client, Timers timers)
|
||||
{
|
||||
this.config = config;
|
||||
this.client = client;
|
||||
this.timers = timers;
|
||||
setPriority(OverlayPriority.HIGHEST);
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.UNDER_WIDGETS);
|
||||
@@ -119,24 +119,23 @@ public class FreezeTimersOverlay extends Overlay
|
||||
String text = processTickCounter(finishedAt);
|
||||
int test = Integer.parseInt(text);
|
||||
Point poi = actor.getCanvasTextLocation(g, text, 0);
|
||||
|
||||
if (poi == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int xpoi = poi.getX();
|
||||
int ypoi = poi.getY();
|
||||
Point FixedPoint = new Point(xpoi, ypoi);
|
||||
Point FixedPoint = new Point(poi.getX(), poi.getY());
|
||||
|
||||
if (config.noImage())
|
||||
{
|
||||
if (test > 3)
|
||||
{
|
||||
renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.WHITE, FixedPoint);
|
||||
OverlayUtil.renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.WHITE, FixedPoint, false, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.YELLOW, FixedPoint);
|
||||
OverlayUtil.renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.YELLOW, FixedPoint, false, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -161,23 +160,26 @@ public class FreezeTimersOverlay extends Overlay
|
||||
|
||||
String text = processTickCounter(finishedAt);
|
||||
Point poi = actor.getCanvasTextLocation(g, text, 0);
|
||||
int xpoi = poi.getX() + 20;
|
||||
int ypoi = poi.getY();
|
||||
Point FixedPoint = new Point(xpoi, ypoi);
|
||||
|
||||
if (poi == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Point FixedPoint = new Point(poi.getX() + 20, poi.getY());
|
||||
if (config.noImage())
|
||||
{
|
||||
if (timers.getTimerEnd(actor, TimerType.FREEZE) <= currentTick)
|
||||
{
|
||||
renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, poi);
|
||||
OverlayUtil.renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, poi, false, 0);
|
||||
}
|
||||
if (timers.getTimerEnd(actor, TimerType.FREEZE) >= currentTick)
|
||||
{
|
||||
renderTextLocation(g, " | " + text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, FixedPoint);
|
||||
OverlayUtil.renderTextLocation(g, " | " + text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, FixedPoint, false, 0);
|
||||
}
|
||||
if (timers.getTimerEnd(actor, TimerType.VENG) >= currentTick)
|
||||
{
|
||||
renderTextLocation(g, " | " + text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, FixedPoint);
|
||||
OverlayUtil.renderTextLocation(g, " | " + text, config.textSize(), config.fontStyle().getFont(), Color.CYAN, FixedPoint, false, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -202,22 +204,26 @@ public class FreezeTimersOverlay extends Overlay
|
||||
|
||||
String text = processTickCounter(finishedAt);
|
||||
Point poi = actor.getCanvasTextLocation(g, text, 0);
|
||||
int xpoi = poi.getX() - 20;
|
||||
int ypoi = poi.getY();
|
||||
Point FixedPoint = new Point(xpoi, ypoi);
|
||||
|
||||
if (poi == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Point FixedPoint = new Point(poi.getX() - 20, poi.getY());
|
||||
if (config.noImage())
|
||||
{
|
||||
if (timers.getTimerEnd(actor, TimerType.FREEZE) <= currentTick)
|
||||
{
|
||||
renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.RED, poi);
|
||||
OverlayUtil.renderTextLocation(g, text, config.textSize(), config.fontStyle().getFont(), Color.RED, poi, false, 0);
|
||||
}
|
||||
if (timers.getTimerEnd(actor, TimerType.FREEZE) >= currentTick)
|
||||
{
|
||||
renderTextLocation(g, text + " | ", config.textSize(), config.fontStyle().getFont(), Color.RED, FixedPoint);
|
||||
OverlayUtil.renderTextLocation(g, text + " | ", config.textSize(), config.fontStyle().getFont(), Color.RED, FixedPoint, false, 0);
|
||||
}
|
||||
if (timers.getTimerEnd(actor, TimerType.TELEBLOCK) >= currentTick)
|
||||
{
|
||||
renderTextLocation(g, text + " | ", config.textSize(), config.fontStyle().getFont(), Color.RED, FixedPoint);
|
||||
OverlayUtil.renderTextLocation(g, text + " | ", config.textSize(), config.fontStyle().getFont(), Color.RED, FixedPoint, false, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -229,10 +235,13 @@ public class FreezeTimersOverlay extends Overlay
|
||||
|
||||
g.setColor(RED);
|
||||
Polygon poly = actor.getCanvasTilePoly();
|
||||
if (poly != null)
|
||||
|
||||
if (poly == null)
|
||||
{
|
||||
OverlayUtil.renderPolygon(g, poly, RED);
|
||||
return false;
|
||||
}
|
||||
|
||||
OverlayUtil.renderPolygon(g, poly, RED);
|
||||
OverlayUtil.renderTextLocation(g, new Point((int) poly.getBounds2D().getCenterX(),
|
||||
(int) poly.getBounds2D().getCenterY()), actor.getName(), RED);
|
||||
}
|
||||
@@ -249,22 +258,6 @@ public class FreezeTimersOverlay extends Overlay
|
||||
xOffset);
|
||||
}
|
||||
|
||||
private void renderTextLocation(Graphics2D graphics, String txtString, int fontSize, int fontStyle, Color fontColor, Point canvasPoint)
|
||||
{
|
||||
graphics.setFont(new Font("Arial", fontStyle, fontSize));
|
||||
if (canvasPoint != null)
|
||||
{
|
||||
final Point canvasCenterPoint = new Point(
|
||||
canvasPoint.getX(),
|
||||
canvasPoint.getY());
|
||||
final Point canvasCenterPoint_shadow = new Point(
|
||||
canvasPoint.getX() + 1,
|
||||
canvasPoint.getY() + 1);
|
||||
OverlayUtil.renderTextLocation(graphics, canvasCenterPoint_shadow, txtString, Color.BLACK);
|
||||
OverlayUtil.renderTextLocation(graphics, canvasCenterPoint, txtString, fontColor);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderImageLocation(Graphics2D graphics, Point imgLoc, BufferedImage image)
|
||||
{
|
||||
int x = imgLoc.getX();
|
||||
@@ -273,12 +266,9 @@ public class FreezeTimersOverlay extends Overlay
|
||||
graphics.drawImage(image, x, y, null);
|
||||
}
|
||||
|
||||
public void renderActorTextAndImage(Graphics2D graphics, Actor actor, String text, Color color,
|
||||
BufferedImage image, int yOffset, int xOffset)
|
||||
private void renderActorTextAndImage(Graphics2D graphics, Actor actor, String text, Color color, BufferedImage image, int yOffset, int xOffset)
|
||||
{
|
||||
Point textLocation = new Point(actor.getCanvasImageLocation(image, 0).getX() + xOffset,
|
||||
actor.getCanvasImageLocation(image, 0).getY() + yOffset);
|
||||
|
||||
Point textLocation = new Point(actor.getCanvasImageLocation(image, 0).getX() + xOffset, actor.getCanvasImageLocation(image, 0).getY() + yOffset);
|
||||
renderImageLocation(graphics, textLocation, image);
|
||||
xOffset = image.getWidth() + 1;
|
||||
yOffset = (image.getHeight() - (int) graphics.getFontMetrics().getStringBounds(text, graphics).getHeight());
|
||||
|
||||
@@ -30,14 +30,13 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.events.GameTick;
|
||||
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.client.config.ConfigManager;
|
||||
@@ -119,6 +118,11 @@ public class ImplingsPlugin extends Plugin
|
||||
{
|
||||
Impling impling = Impling.findImpling(npc.getId());
|
||||
|
||||
if (impling == null || impling.getImplingType() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImplingType type = impling.getImplingType();
|
||||
if (implingCounterMap.containsKey(type))
|
||||
{
|
||||
|
||||
@@ -62,4 +62,14 @@ public interface InterfaceStylesConfig extends Config
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "rsCrossSprites",
|
||||
name = "RuneScape cross sprites",
|
||||
description = "Replaces left-click cross sprites with the ones in RuneScape"
|
||||
)
|
||||
default boolean rsCrossSprites()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -31,11 +31,13 @@ import java.awt.image.BufferedImage;
|
||||
import javax.inject.Inject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.HealthBar;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.Sprite;
|
||||
import net.runelite.api.events.BeforeMenuRender;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.PostHealthBar;
|
||||
import net.runelite.api.events.WidgetPositioned;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
@@ -69,6 +71,8 @@ public class InterfaceStylesPlugin extends Plugin
|
||||
@Inject
|
||||
private SpriteManager spriteManager;
|
||||
|
||||
private Sprite[] defaultCrossSprites;
|
||||
|
||||
@Provides
|
||||
InterfaceStylesConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
@@ -89,6 +93,7 @@ public class InterfaceStylesPlugin extends Plugin
|
||||
restoreWidgetDimensions();
|
||||
removeGameframe();
|
||||
restoreHealthBars();
|
||||
restoreCrossSprites();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -126,6 +131,22 @@ public class InterfaceStylesPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged gameStateChanged)
|
||||
{
|
||||
if (gameStateChanged.getGameState() != GameState.LOGIN_SCREEN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The cross sprites aren't loaded yet when the initial config change event is received.
|
||||
* So run the overriding for cross sprites when we reach the login screen,
|
||||
* at which point the cross sprites will have been loaded.
|
||||
*/
|
||||
overrideCrossSprites();
|
||||
}
|
||||
|
||||
private void updateAllOverrides()
|
||||
{
|
||||
removeGameframe();
|
||||
@@ -134,6 +155,7 @@ public class InterfaceStylesPlugin extends Plugin
|
||||
restoreWidgetDimensions();
|
||||
adjustWidgetDimensions();
|
||||
overrideHealthBars();
|
||||
overrideCrossSprites();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -283,6 +305,62 @@ public class InterfaceStylesPlugin extends Plugin
|
||||
clientThread.invokeLater(client::resetHealthBarCaches);
|
||||
}
|
||||
|
||||
private void overrideCrossSprites()
|
||||
{
|
||||
if (config.rsCrossSprites())
|
||||
{
|
||||
// If we've already replaced them,
|
||||
// we don't need to replace them again
|
||||
if (defaultCrossSprites != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Sprite[] crossSprites = client.getCrossSprites();
|
||||
|
||||
if (crossSprites == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
defaultCrossSprites = new Sprite[crossSprites.length];
|
||||
System.arraycopy(crossSprites, 0, defaultCrossSprites, 0, defaultCrossSprites.length);
|
||||
|
||||
for (int i = 0; i < crossSprites.length; i++)
|
||||
{
|
||||
Sprite newSprite = getFileSpritePixels("rs3/cross_sprites/" + i + ".png");
|
||||
|
||||
if (newSprite == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
crossSprites[i] = newSprite;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
restoreCrossSprites();
|
||||
}
|
||||
}
|
||||
|
||||
private void restoreCrossSprites()
|
||||
{
|
||||
if (defaultCrossSprites == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Sprite[] crossSprites = client.getCrossSprites();
|
||||
|
||||
if (crossSprites != null && defaultCrossSprites.length == crossSprites.length)
|
||||
{
|
||||
System.arraycopy(defaultCrossSprites, 0, crossSprites, 0, defaultCrossSprites.length);
|
||||
}
|
||||
|
||||
defaultCrossSprites = null;
|
||||
}
|
||||
|
||||
private void restoreWidgetDimensions()
|
||||
{
|
||||
for (WidgetOffset widgetOffset : WidgetOffset.values())
|
||||
|
||||
@@ -118,33 +118,33 @@ enum WidgetOffset
|
||||
FIXED_2005_INTERFACE_CONTAINER(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_INTERFACE_CONTAINER, 7, null, null, null),
|
||||
FIXED_2005_BANK_CONTAINER(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_BANK_CONTAINER, 7, null, null, null),
|
||||
FIXED_2005_COMBAT_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_COMBAT_TAB, 19, 2, null, null),
|
||||
FIXED_2005_COMBAT_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_COMBAT_ICON, 26, null, null, null),
|
||||
FIXED_2005_COMBAT_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_COMBAT_ICON, 28, 1, null, null),
|
||||
FIXED_2005_STATS_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_STATS_TAB, 55, null, 30, null),
|
||||
FIXED_2005_STATS_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_STATS_ICON, 53, null, null, null),
|
||||
FIXED_2005_STATS_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_STATS_ICON, 51, null, null, null),
|
||||
FIXED_2005_QUESTS_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_QUESTS_TAB, 82, 1, 30, null),
|
||||
FIXED_2005_QUESTS_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_QUESTS_ICON, 81, null, null, null),
|
||||
FIXED_2005_QUESTS_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_QUESTS_ICON, 80, null, null, null),
|
||||
FIXED_2005_INVENTORY_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_INVENTORY_TAB, null, null, 45, null),
|
||||
FIXED_2005_INVENTORY_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_INVENTORY_ICON, 115, null, null, null),
|
||||
FIXED_2005_INVENTORY_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_INVENTORY_ICON, 113, 1, null, null),
|
||||
FIXED_2005_EQUIPMENT_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_EQUIPMENT_TAB, 153, 1, 30, null),
|
||||
FIXED_2005_EQUIPMENT_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_EQUIPMENT_ICON, 152, 4, null, null),
|
||||
FIXED_2005_EQUIPMENT_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_EQUIPMENT_ICON, 151, 4, null, null),
|
||||
FIXED_2005_PRAYER_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_PRAYER_TAB, 180, null, 32, null),
|
||||
FIXED_2005_PRAYER_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_PRAYER_ICON, 180, null, null, null),
|
||||
FIXED_2005_PRAYER_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_PRAYER_ICON, 178, null, null, null),
|
||||
FIXED_2005_MAGIC_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_MAGIC_TAB, 209, 1, 30, null),
|
||||
FIXED_2005_MAGIC_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_MAGIC_ICON, 206, 3, null, null),
|
||||
FIXED_2005_MAGIC_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_MAGIC_ICON, 206, 2, null, null),
|
||||
FIXED_2005_CLAN_CHAT_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_CLAN_CHAT_TAB, 15, null, null, null),
|
||||
FIXED_2005_CLAN_CHAT_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_CLAN_CHAT_ICON, 22, 0, null, null),
|
||||
FIXED_2005_FRIENDS_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_FRIENDS_TAB, 51, null, 30, null),
|
||||
FIXED_2005_FRIENDS_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_FRIENDS_ICON, 50, null, null, null),
|
||||
FIXED_2005_FRIENDS_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_FRIENDS_ICON, 49, -1, null, null),
|
||||
FIXED_2005_IGNORES_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_IGNORES_TAB, 79, null, 30, null),
|
||||
FIXED_2005_IGNORES_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_IGNORES_ICON, 78, null, null, null),
|
||||
FIXED_2005_LOGOUT_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_LOGOUT_TAB, 107, 1, 45, null),
|
||||
FIXED_2005_LOGOUT_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_LOGOUT_ICON, 114, 1, null, null),
|
||||
FIXED_2005_LOGOUT_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_LOGOUT_ICON, 112, null, null, null),
|
||||
FIXED_2005_OPTIONS_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_OPTIONS_TAB, 150, null, 30, null),
|
||||
FIXED_2005_OPTIONS_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_OPTIONS_ICON, 149, null, null, null),
|
||||
FIXED_2005_OPTIONS_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_OPTIONS_ICON, 148, -1, null, null),
|
||||
FIXED_2005_EMOTES_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_EMOTES_TAB, 178, null, 30, null),
|
||||
FIXED_2005_EMOTES_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_EMOTES_ICON, 179, null, null, null),
|
||||
FIXED_2005_EMOTES_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_EMOTES_ICON, 178, 1, null, null),
|
||||
FIXED_2005_MUSIC_HIGHLIGHT(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_MUSIC_TAB, 206, null, 30, null),
|
||||
FIXED_2005_MUSIC_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_MUSIC_ICON, 202, 5, null, null);
|
||||
FIXED_2005_MUSIC_ICON(Skin.AROUND_2005, WidgetInfo.FIXED_VIEWPORT_MUSIC_ICON, 202, 2, null, null);
|
||||
|
||||
private Skin skin;
|
||||
private WidgetInfo widgetInfo;
|
||||
|
||||
@@ -173,10 +173,10 @@ public interface ItemChargeConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showBellowCharges",
|
||||
name = "Show Bellow Charges",
|
||||
description = "Configures if ogre bellow item charge is shown",
|
||||
position = 12
|
||||
keyName = "showBellowCharges",
|
||||
name = "Show Bellow Charges",
|
||||
description = "Configures if ogre bellow item charge is shown",
|
||||
position = 12
|
||||
)
|
||||
default boolean showBellowCharges()
|
||||
{
|
||||
@@ -184,10 +184,32 @@ public interface ItemChargeConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showAbyssalBraceletCharges",
|
||||
name = "Show Abyssal Bracelet Charges",
|
||||
description = "Configures if abyssal bracelet item charge is shown",
|
||||
position = 13
|
||||
keyName = "showBasketCharges",
|
||||
name = "Show Basket Charges",
|
||||
description = "Configures if fruit basket item charge is shown",
|
||||
position = 13
|
||||
)
|
||||
default boolean showBasketCharges()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showSackCharges",
|
||||
name = "Show Sack Charges",
|
||||
description = "Configures if sack item charge is shown",
|
||||
position = 14
|
||||
)
|
||||
default boolean showSackCharges()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showAbyssalBraceletCharges",
|
||||
name = "Show Abyssal Bracelet Charges",
|
||||
description = "Configures if abyssal bracelet item charge is shown",
|
||||
position = 15
|
||||
)
|
||||
default boolean showAbyssalBraceletCharges()
|
||||
{
|
||||
@@ -198,7 +220,7 @@ public interface ItemChargeConfig extends Config
|
||||
keyName = "recoilNotification",
|
||||
name = "Ring of Recoil Notification",
|
||||
description = "Configures if the ring of recoil breaking notification is shown",
|
||||
position = 14
|
||||
position = 16
|
||||
)
|
||||
default boolean recoilNotification()
|
||||
{
|
||||
@@ -209,7 +231,7 @@ public interface ItemChargeConfig extends Config
|
||||
keyName = "showBindingNecklaceCharges",
|
||||
name = "Show Binding Necklace Charges",
|
||||
description = "Configures if binding necklace item charge is shown",
|
||||
position = 15
|
||||
position = 17
|
||||
)
|
||||
default boolean showBindingNecklaceCharges()
|
||||
{
|
||||
@@ -238,7 +260,7 @@ public interface ItemChargeConfig extends Config
|
||||
keyName = "bindingNotification",
|
||||
name = "Binding Necklace Notification",
|
||||
description = "Configures if the binding necklace breaking notification is shown",
|
||||
position = 16
|
||||
position = 18
|
||||
)
|
||||
default boolean bindingNotification()
|
||||
{
|
||||
@@ -249,7 +271,7 @@ public interface ItemChargeConfig extends Config
|
||||
keyName = "showExplorerRingCharges",
|
||||
name = "Show Explorer's Ring Alch Charges",
|
||||
description = "Configures if explorer's ring alchemy charges are shown",
|
||||
position = 17
|
||||
position = 19
|
||||
)
|
||||
default boolean showExplorerRingCharges()
|
||||
{
|
||||
@@ -278,7 +300,7 @@ public interface ItemChargeConfig extends Config
|
||||
keyName = "showInfoboxes",
|
||||
name = "Show Infoboxes",
|
||||
description = "Configures whether to show an infobox equipped charge items",
|
||||
position = 18
|
||||
position = 20
|
||||
)
|
||||
default boolean showInfoboxes()
|
||||
{
|
||||
|
||||
@@ -38,6 +38,8 @@ import static net.runelite.client.plugins.itemcharges.ItemChargeType.IMPBOX;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.TELEPORT;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERCAN;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERSKIN;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.FRUIT_BASKET;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.SACK;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.overlay.WidgetItemOverlay;
|
||||
import net.runelite.client.ui.overlay.components.TextComponent;
|
||||
@@ -152,6 +154,8 @@ class ItemChargeOverlay extends WidgetItemOverlay
|
||||
|| (type == WATERCAN && !config.showWateringCanCharges())
|
||||
|| (type == WATERSKIN && !config.showWaterskinCharges())
|
||||
|| (type == BELLOWS && !config.showBellowCharges())
|
||||
|| (type == FRUIT_BASKET && !config.showBasketCharges())
|
||||
|| (type == SACK && !config.showSackCharges())
|
||||
|| (type == ABYSSAL_BRACELET && !config.showAbyssalBraceletCharges()))
|
||||
{
|
||||
return;
|
||||
@@ -172,6 +176,7 @@ class ItemChargeOverlay extends WidgetItemOverlay
|
||||
{
|
||||
return config.showTeleportCharges() || config.showDodgyCount() || config.showFungicideCharges()
|
||||
|| config.showImpCharges() || config.showWateringCanCharges() || config.showWaterskinCharges()
|
||||
|| config.showBellowCharges() || config.showAbyssalBraceletCharges() || config.showExplorerRingCharges();
|
||||
|| config.showBellowCharges() || config.showBasketCharges() || config.showSackCharges()
|
||||
|| config.showAbyssalBraceletCharges() || config.showExplorerRingCharges();
|
||||
}
|
||||
}
|
||||
@@ -37,5 +37,7 @@ enum ItemChargeType
|
||||
BRACELET_OF_SLAUGHTER,
|
||||
EXPEDITIOUS_BRACELET,
|
||||
BINDING_NECKLACE,
|
||||
EXPLORER_RING
|
||||
EXPLORER_RING,
|
||||
FRUIT_BASKET,
|
||||
SACK
|
||||
}
|
||||
|
||||
@@ -29,133 +29,8 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import static net.runelite.api.ItemID.ABYSSAL_BRACELET1;
|
||||
import static net.runelite.api.ItemID.ABYSSAL_BRACELET2;
|
||||
import static net.runelite.api.ItemID.ABYSSAL_BRACELET3;
|
||||
import static net.runelite.api.ItemID.ABYSSAL_BRACELET4;
|
||||
import static net.runelite.api.ItemID.ABYSSAL_BRACELET5;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY1;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY2;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY3;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY4;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY5;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY6;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T1;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T2;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T3;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T4;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T5;
|
||||
import static net.runelite.api.ItemID.AMULET_OF_GLORY_T6;
|
||||
import static net.runelite.api.ItemID.BURNING_AMULET1;
|
||||
import static net.runelite.api.ItemID.BURNING_AMULET2;
|
||||
import static net.runelite.api.ItemID.BURNING_AMULET3;
|
||||
import static net.runelite.api.ItemID.BURNING_AMULET4;
|
||||
import static net.runelite.api.ItemID.BURNING_AMULET5;
|
||||
import static net.runelite.api.ItemID.COMBAT_BRACELET1;
|
||||
import static net.runelite.api.ItemID.COMBAT_BRACELET2;
|
||||
import static net.runelite.api.ItemID.COMBAT_BRACELET3;
|
||||
import static net.runelite.api.ItemID.COMBAT_BRACELET4;
|
||||
import static net.runelite.api.ItemID.COMBAT_BRACELET5;
|
||||
import static net.runelite.api.ItemID.COMBAT_BRACELET6;
|
||||
import static net.runelite.api.ItemID.DIGSITE_PENDANT_1;
|
||||
import static net.runelite.api.ItemID.DIGSITE_PENDANT_2;
|
||||
import static net.runelite.api.ItemID.DIGSITE_PENDANT_3;
|
||||
import static net.runelite.api.ItemID.DIGSITE_PENDANT_4;
|
||||
import static net.runelite.api.ItemID.DIGSITE_PENDANT_5;
|
||||
import static net.runelite.api.ItemID.ENCHANTED_LYRE1;
|
||||
import static net.runelite.api.ItemID.ENCHANTED_LYRE2;
|
||||
import static net.runelite.api.ItemID.ENCHANTED_LYRE3;
|
||||
import static net.runelite.api.ItemID.ENCHANTED_LYRE4;
|
||||
import static net.runelite.api.ItemID.ENCHANTED_LYRE5;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_0;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_1;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_10;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_2;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_3;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_4;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_5;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_6;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_7;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_8;
|
||||
import static net.runelite.api.ItemID.FUNGICIDE_SPRAY_9;
|
||||
import static net.runelite.api.ItemID.GAMES_NECKLACE1;
|
||||
import static net.runelite.api.ItemID.GAMES_NECKLACE2;
|
||||
import static net.runelite.api.ItemID.GAMES_NECKLACE3;
|
||||
import static net.runelite.api.ItemID.GAMES_NECKLACE4;
|
||||
import static net.runelite.api.ItemID.GAMES_NECKLACE5;
|
||||
import static net.runelite.api.ItemID.GAMES_NECKLACE6;
|
||||
import static net.runelite.api.ItemID.GAMES_NECKLACE7;
|
||||
import static net.runelite.api.ItemID.GAMES_NECKLACE8;
|
||||
import static net.runelite.api.ItemID.IMPINABOX1;
|
||||
import static net.runelite.api.ItemID.IMPINABOX2;
|
||||
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE1;
|
||||
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE2;
|
||||
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE3;
|
||||
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE4;
|
||||
import static net.runelite.api.ItemID.NECKLACE_OF_PASSAGE5;
|
||||
import static net.runelite.api.ItemID.OGRE_BELLOWS;
|
||||
import static net.runelite.api.ItemID.OGRE_BELLOWS_1;
|
||||
import static net.runelite.api.ItemID.OGRE_BELLOWS_2;
|
||||
import static net.runelite.api.ItemID.OGRE_BELLOWS_3;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_1;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_2;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_3;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_4;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_5;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_6;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_7;
|
||||
import static net.runelite.api.ItemID.PHARAOHS_SCEPTRE_8;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING1;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING2;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING3;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING4;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING5;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING6;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING7;
|
||||
import static net.runelite.api.ItemID.RING_OF_DUELING8;
|
||||
import static net.runelite.api.ItemID.RING_OF_RETURNING1;
|
||||
import static net.runelite.api.ItemID.RING_OF_RETURNING2;
|
||||
import static net.runelite.api.ItemID.RING_OF_RETURNING3;
|
||||
import static net.runelite.api.ItemID.RING_OF_RETURNING4;
|
||||
import static net.runelite.api.ItemID.RING_OF_RETURNING5;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_1;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_2;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_3;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_4;
|
||||
import static net.runelite.api.ItemID.RING_OF_WEALTH_5;
|
||||
import static net.runelite.api.ItemID.SKILLS_NECKLACE1;
|
||||
import static net.runelite.api.ItemID.SKILLS_NECKLACE2;
|
||||
import static net.runelite.api.ItemID.SKILLS_NECKLACE3;
|
||||
import static net.runelite.api.ItemID.SKILLS_NECKLACE4;
|
||||
import static net.runelite.api.ItemID.SKILLS_NECKLACE5;
|
||||
import static net.runelite.api.ItemID.SKILLS_NECKLACE6;
|
||||
import static net.runelite.api.ItemID.SLAYER_RING_1;
|
||||
import static net.runelite.api.ItemID.SLAYER_RING_2;
|
||||
import static net.runelite.api.ItemID.SLAYER_RING_3;
|
||||
import static net.runelite.api.ItemID.SLAYER_RING_4;
|
||||
import static net.runelite.api.ItemID.SLAYER_RING_5;
|
||||
import static net.runelite.api.ItemID.SLAYER_RING_6;
|
||||
import static net.runelite.api.ItemID.SLAYER_RING_7;
|
||||
import static net.runelite.api.ItemID.SLAYER_RING_8;
|
||||
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_1;
|
||||
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_2;
|
||||
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_3;
|
||||
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_4;
|
||||
import static net.runelite.api.ItemID.TELEPORT_CRYSTAL_5;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN1;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN2;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN3;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN4;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN5;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN6;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN7;
|
||||
import static net.runelite.api.ItemID.WATERING_CAN8;
|
||||
import static net.runelite.api.ItemID.WATERSKIN0;
|
||||
import static net.runelite.api.ItemID.WATERSKIN1;
|
||||
import static net.runelite.api.ItemID.WATERSKIN2;
|
||||
import static net.runelite.api.ItemID.WATERSKIN3;
|
||||
import static net.runelite.api.ItemID.WATERSKIN4;
|
||||
|
||||
import static net.runelite.api.ItemID.*;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.ABYSSAL_BRACELET;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.BELLOWS;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.FUNGICIDE_SPRAY;
|
||||
@@ -163,6 +38,8 @@ import static net.runelite.client.plugins.itemcharges.ItemChargeType.IMPBOX;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.TELEPORT;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERCAN;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.WATERSKIN;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.FRUIT_BASKET;
|
||||
import static net.runelite.client.plugins.itemcharges.ItemChargeType.SACK;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@@ -173,6 +50,31 @@ enum ItemWithCharge
|
||||
ABRACE3(ABYSSAL_BRACELET, ABYSSAL_BRACELET3, 3),
|
||||
ABRACE4(ABYSSAL_BRACELET, ABYSSAL_BRACELET4, 4),
|
||||
ABRACE5(ABYSSAL_BRACELET, ABYSSAL_BRACELET5, 5),
|
||||
BASKET_APPLES1(FRUIT_BASKET, APPLES1, 1),
|
||||
BASKET_APPLES2(FRUIT_BASKET, APPLES2, 2),
|
||||
BASKET_APPLES3(FRUIT_BASKET, APPLES3, 3),
|
||||
BASKET_APPLES4(FRUIT_BASKET, APPLES4, 4),
|
||||
BASKET_APPLES5(FRUIT_BASKET, APPLES5, 5),
|
||||
BASKET_BANANAS1(FRUIT_BASKET, BANANAS1, 1),
|
||||
BASKET_BANANAS2(FRUIT_BASKET, BANANAS2, 2),
|
||||
BASKET_BANANAS3(FRUIT_BASKET, BANANAS3, 3),
|
||||
BASKET_BANANAS4(FRUIT_BASKET, BANANAS4, 4),
|
||||
BASKET_BANANAS5(FRUIT_BASKET, BANANAS5, 5),
|
||||
BASKET_ORANGES1(FRUIT_BASKET, ORANGES1, 1),
|
||||
BASKET_ORANGES2(FRUIT_BASKET, ORANGES2, 2),
|
||||
BASKET_ORANGES3(FRUIT_BASKET, ORANGES3, 3),
|
||||
BASKET_ORANGES4(FRUIT_BASKET, ORANGES4, 4),
|
||||
BASKET_ORANGES5(FRUIT_BASKET, ORANGES5, 5),
|
||||
BASKET_STRAWBERRIES1(FRUIT_BASKET, STRAWBERRIES1, 1),
|
||||
BASKET_STRAWBERRIES2(FRUIT_BASKET, STRAWBERRIES2, 2),
|
||||
BASKET_STRAWBERRIES3(FRUIT_BASKET, STRAWBERRIES3, 3),
|
||||
BASKET_STRAWBERRIES4(FRUIT_BASKET, STRAWBERRIES4, 4),
|
||||
BASKET_STRAWBERRIES5(FRUIT_BASKET, STRAWBERRIES5, 5),
|
||||
BASKET_TOMATOES1(FRUIT_BASKET, TOMATOES1, 1),
|
||||
BASKET_TOMATOES2(FRUIT_BASKET, TOMATOES2, 2),
|
||||
BASKET_TOMATOES3(FRUIT_BASKET, TOMATOES3, 3),
|
||||
BASKET_TOMATOES4(FRUIT_BASKET, TOMATOES4, 4),
|
||||
BASKET_TOMATOES5(FRUIT_BASKET, TOMATOES5, 5),
|
||||
BELLOWS0(BELLOWS, OGRE_BELLOWS, 0),
|
||||
BELLOWS1(BELLOWS, OGRE_BELLOWS_1, 1),
|
||||
BELLOWS2(BELLOWS, OGRE_BELLOWS_2, 2),
|
||||
@@ -270,6 +172,36 @@ enum ItemWithCharge
|
||||
ROW3(TELEPORT, RING_OF_WEALTH_3, 3),
|
||||
ROW4(TELEPORT, RING_OF_WEALTH_4, 4),
|
||||
ROW5(TELEPORT, RING_OF_WEALTH_5, 5),
|
||||
SACK_CABBAGES1(SACK, CABBAGES1, 1),
|
||||
SACK_CABBAGES2(SACK, CABBAGES2, 2),
|
||||
SACK_CABBAGES3(SACK, CABBAGES3, 3),
|
||||
SACK_CABBAGES4(SACK, CABBAGES4, 4),
|
||||
SACK_CABBAGES5(SACK, CABBAGES5, 5),
|
||||
SACK_CABBAGES6(SACK, CABBAGES6, 6),
|
||||
SACK_CABBAGES7(SACK, CABBAGES7, 7),
|
||||
SACK_CABBAGES8(SACK, CABBAGES8, 8),
|
||||
SACK_CABBAGES9(SACK, CABBAGES9, 9),
|
||||
SACK_CABBAGES10(SACK, CABBAGES10, 10),
|
||||
SACK_ONIONS1(SACK, ONIONS1, 1),
|
||||
SACK_ONIONS2(SACK, ONIONS2, 2),
|
||||
SACK_ONIONS3(SACK, ONIONS3, 3),
|
||||
SACK_ONIONS4(SACK, ONIONS4, 4),
|
||||
SACK_ONIONS5(SACK, ONIONS5, 5),
|
||||
SACK_ONIONS6(SACK, ONIONS6, 6),
|
||||
SACK_ONIONS7(SACK, ONIONS7, 7),
|
||||
SACK_ONIONS8(SACK, ONIONS8, 8),
|
||||
SACK_ONIONS9(SACK, ONIONS9, 9),
|
||||
SACK_ONIONS10(SACK, ONIONS10, 10),
|
||||
SACK_POTATOES1(SACK, POTATOES1, 1),
|
||||
SACK_POTATOES2(SACK, POTATOES2, 2),
|
||||
SACK_POTATOES3(SACK, POTATOES3, 3),
|
||||
SACK_POTATOES4(SACK, POTATOES4, 4),
|
||||
SACK_POTATOES5(SACK, POTATOES5, 5),
|
||||
SACK_POTATOES6(SACK, POTATOES6, 6),
|
||||
SACK_POTATOES7(SACK, POTATOES7, 7),
|
||||
SACK_POTATOES8(SACK, POTATOES8, 8),
|
||||
SACK_POTATOES9(SACK, POTATOES9, 9),
|
||||
SACK_POTATOES10(SACK, POTATOES10, 10),
|
||||
SKILLS1(TELEPORT, SKILLS_NECKLACE1, 1),
|
||||
SKILLS2(TELEPORT, SKILLS_NECKLACE2, 2),
|
||||
SKILLS3(TELEPORT, SKILLS_NECKLACE3, 3),
|
||||
|
||||
@@ -129,9 +129,12 @@ public class LootTrackerPlugin extends Plugin
|
||||
|
||||
// Chest loot handling
|
||||
private static final String CHEST_LOOTED_MESSAGE = "You find some treasure in the chest!";
|
||||
private static final Pattern LARRAN_LOOTED_PATTERN = Pattern.compile("You have opened Larran's (big|small) chest .*");
|
||||
private static final Map<Integer, String> CHEST_EVENT_TYPES = ImmutableMap.of(
|
||||
5179, "Brimstone Chest",
|
||||
11573, "Crystal Chest"
|
||||
11573, "Crystal Chest",
|
||||
12093, "Larran's big chest",
|
||||
13113, "Larran's small chest"
|
||||
);
|
||||
private static final File LOOT_RECORDS_FILE = new File(RuneLite.RUNELITE_DIR, "lootRecords.json");
|
||||
private static final Set<Integer> RESPAWN_REGIONS = ImmutableSet.of(
|
||||
@@ -545,7 +548,7 @@ public class LootTrackerPlugin extends Plugin
|
||||
|
||||
final String message = event.getMessage();
|
||||
|
||||
if (message.equals(CHEST_LOOTED_MESSAGE))
|
||||
if (message.equals(CHEST_LOOTED_MESSAGE) || LARRAN_LOOTED_PATTERN.matcher(message).matches())
|
||||
{
|
||||
final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
|
||||
if (!CHEST_EVENT_TYPES.containsKey(regionID))
|
||||
|
||||
@@ -1690,4 +1690,4 @@ default CharterOption charterOption()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -906,34 +906,28 @@ public class MenuEntrySwapperPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player[] players = client.getCachedPlayers();
|
||||
Player player = null;
|
||||
int identifier = event.getIdentifier();
|
||||
|
||||
if (identifier >= 0 && identifier < players.length)
|
||||
{
|
||||
player = players[identifier];
|
||||
}
|
||||
|
||||
if (player == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//If the option is already to walk there, or cancel we don't need to swap it with anything
|
||||
if (pOptionToReplace.equals(CANCEL) || pOptionToReplace.equals(WALK_HERE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!pOptionToReplace.equals(CANCEL) && !pOptionToReplace.equals(WALK_HERE))
|
||||
{
|
||||
Player[] players = client.getCachedPlayers();
|
||||
int identifier = event.getIdentifier();
|
||||
|
||||
if (((config.getRemoveFreezePlayerCoX() && client.getVar(Varbits.IN_RAID) == 1)
|
||||
|| (config.getRemoveFreezePlayerToB() && client.getVar(Varbits.THEATRE_OF_BLOOD) == 2))
|
||||
&& (player.isFriend() || player.isClanMember())
|
||||
&& CAST_OPTIONS_KEYWORDS.contains(pOptionToReplace))
|
||||
if (identifier >= 0 && identifier < players.length)
|
||||
{
|
||||
addswap(pOptionToReplace);
|
||||
Player player = players[identifier];
|
||||
if (player != null)
|
||||
{
|
||||
if (((config.getRemoveFreezePlayerCoX() && client.getVar(Varbits.IN_RAID) == 1)
|
||||
|| (config.getRemoveFreezePlayerToB() && client.getVar(Varbits.THEATRE_OF_BLOOD) == 2))
|
||||
&& (player.isFriend() || player.isClanMember())
|
||||
&& CAST_OPTIONS_KEYWORDS.contains(pOptionToReplace))
|
||||
{
|
||||
addswap(pOptionToReplace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (option.equals("talk-to"))
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ public enum DigsitePendantMode
|
||||
{
|
||||
DIGSITE("Digsite"),
|
||||
FOSSIL_ISLAND("Fossil Island"),
|
||||
LITHKREN("Lithkren");
|
||||
LITHKREN("Lithkren Dungeon");
|
||||
|
||||
private final String name;
|
||||
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
package net.runelite.client.plugins.npchighlight;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.NPC;
|
||||
@@ -38,7 +40,7 @@ class MemorizedNpc
|
||||
private int npcIndex;
|
||||
|
||||
@Getter
|
||||
private String npcName;
|
||||
private Set<String> npcNames;
|
||||
|
||||
@Getter
|
||||
private int npcSize;
|
||||
@@ -63,7 +65,8 @@ class MemorizedNpc
|
||||
|
||||
MemorizedNpc(NPC npc)
|
||||
{
|
||||
this.npcName = npc.getName();
|
||||
this.npcNames = new HashSet<>();
|
||||
this.npcNames.add(npc.getName());
|
||||
this.npcIndex = npc.getIndex();
|
||||
this.possibleRespawnLocations = new ArrayList<>();
|
||||
this.respawnTime = -1;
|
||||
|
||||
@@ -34,6 +34,7 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -58,6 +59,7 @@ import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.GraphicsObjectCreated;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NpcDefinitionChanged;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
@@ -304,14 +306,15 @@ public class NpcIndicatorsPlugin extends Plugin
|
||||
|
||||
if (removed)
|
||||
{
|
||||
highlightedNpcs.remove(npc);
|
||||
memorizedNpcs.remove(npc.getIndex());
|
||||
MemorizedNpc mn = memorizedNpcs.get(npc.getIndex());
|
||||
if (mn != null && isNpcMemorizationUnnecessary(mn))
|
||||
{
|
||||
memorizedNpcs.remove(npc.getIndex());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memorizeNpc(npc);
|
||||
npcTags.add(id);
|
||||
highlightedNpcs.add(npc);
|
||||
}
|
||||
|
||||
click.consume();
|
||||
@@ -320,30 +323,28 @@ public class NpcIndicatorsPlugin extends Plugin
|
||||
@Subscribe
|
||||
public void onNpcSpawned(NpcSpawned npcSpawned)
|
||||
{
|
||||
final NPC npc = npcSpawned.getNpc();
|
||||
final String npcName = npc.getName();
|
||||
NPC npc = npcSpawned.getNpc();
|
||||
highlightNpcIfMatch(npc);
|
||||
|
||||
if (npcName == null)
|
||||
if (memorizedNpcs.containsKey(npc.getIndex()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (npcTags.contains(npc.getIndex()))
|
||||
{
|
||||
memorizeNpc(npc);
|
||||
highlightedNpcs.add(npc);
|
||||
spawnedNpcsThisTick.add(npc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (String highlight : highlights)
|
||||
@Subscribe
|
||||
public void onNpcDefinitionChanged(NpcDefinitionChanged event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
highlightNpcIfMatch(npc);
|
||||
|
||||
MemorizedNpc mn = memorizedNpcs.get(npc.getIndex());
|
||||
if (mn != null)
|
||||
{
|
||||
if (WildcardMatcher.matches(highlight, npcName))
|
||||
String npcName = npc.getName();
|
||||
if (npcName != null)
|
||||
{
|
||||
memorizeNpc(npc);
|
||||
highlightedNpcs.add(npc);
|
||||
spawnedNpcsThisTick.add(npc);
|
||||
break;
|
||||
mn.getNpcNames().add(npcName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -428,12 +429,59 @@ public class NpcIndicatorsPlugin extends Plugin
|
||||
return new WorldPoint(currWP.getX() - dx, currWP.getY() - dy, currWP.getPlane());
|
||||
}
|
||||
|
||||
private void highlightNpcIfMatch(final NPC npc)
|
||||
{
|
||||
if (npcTags.contains(npc.getIndex()))
|
||||
{
|
||||
memorizeNpc(npc);
|
||||
highlightedNpcs.add(npc);
|
||||
return;
|
||||
}
|
||||
|
||||
final String npcName = npc.getName();
|
||||
if (npcName != null)
|
||||
{
|
||||
for (String highlight : highlights)
|
||||
{
|
||||
if (WildcardMatcher.matches(highlight, npcName))
|
||||
{
|
||||
memorizeNpc(npc);
|
||||
highlightedNpcs.add(npc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
highlightedNpcs.remove(npc);
|
||||
}
|
||||
|
||||
private void memorizeNpc(NPC npc)
|
||||
{
|
||||
final int npcIndex = npc.getIndex();
|
||||
memorizedNpcs.putIfAbsent(npcIndex, new MemorizedNpc(npc));
|
||||
}
|
||||
|
||||
private boolean isNpcMemorizationUnnecessary(final MemorizedNpc mn)
|
||||
{
|
||||
if (npcTags.contains(mn.getNpcIndex()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (String npcName : mn.getNpcNames())
|
||||
{
|
||||
for (String highlight : highlights)
|
||||
{
|
||||
if (WildcardMatcher.matches(highlight, npcName))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void removeOldHighlightedRespawns()
|
||||
{
|
||||
deadNpcsToDisplay.values().removeIf(x -> x.getDiedOnTick() + x.getRespawnTime() <= client.getTickCount() + 1);
|
||||
@@ -464,34 +512,21 @@ public class NpcIndicatorsPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
outer:
|
||||
Iterator<Map.Entry<Integer, MemorizedNpc>> it = memorizedNpcs.entrySet().iterator();
|
||||
while (it.hasNext())
|
||||
{
|
||||
MemorizedNpc mn = it.next().getValue();
|
||||
|
||||
if (isNpcMemorizationUnnecessary(mn))
|
||||
{
|
||||
deadNpcsToDisplay.remove(mn.getNpcIndex());
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
for (NPC npc : client.getNpcs())
|
||||
{
|
||||
final String npcName = npc.getName();
|
||||
|
||||
if (npcName == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (npcTags.contains(npc.getIndex()))
|
||||
{
|
||||
highlightedNpcs.add(npc);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String highlight : highlights)
|
||||
{
|
||||
if (WildcardMatcher.matches(highlight, npcName))
|
||||
{
|
||||
memorizeNpc(npc);
|
||||
highlightedNpcs.add(npc);
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
|
||||
// NPC is not highlighted
|
||||
memorizedNpcs.remove(npc.getIndex());
|
||||
highlightNpcIfMatch(npc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,7 +559,7 @@ public class NpcIndicatorsPlugin extends Plugin
|
||||
|
||||
if (!mn.getPossibleRespawnLocations().isEmpty())
|
||||
{
|
||||
log.debug("Starting {} tick countdown for {}", mn.getRespawnTime(), mn.getNpcName());
|
||||
log.debug("Starting {} tick countdown for {}", mn.getRespawnTime(), mn.getNpcNames().iterator().next());
|
||||
deadNpcsToDisplay.put(mn.getNpcIndex(), mn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Woox <https://github.com/wooxsolo>
|
||||
* Copyright (c) 2019, Ganom <https://github.com/Ganom>
|
||||
* Copyright (c) 2019, GeChallengeM <https://github.com/GeChallengeM>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -23,55 +22,63 @@
|
||||
* (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.fightcave;
|
||||
package net.runelite.client.plugins.npcstatus;
|
||||
|
||||
import java.awt.Color;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCDefinition;
|
||||
import net.runelite.api.coords.WorldArea;
|
||||
import net.runelite.api.Actor;
|
||||
|
||||
class NPCContainer
|
||||
@Getter
|
||||
class MemorizedNPC
|
||||
{
|
||||
|
||||
@Getter
|
||||
private NPC npc;
|
||||
|
||||
@Getter
|
||||
private int npcIndex;
|
||||
|
||||
@Getter
|
||||
private String npcName;
|
||||
|
||||
@Getter
|
||||
private int npcSize;
|
||||
|
||||
private int attackSpeed;
|
||||
@Setter
|
||||
@Getter
|
||||
private int TicksUntilAttack;
|
||||
|
||||
private int combatTimerEnd;
|
||||
@Setter
|
||||
@Getter
|
||||
private int npcSpeed;
|
||||
|
||||
private int timeLeft;
|
||||
@Setter
|
||||
@Getter
|
||||
private Actor npcInteracting;
|
||||
private int flinchTimerEnd;
|
||||
@Setter
|
||||
private Status status;
|
||||
@Setter
|
||||
private WorldArea lastnpcarea;
|
||||
@Setter
|
||||
private Actor lastinteracted;
|
||||
@Setter
|
||||
private int lastspotanimation;
|
||||
|
||||
|
||||
NPCContainer(NPC npc)
|
||||
MemorizedNPC(NPC npc, int attackSpeed, WorldArea worldArea)
|
||||
{
|
||||
this.npc = npc;
|
||||
this.npcName = npc.getName();
|
||||
this.npcIndex = npc.getIndex();
|
||||
this.npcInteracting = npc.getInteracting();
|
||||
this.npcSpeed = 0;
|
||||
this.TicksUntilAttack = 0;
|
||||
final NPCDefinition composition = npc.getTransformedDefinition();
|
||||
this.npcName = npc.getName();
|
||||
this.attackSpeed = attackSpeed;
|
||||
this.combatTimerEnd = -1;
|
||||
this.flinchTimerEnd = -1;
|
||||
this.timeLeft = 0;
|
||||
this.status = Status.OUT_OF_COMBAT;
|
||||
this.lastnpcarea = worldArea;
|
||||
this.lastinteracted = null;
|
||||
this.lastspotanimation = -1;
|
||||
}
|
||||
|
||||
if (composition != null)
|
||||
{
|
||||
this.npcSize = composition.getSize();
|
||||
}
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
enum Status
|
||||
{
|
||||
FLINCHING("Flinching", Color.GREEN),
|
||||
IN_COMBAT_DELAY("In Combat Delay", Color.ORANGE),
|
||||
IN_COMBAT("In Combat", Color.RED),
|
||||
OUT_OF_COMBAT("Out of Combat", Color.BLUE);
|
||||
|
||||
private String name;
|
||||
private Color color;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Devin French <https://github.com/devinfrench>
|
||||
* Copyright (c) 2019, GeChallengeM <https://github.com/GeChallengeM>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -22,32 +22,22 @@
|
||||
* (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.fightcave;
|
||||
package net.runelite.client.plugins.npcstatus;
|
||||
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
public enum JadAttack
|
||||
@ConfigGroup("npcstatus")
|
||||
public interface NpcStatusConfig extends Config
|
||||
{
|
||||
MAGIC(AnimationID.TZTOK_JAD_MAGIC_ATTACK, Prayer.PROTECT_FROM_MAGIC),
|
||||
RANGE(AnimationID.TZTOK_JAD_RANGE_ATTACK, Prayer.PROTECT_FROM_MISSILES);
|
||||
|
||||
private final int animation;
|
||||
private final Prayer prayer;
|
||||
|
||||
JadAttack(int animation, Prayer prayer)
|
||||
@ConfigItem(
|
||||
keyName = "AttackRange",
|
||||
name = "NPC Attack range",
|
||||
description = "The attack range of the NPC"
|
||||
)
|
||||
default int getRange()
|
||||
{
|
||||
this.animation = animation;
|
||||
this.prayer = prayer;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int getAnimation()
|
||||
{
|
||||
return animation;
|
||||
}
|
||||
|
||||
public Prayer getPrayer()
|
||||
{
|
||||
return prayer;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2018, GeChallengeM <https://github.com/GeChallengeM>
|
||||
* 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.npcstatus;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
public class NpcStatusOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final NpcStatusPlugin plugin;
|
||||
|
||||
@Inject
|
||||
NpcStatusOverlay(Client client, NpcStatusPlugin plugin)
|
||||
{
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_SCENE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
for (MemorizedNPC npc : plugin.getMemorizedNPCs())
|
||||
{
|
||||
if (npc.getNpc().getInteracting() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (npc.getNpc().getInteracting() == client.getLocalPlayer() || client.getLocalPlayer().getInteracting() == npc.getNpc())
|
||||
{
|
||||
switch (npc.getStatus())
|
||||
{
|
||||
case FLINCHING:
|
||||
npc.setTimeLeft(Math.max(0, npc.getFlinchTimerEnd() - client.getTickCount()));
|
||||
break;
|
||||
case IN_COMBAT_DELAY:
|
||||
npc.setTimeLeft(Math.max(0, npc.getCombatTimerEnd() - client.getTickCount() - 7));
|
||||
break;
|
||||
case IN_COMBAT:
|
||||
npc.setTimeLeft(Math.max(0, npc.getCombatTimerEnd() - client.getTickCount()));
|
||||
break;
|
||||
case OUT_OF_COMBAT:
|
||||
default:
|
||||
npc.setTimeLeft(0);
|
||||
break;
|
||||
}
|
||||
|
||||
Point textLocation = npc.getNpc().getCanvasTextLocation(graphics, Integer.toString(npc.getTimeLeft()), npc.getNpc().getLogicalHeight() + 40);
|
||||
|
||||
if (textLocation != null)
|
||||
{
|
||||
OverlayUtil.renderTextLocation(graphics, textLocation, Integer.toString(npc.getTimeLeft()), npc.getStatus().getColor());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 2019, GeChallengeM <https://github.com/GeChallengeM>
|
||||
* 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.npcstatus;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.GraphicID;
|
||||
import net.runelite.api.Hitsplat;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.coords.WorldArea;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.HitsplatApplied;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.NPCManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "NPC Status Timer",
|
||||
description = "Adds a timer on NPC's for their attacks and flinching.",
|
||||
tags = {"flinch", "npc"},
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class NpcStatusPlugin extends Plugin
|
||||
{
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Set<MemorizedNPC> memorizedNPCs = new HashSet<>();
|
||||
@Inject
|
||||
private Client client;
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
@Inject
|
||||
private NPCManager npcManager;
|
||||
@Inject
|
||||
private NpcStatusConfig config;
|
||||
@Inject
|
||||
private NpcStatusOverlay npcStatusOverlay;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Instant lastTickUpdate;
|
||||
private WorldArea lastPlayerLocation;
|
||||
|
||||
@Provides
|
||||
NpcStatusConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(NpcStatusConfig.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
overlayManager.add(npcStatusOverlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
overlayManager.remove(npcStatusOverlay);
|
||||
memorizedNPCs.clear();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcSpawned(NpcSpawned npcSpawned)
|
||||
{
|
||||
final NPC npc = npcSpawned.getNpc();
|
||||
final String npcName = npc.getName();
|
||||
|
||||
if (npcName == null || !Arrays.asList(npc.getDefinition().getActions()).contains("Attack"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
memorizedNPCs.add(new MemorizedNPC(npc, npcManager.getAttackSpeed(npc.getId()), npc.getWorldArea()));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcDespawned(NpcDespawned npcDespawned)
|
||||
{
|
||||
final NPC npc = npcDespawned.getNpc();
|
||||
memorizedNPCs.removeIf(c -> c.getNpc() == npc);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (event.getGameState() == GameState.LOGIN_SCREEN ||
|
||||
event.getGameState() == GameState.HOPPING)
|
||||
{
|
||||
memorizedNPCs.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onHitsplatApplied(HitsplatApplied event)
|
||||
{
|
||||
if (event.getActor().getInteracting() != client.getLocalPlayer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
final Hitsplat hitsplat = event.getHitsplat();
|
||||
if (hitsplat.getHitsplatType() == Hitsplat.HitsplatType.DAMAGE || hitsplat.getHitsplatType() == Hitsplat.HitsplatType.BLOCK)
|
||||
{
|
||||
if (event.getActor() instanceof NPC)
|
||||
{
|
||||
for (MemorizedNPC mn : memorizedNPCs)
|
||||
{
|
||||
if (mn.getStatus() == MemorizedNPC.Status.OUT_OF_COMBAT || (mn.getStatus() == MemorizedNPC.Status.IN_COMBAT && mn.getCombatTimerEnd() - client.getTickCount() < 1) || mn.getLastinteracted() == null)
|
||||
{
|
||||
mn.setStatus(MemorizedNPC.Status.FLINCHING);
|
||||
mn.setCombatTimerEnd(-1);
|
||||
mn.setFlinchTimerEnd(client.getTickCount() + mn.getAttackSpeed() / 2 + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void checkStatus()
|
||||
{
|
||||
for (MemorizedNPC npc : memorizedNPCs)
|
||||
{
|
||||
final int ATTACK_SPEED = npc.getAttackSpeed();
|
||||
final double CombatTime = npc.getCombatTimerEnd() - client.getTickCount();
|
||||
final double FlinchTime = npc.getFlinchTimerEnd() - client.getTickCount();
|
||||
if (npc.getNpc().getWorldArea() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (npc.getNpc().getInteracting() == client.getLocalPlayer())
|
||||
{
|
||||
if (npc.getLastspotanimation() == GraphicID.SPLASH && npc.getNpc().getSpotAnimation() == GraphicID.SPLASH) //For splash flinching
|
||||
{
|
||||
npc.setLastspotanimation(-1);
|
||||
if ((npc.getStatus() == MemorizedNPC.Status.OUT_OF_COMBAT ) || npc.getLastinteracted() == null)
|
||||
{
|
||||
npc.setStatus(MemorizedNPC.Status.FLINCHING);
|
||||
npc.setCombatTimerEnd(-1);
|
||||
npc.setFlinchTimerEnd(client.getTickCount() + ATTACK_SPEED / 2 + 1);
|
||||
npc.setLastnpcarea(npc.getNpc().getWorldArea());
|
||||
npc.setLastinteracted(npc.getNpc().getInteracting());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//Checks: will the NPC attack this tick?
|
||||
if (((npc.getNpc().getWorldArea().canMelee(client, lastPlayerLocation) && config.getRange() == 1) //Separate mechanics for meleerange-only NPC's because they have extra collisiondata checks (fences etc.) and can't attack diagonally
|
||||
|| (lastPlayerLocation.hasLineOfSightTo(client, npc.getNpc().getWorldArea()) && npc.getNpc().getWorldArea().distanceTo(lastPlayerLocation) <= config.getRange() && config.getRange() > 1))
|
||||
&& ((npc.getStatus() != MemorizedNPC.Status.FLINCHING && CombatTime < 9) || (npc.getStatus() == MemorizedNPC.Status.FLINCHING && FlinchTime < 2))
|
||||
&& npc.getNpc().getAnimation() != -1 //Failsafe, attacking NPC's always have an animation.
|
||||
&& !(npc.getLastnpcarea().distanceTo(lastPlayerLocation) == 0 && npc.getLastnpcarea() != npc.getNpc().getWorldArea())) //Weird mechanic: NPC's can't attack on the tick they do a random move
|
||||
{
|
||||
npc.setCombatTimerEnd(client.getTickCount() + ATTACK_SPEED + 8);
|
||||
npc.setStatus(MemorizedNPC.Status.IN_COMBAT_DELAY);
|
||||
npc.setLastnpcarea(npc.getNpc().getWorldArea());
|
||||
npc.setLastspotanimation(npc.getNpc().getSpotAnimation());
|
||||
npc.setLastinteracted(npc.getNpc().getInteracting());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
switch (npc.getStatus())
|
||||
{
|
||||
case IN_COMBAT:
|
||||
if (CombatTime < 2)
|
||||
{
|
||||
npc.setStatus(MemorizedNPC.Status.OUT_OF_COMBAT);
|
||||
}
|
||||
break;
|
||||
case IN_COMBAT_DELAY:
|
||||
if (CombatTime < 9)
|
||||
{
|
||||
npc.setStatus(MemorizedNPC.Status.IN_COMBAT);
|
||||
}
|
||||
break;
|
||||
case FLINCHING:
|
||||
if (FlinchTime < 2)
|
||||
{
|
||||
npc.setStatus(MemorizedNPC.Status.IN_COMBAT);
|
||||
npc.setCombatTimerEnd(client.getTickCount() + 8);
|
||||
}
|
||||
}
|
||||
npc.setLastnpcarea(npc.getNpc().getWorldArea());
|
||||
npc.setLastspotanimation(npc.getNpc().getSpotAnimation());
|
||||
npc.setLastinteracted(npc.getNpc().getInteracting());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
lastTickUpdate = Instant.now();
|
||||
checkStatus();
|
||||
lastPlayerLocation = client.getLocalPlayer().getWorldArea();
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public class BatSolver
|
||||
}
|
||||
|
||||
|
||||
public void calculateChanceOfPoison()
|
||||
private void calculateChanceOfPoison()
|
||||
{
|
||||
if (getType() == null)
|
||||
{
|
||||
|
||||
@@ -35,9 +35,9 @@ import lombok.Getter;
|
||||
// e.g. if there is an empty chest in L room chest 1, the other empty chests could be 16, 17, 38, 54, 55
|
||||
// See https://dikkenoob.github.io/ for more information
|
||||
|
||||
public class SolutionSet
|
||||
class SolutionSet
|
||||
{
|
||||
public static final SolutionSet[] SOLUTION_SETS =
|
||||
static final SolutionSet[] SOLUTION_SETS =
|
||||
{
|
||||
new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 16, 17, 55),
|
||||
new SolutionSet(ThievingRoomType.LEFT_TURN, 1, 17, 38, 54),
|
||||
@@ -147,12 +147,12 @@ public class SolutionSet
|
||||
this.emptyChests = new HashSet<>(Arrays.asList(emptyChests));
|
||||
}
|
||||
|
||||
public void addEmptyChest(int chestId)
|
||||
void addEmptyChest(int chestId)
|
||||
{
|
||||
emptyChests.add(chestId);
|
||||
}
|
||||
|
||||
public boolean containsChest(int chestId)
|
||||
boolean containsChest(int chestId)
|
||||
{
|
||||
return emptyChests.contains(chestId);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class InstancePoint
|
||||
private static final int CHUNK_SIZE = 8;
|
||||
private static final double CHUNK_OFFSET = 3.5;
|
||||
|
||||
public InstancePoint(int x, int y, int rot)
|
||||
private InstancePoint(int x, int y, int rot)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
@@ -29,7 +29,7 @@ public class InstancePoint
|
||||
this.rot = 0;
|
||||
}
|
||||
|
||||
public static InstancePoint buildFromPoint(WorldPoint worldPoint, Client client)
|
||||
static InstancePoint buildFromPoint(WorldPoint worldPoint, Client client)
|
||||
{
|
||||
Point point = new Point(worldPoint.getX(), worldPoint.getY());
|
||||
Point base = new Point(client.getBaseX(), client.getBaseY());
|
||||
@@ -48,7 +48,7 @@ public class InstancePoint
|
||||
return buildFromTile(base, point, rotation, new Point(x, y));
|
||||
}
|
||||
|
||||
public static InstancePoint buildFromTile(Point base, Point tile, int rot, Point chunkOrigin)
|
||||
private static InstancePoint buildFromTile(Point base, Point tile, int rot, Point chunkOrigin)
|
||||
{
|
||||
int deltaX = tile.getX() - base.getX();
|
||||
int deltaY = tile.getY() - base.getY();
|
||||
|
||||
@@ -26,10 +26,10 @@ package net.runelite.client.plugins.raidsthieving;
|
||||
|
||||
public class RaidsThievingConstants
|
||||
{
|
||||
public static final int CLOSED_CHEST_ID = 29742;
|
||||
public static final int OPEN_EMPTY_CHEST = 29743;
|
||||
public static final int OPEN_FULL_CHEST_1 = 29744;
|
||||
public static final int OPEN_FULL_CHEST_2 = 29745;
|
||||
public static final int EMPTY_TROUGH = 29746;
|
||||
static final int CLOSED_CHEST_ID = 29742;
|
||||
static final int OPEN_EMPTY_CHEST = 29743;
|
||||
static final int OPEN_FULL_CHEST_1 = 29744;
|
||||
static final int OPEN_FULL_CHEST_2 = 29745;
|
||||
static final int EMPTY_TROUGH = 29746;
|
||||
public static final int[] STORAGE = {29769, 29770, 29771, 29772};
|
||||
}
|
||||
|
||||
@@ -201,6 +201,12 @@ public class RaidsThievingPlugin extends Plugin
|
||||
{
|
||||
log.debug("Found poison splat");
|
||||
WorldPoint loc = WorldPoint.fromLocal(client, obj.getLocation());
|
||||
|
||||
if (chests.get(loc) == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
chests.get(loc).setPoison(true);
|
||||
}
|
||||
}
|
||||
@@ -235,7 +241,7 @@ public class RaidsThievingPlugin extends Plugin
|
||||
mapper = null;
|
||||
}
|
||||
|
||||
public int numberOfEmptyChestsFound()
|
||||
int numberOfEmptyChestsFound()
|
||||
{
|
||||
int total = 0;
|
||||
for (ThievingChest chest : chests.values())
|
||||
@@ -248,7 +254,6 @@ public class RaidsThievingPlugin extends Plugin
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
private boolean checkForBats()
|
||||
{
|
||||
for (ThievingChest chest : chests.values())
|
||||
@@ -266,7 +271,7 @@ public class RaidsThievingPlugin extends Plugin
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getChestId(WorldPoint worldPoint)
|
||||
int getChestId(WorldPoint worldPoint)
|
||||
{
|
||||
return chests.get(worldPoint).getChestId();
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
@@ -169,12 +171,7 @@ class ScreenMarkerPanel extends JPanel
|
||||
@Override
|
||||
public void mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
marker.getMarker().setName(nameInput.getText());
|
||||
plugin.updateConfig();
|
||||
|
||||
nameInput.setEditable(false);
|
||||
updateNameActions(false);
|
||||
requestFocusInWindow();
|
||||
save();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,10 +195,7 @@ class ScreenMarkerPanel extends JPanel
|
||||
@Override
|
||||
public void mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
nameInput.setEditable(false);
|
||||
nameInput.setText(marker.getMarker().getName());
|
||||
updateNameActions(false);
|
||||
requestFocusInWindow();
|
||||
cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -252,6 +246,35 @@ class ScreenMarkerPanel extends JPanel
|
||||
nameInput.setPreferredSize(new Dimension(0, 24));
|
||||
nameInput.getTextField().setForeground(Color.WHITE);
|
||||
nameInput.getTextField().setBorder(new EmptyBorder(0, 8, 0, 0));
|
||||
nameInput.addKeyListener(new KeyAdapter()
|
||||
{
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e)
|
||||
{
|
||||
if (e.getKeyCode() == KeyEvent.VK_ENTER)
|
||||
{
|
||||
save();
|
||||
}
|
||||
else if (e.getKeyCode() == KeyEvent.VK_ESCAPE)
|
||||
{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
});
|
||||
nameInput.getTextField().addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent mouseEvent)
|
||||
{
|
||||
preview(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent mouseEvent)
|
||||
{
|
||||
preview(false);
|
||||
}
|
||||
});
|
||||
|
||||
nameWrapper.add(nameInput, BorderLayout.CENTER);
|
||||
nameWrapper.add(nameActions, BorderLayout.EAST);
|
||||
@@ -359,10 +382,7 @@ class ScreenMarkerPanel extends JPanel
|
||||
@Override
|
||||
public void mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
visible = !visible;
|
||||
marker.getMarker().setVisible(visible);
|
||||
plugin.updateConfig();
|
||||
updateVisibility();
|
||||
toggle(!visible);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -424,6 +444,42 @@ class ScreenMarkerPanel extends JPanel
|
||||
|
||||
}
|
||||
|
||||
private void preview(boolean on)
|
||||
{
|
||||
if (visible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
marker.getMarker().setVisible(on);
|
||||
}
|
||||
|
||||
private void toggle(boolean on)
|
||||
{
|
||||
visible = on;
|
||||
marker.getMarker().setVisible(visible);
|
||||
plugin.updateConfig();
|
||||
updateVisibility();
|
||||
}
|
||||
|
||||
private void save()
|
||||
{
|
||||
marker.getMarker().setName(nameInput.getText());
|
||||
plugin.updateConfig();
|
||||
|
||||
nameInput.setEditable(false);
|
||||
updateNameActions(false);
|
||||
requestFocusInWindow();
|
||||
}
|
||||
|
||||
private void cancel()
|
||||
{
|
||||
nameInput.setEditable(false);
|
||||
nameInput.setText(marker.getMarker().getName());
|
||||
updateNameActions(false);
|
||||
requestFocusInWindow();
|
||||
}
|
||||
|
||||
private void updateNameActions(boolean saveAndCancel)
|
||||
{
|
||||
save.setVisible(saveAndCancel);
|
||||
|
||||
@@ -26,11 +26,30 @@ package net.runelite.client.plugins.shiftwalker;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
// import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
|
||||
@ConfigGroup("shiftwalkhere")
|
||||
public interface ShiftWalkerConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "shiftWalk",
|
||||
name = "Shift to Walk",
|
||||
description = "For when you want Walk here as a priority"
|
||||
)
|
||||
default boolean shiftWalk()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "shiftLoot",
|
||||
name = "Shift to Loot",
|
||||
description = "For when people stand on your loot"
|
||||
)
|
||||
default boolean shiftLoot()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
|
||||
@ConfigItem(
|
||||
|
||||
@@ -50,7 +50,7 @@ public class ShiftWalkerPlugin extends Plugin
|
||||
{
|
||||
|
||||
private static final String WALK_HERE = "Walk here";
|
||||
|
||||
private static final String TAKE = "Take";
|
||||
@Inject
|
||||
private ShiftWalkerConfig config;
|
||||
|
||||
@@ -92,11 +92,20 @@ public class ShiftWalkerPlugin extends Plugin
|
||||
|
||||
void startPrioritizing()
|
||||
{
|
||||
menuManager.addPriorityEntry(WALK_HERE);
|
||||
if (config.shiftLoot())
|
||||
{
|
||||
menuManager.addPriorityEntry(TAKE);
|
||||
}
|
||||
|
||||
if (config.shiftWalk())
|
||||
{
|
||||
menuManager.addPriorityEntry(WALK_HERE);
|
||||
}
|
||||
}
|
||||
|
||||
void stopPrioritizing()
|
||||
{
|
||||
menuManager.removePriorityEntry(TAKE);
|
||||
menuManager.removePriorityEntry(WALK_HERE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ package net.runelite.client.plugins.slayer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class KnapsackSolver
|
||||
class KnapsackSolver
|
||||
{
|
||||
|
||||
private List<Integer> reconstructItemsInSack(int[][] sackMatrix, List<Integer> items, int i, int w)
|
||||
@@ -49,7 +49,7 @@ public class KnapsackSolver
|
||||
}
|
||||
}
|
||||
|
||||
public int howMuchFitsInSack(List<Integer> items, int maxWeight)
|
||||
int howMuchFitsInSack(List<Integer> items, int maxWeight)
|
||||
{
|
||||
int itemCount = items.size();
|
||||
|
||||
|
||||
@@ -29,17 +29,17 @@ public class NPCPresence
|
||||
return name + "[" + combatLevel + "]";
|
||||
}
|
||||
|
||||
public boolean shouldExist()
|
||||
boolean shouldExist()
|
||||
{
|
||||
return fadeTimer > 0;
|
||||
}
|
||||
|
||||
public void tickExistence()
|
||||
void tickExistence()
|
||||
{
|
||||
fadeTimer--;
|
||||
}
|
||||
|
||||
public static NPCPresence buildPresence(NPC npc)
|
||||
static NPCPresence buildPresence(NPC npc)
|
||||
{
|
||||
return new NPCPresence(npc.getName(), npc.getCombatLevel());
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -66,6 +67,7 @@ import net.runelite.api.events.ExperienceChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.InteractingChanged;
|
||||
import net.runelite.api.events.NpcDefinitionChanged;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
@@ -79,7 +81,6 @@ import net.runelite.client.chat.ChatCommandManager;
|
||||
import net.runelite.client.chat.ChatMessageBuilder;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.ChatInput;
|
||||
import net.runelite.client.game.AsyncBufferedImage;
|
||||
@@ -215,11 +216,8 @@ public class SlayerPlugin extends Plugin
|
||||
@Inject
|
||||
private ChatClient chatClient;
|
||||
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<NPC> highlightedTargets = new ArrayList<>();
|
||||
private final Set<NPC> highlightedTargets = new HashSet<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
@@ -349,8 +347,17 @@ public class SlayerPlugin extends Plugin
|
||||
if (isTarget(npc, targetNames))
|
||||
{
|
||||
highlightedTargets.add(npc);
|
||||
NPCPresence newPresence = NPCPresence.buildPresence(npc);
|
||||
// log.debug("New presence of " + newPresence.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcDefinitionChanged(NpcDefinitionChanged event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
|
||||
if (isTarget(npc, targetNames))
|
||||
{
|
||||
highlightedTargets.add(npc);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,7 +370,6 @@ public class SlayerPlugin extends Plugin
|
||||
{
|
||||
NPCPresence lingeringPresence = NPCPresence.buildPresence(npc);
|
||||
lingeringPresences.add(lingeringPresence);
|
||||
// log.debug("Presence of " + lingeringPresence.toString() + " now lingering");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,7 +396,7 @@ public class SlayerPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
int estimateKillCount(List<NPCPresence> potentialKills, int gains)
|
||||
private int estimateKillCount(List<NPCPresence> potentialKills, int gains)
|
||||
{
|
||||
// failsafe to avoid calculating kill count if there were no slayer monsters around that could be killed on task
|
||||
// this failsafe *WILL FAIL* if someone decides to lamp their slayer in the middle of a task next to on task creatures
|
||||
@@ -583,8 +589,6 @@ public class SlayerPlugin extends Plugin
|
||||
streak = 1;
|
||||
break;
|
||||
case 1:
|
||||
streak = Integer.parseInt(matches.get(0));
|
||||
break;
|
||||
case 3:
|
||||
streak = Integer.parseInt(matches.get(0));
|
||||
break;
|
||||
@@ -665,29 +669,13 @@ public class SlayerPlugin extends Plugin
|
||||
// this is not the initial xp sent on login so these are new xp gains
|
||||
int gains = slayerExp - cachedXp;
|
||||
|
||||
//log.debug("Slayer xp drop received");
|
||||
|
||||
//StringBuilder debugString = new StringBuilder();
|
||||
|
||||
// potential npcs to give xp drop are current highlighted npcs and the lingering presences
|
||||
List<NPCPresence> potentialNPCs = new ArrayList<>();
|
||||
//debugString.append("Lingering presences {");
|
||||
for (NPCPresence presence : lingeringPresences)
|
||||
{
|
||||
potentialNPCs.add(presence);
|
||||
// debugString.append(presence.toString());
|
||||
// debugString.append(", ");
|
||||
}
|
||||
//debugString.append("}\nCurrent presences {");
|
||||
List<NPCPresence> potentialNPCs = new ArrayList<>(lingeringPresences);
|
||||
for (NPC npc : highlightedTargets)
|
||||
{
|
||||
NPCPresence currentPresence = NPCPresence.buildPresence(npc);
|
||||
potentialNPCs.add(currentPresence);
|
||||
// debugString.append(currentPresence.toString());
|
||||
// debugString.append(", ");
|
||||
}
|
||||
//debugString.append("}");
|
||||
//log.debug(debugString.toString());
|
||||
|
||||
int killCount = estimateKillCount(potentialNPCs, gains);
|
||||
for (int i = 0; i < killCount; i++)
|
||||
@@ -751,7 +739,7 @@ public class SlayerPlugin extends Plugin
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void killedOne()
|
||||
private void killedOne()
|
||||
{
|
||||
if (currentTask.getAmount() == 0)
|
||||
{
|
||||
@@ -788,7 +776,7 @@ public class SlayerPlugin extends Plugin
|
||||
}
|
||||
|
||||
// checks if any contiguous subsequence of seq0 exactly matches the String toMatch
|
||||
boolean contiguousSubsequenceMatches(String[] seq0, String toMatch)
|
||||
private boolean contiguousSubsequenceMatches(String[] seq0, String toMatch)
|
||||
{
|
||||
for (int i = 0; i < seq0.length; i++)
|
||||
{
|
||||
@@ -906,8 +894,7 @@ public class SlayerPlugin extends Plugin
|
||||
|
||||
if (task != null)
|
||||
{
|
||||
task.getNpcIds().stream()
|
||||
.forEach(targetIds::add);
|
||||
targetIds.addAll(task.getNpcIds());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -962,7 +949,7 @@ public class SlayerPlugin extends Plugin
|
||||
rebuildTargetList();
|
||||
}
|
||||
|
||||
public AsyncBufferedImage getImageForTask(Task task)
|
||||
AsyncBufferedImage getImageForTask(Task task)
|
||||
{
|
||||
int itemSpriteId = ItemID.ENCHANTED_GEM;
|
||||
if (task != null)
|
||||
@@ -1048,6 +1035,11 @@ public class SlayerPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
if (task == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (TASK_STRING_VALIDATION.matcher(task.getTask()).find() || task.getTask().length() > TASK_STRING_MAX_LENGTH ||
|
||||
TASK_STRING_VALIDATION.matcher(task.getLocation()).find() || task.getLocation().length() > TASK_STRING_MAX_LENGTH)
|
||||
{
|
||||
|
||||
@@ -343,7 +343,7 @@ public class SlayerTaskPanel extends PluginPanel
|
||||
changePauseState(paused);
|
||||
}
|
||||
|
||||
static String htmlLabel(String key, long timeMillis)
|
||||
private static String htmlLabel(String key, long timeMillis)
|
||||
{
|
||||
if (timeMillis == Long.MAX_VALUE)
|
||||
{
|
||||
@@ -363,7 +363,7 @@ public class SlayerTaskPanel extends PluginPanel
|
||||
}
|
||||
}
|
||||
|
||||
static String htmlLabel(String key, int value)
|
||||
private static String htmlLabel(String key, int value)
|
||||
{
|
||||
String valueStr = StackFormatter.quantityToRSDecimalStack(value);
|
||||
return String.format(HTML_LABEL_TEMPLATE, ColorUtil.toHexColor(ColorScheme.LIGHT_GRAY_COLOR),
|
||||
|
||||
@@ -31,14 +31,14 @@ import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SlayerXpDropLookup
|
||||
class SlayerXpDropLookup
|
||||
{
|
||||
private Map<String, List<Double>> xpMap;
|
||||
|
||||
// floating point math equality
|
||||
private static final double EPSILON = 1e-6;
|
||||
|
||||
void loadXpJson()
|
||||
private void loadXpJson()
|
||||
{
|
||||
final InputStream xpFile = getClass().getResourceAsStream("/slayer_xp.json");
|
||||
Gson gson = new Gson();
|
||||
@@ -76,7 +76,7 @@ public class SlayerXpDropLookup
|
||||
* @param npc the npc we are estimating slayer xp for
|
||||
* @return our best guess for the slayer xp for this npc
|
||||
*/
|
||||
public double findXpForNpc(NPCPresence npc)
|
||||
double findXpForNpc(NPCPresence npc)
|
||||
{
|
||||
List<Double> xpCombatLevel = xpMap.get(npc.getName());
|
||||
if (xpCombatLevel == null)
|
||||
@@ -127,7 +127,7 @@ public class SlayerXpDropLookup
|
||||
return -1;
|
||||
}
|
||||
|
||||
public SlayerXpDropLookup()
|
||||
SlayerXpDropLookup()
|
||||
{
|
||||
loadXpJson();
|
||||
}
|
||||
|
||||
@@ -26,12 +26,11 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.slayer;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
@@ -57,8 +56,7 @@ public class TargetClickboxOverlay extends Overlay
|
||||
private final ModelOutlineRenderer modelOutliner;
|
||||
|
||||
@Inject
|
||||
TargetClickboxOverlay(Client client, SlayerConfig config, SlayerPlugin plugin,
|
||||
ModelOutlineRenderer modelOutlineRenderer)
|
||||
TargetClickboxOverlay(Client client, SlayerConfig config, SlayerPlugin plugin, ModelOutlineRenderer modelOutlineRenderer)
|
||||
{
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
@@ -73,10 +71,16 @@ public class TargetClickboxOverlay extends Overlay
|
||||
{
|
||||
if (config.highlightTargets())
|
||||
{
|
||||
List<NPC> targets = plugin.getHighlightedTargets();
|
||||
Set<NPC> targets = plugin.getHighlightedTargets();
|
||||
for (NPC target : targets)
|
||||
{
|
||||
if (target == null || target.getName() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Color coloration = config.getTargetColor();
|
||||
|
||||
if (plugin.isSuperior(target.getName()))
|
||||
{
|
||||
coloration = config.getSuperiorColor();
|
||||
@@ -95,28 +99,36 @@ public class TargetClickboxOverlay extends Overlay
|
||||
{
|
||||
case SOUTH_WEST_TILE:
|
||||
LocalPoint lp1 = LocalPoint.fromWorld(client, actor.getWorldLocation());
|
||||
|
||||
if (lp1 == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Polygon tilePoly1 = Perspective.getCanvasTilePoly(client, lp1);
|
||||
|
||||
renderPoly(graphics, color, tilePoly1);
|
||||
OverlayUtil.renderPolygon(graphics, tilePoly1, color);
|
||||
break;
|
||||
|
||||
case TILE:
|
||||
int size = 1;
|
||||
NPCDefinition composition = actor.getTransformedDefinition();
|
||||
|
||||
if (composition != null)
|
||||
{
|
||||
size = composition.getSize();
|
||||
}
|
||||
|
||||
LocalPoint lp = actor.getLocalLocation();
|
||||
Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size);
|
||||
|
||||
renderPoly(graphics, color, tilePoly);
|
||||
OverlayUtil.renderPolygon(graphics, tilePoly, color);
|
||||
break;
|
||||
|
||||
case HULL:
|
||||
Polygon objectClickbox = actor.getConvexHull();
|
||||
|
||||
renderPoly(graphics, color, objectClickbox);
|
||||
OverlayUtil.renderPolygon(graphics, objectClickbox, color);
|
||||
break;
|
||||
case THIN_OUTLINE:
|
||||
modelOutliner.drawOutline(actor, 1, color);
|
||||
@@ -136,15 +148,23 @@ public class TargetClickboxOverlay extends Overlay
|
||||
case TRUE_LOCATIONS:
|
||||
size = 1;
|
||||
composition = actor.getTransformedDefinition();
|
||||
|
||||
if (composition != null)
|
||||
{
|
||||
size = composition.getSize();
|
||||
}
|
||||
|
||||
WorldPoint wp = actor.getWorldLocation();
|
||||
lp = LocalPoint.fromWorld(client, wp);
|
||||
|
||||
if (lp == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size);
|
||||
|
||||
renderPoly(graphics, color, tilePoly);
|
||||
OverlayUtil.renderPolygon(graphics, tilePoly, color);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -159,16 +179,4 @@ public class TargetClickboxOverlay extends Overlay
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderPoly(Graphics2D graphics, Color color, Polygon polygon)
|
||||
{
|
||||
if (polygon != null)
|
||||
{
|
||||
graphics.setColor(color);
|
||||
graphics.setStroke(new BasicStroke(2));
|
||||
graphics.draw(polygon);
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), 20));
|
||||
graphics.fill(polygon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,8 @@ package net.runelite.client.plugins.slayer;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
@@ -41,15 +40,12 @@ import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
public class TargetMinimapOverlay extends Overlay
|
||||
{
|
||||
|
||||
private final Client client;
|
||||
private final SlayerConfig config;
|
||||
private final SlayerPlugin plugin;
|
||||
|
||||
@Inject
|
||||
TargetMinimapOverlay(Client client, SlayerConfig config, SlayerPlugin plugin)
|
||||
TargetMinimapOverlay(SlayerConfig config, SlayerPlugin plugin)
|
||||
{
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
this.plugin = plugin;
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
@@ -64,10 +60,16 @@ public class TargetMinimapOverlay extends Overlay
|
||||
return null;
|
||||
}
|
||||
|
||||
List<NPC> targets = plugin.getHighlightedTargets();
|
||||
Set<NPC> targets = plugin.getHighlightedTargets();
|
||||
for (NPC target : targets)
|
||||
{
|
||||
if (target == null || target.getName() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Color coloration = config.getTargetColor();
|
||||
|
||||
if (plugin.isSuperior(target.getName()))
|
||||
{
|
||||
coloration = config.getSuperiorColor();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Devin French <https://github.com/devinfrench>
|
||||
* Copyright (c) 2018, Aquivers <https://github.com/aquivers>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -22,66 +22,56 @@
|
||||
* (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.fightcave;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import javax.inject.Inject;
|
||||
package net.runelite.client.plugins.tearsofguthix;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.client.game.SpriteManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||
import net.runelite.client.ui.overlay.components.ComponentConstants;
|
||||
import net.runelite.client.ui.overlay.components.ImageComponent;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import javax.inject.Inject;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import net.runelite.client.ui.overlay.components.table.TableAlignment;
|
||||
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
|
||||
public class JadOverlay extends Overlay
|
||||
class TearsOfGuthixExperienceOverlay extends Overlay
|
||||
{
|
||||
private static final Color NOT_ACTIVATED_BACKGROUND_COLOR = new Color(150, 0, 0, 150);
|
||||
|
||||
private final Client client;
|
||||
private final FightCavePlugin plugin;
|
||||
private final SpriteManager spriteManager;
|
||||
private final PanelComponent imagePanelComponent = new PanelComponent();
|
||||
private final TearsOfGuthixPlugin plugin;
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
|
||||
@Inject
|
||||
private JadOverlay(Client client, FightCavePlugin plugin, SpriteManager spriteManager)
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private TearsOfGuthixExperienceOverlay(final TearsOfGuthixPlugin plugin)
|
||||
{
|
||||
setPosition(OverlayPosition.BOTTOM_RIGHT);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
this.client = client;
|
||||
setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT);
|
||||
setPriority(OverlayPriority.LOW);
|
||||
this.plugin = plugin;
|
||||
this.spriteManager = spriteManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
final JadAttack attack = plugin.getAttack();
|
||||
|
||||
if (attack == null)
|
||||
if (plugin.getPlayerLowestSkill() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final BufferedImage prayerImage = getPrayerImage(attack);
|
||||
panelComponent.getChildren().clear();
|
||||
|
||||
imagePanelComponent.getChildren().clear();
|
||||
imagePanelComponent.getChildren().add(new ImageComponent(prayerImage));
|
||||
imagePanelComponent.setBackgroundColor(client.isPrayerActive(attack.getPrayer())
|
||||
? ComponentConstants.STANDARD_BACKGROUND_COLOR
|
||||
: NOT_ACTIVATED_BACKGROUND_COLOR);
|
||||
TableComponent tableComponent = new TableComponent();
|
||||
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
|
||||
|
||||
return imagePanelComponent.render(graphics);
|
||||
}
|
||||
tableComponent.addRow(plugin.getPlayerLowestSkill().getName(), "Lvl - " + client.getRealSkillLevel(plugin.getPlayerLowestSkill()) + "");
|
||||
|
||||
private BufferedImage getPrayerImage(JadAttack attack)
|
||||
{
|
||||
final int prayerSpriteID = attack == JadAttack.MAGIC ? SpriteID.PRAYER_PROTECT_FROM_MAGIC : SpriteID.PRAYER_PROTECT_FROM_MISSILES;
|
||||
return spriteManager.getSprite(prayerSpriteID, 0);
|
||||
if (!tableComponent.isEmpty())
|
||||
{
|
||||
panelComponent.getChildren().add(tableComponent);
|
||||
}
|
||||
|
||||
return panelComponent.render(graphics);
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,13 @@ import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.DecorativeObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ObjectID;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.events.DecorativeObjectDespawned;
|
||||
import net.runelite.api.events.DecorativeObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
@@ -58,20 +61,29 @@ public class TearsOfGuthixPlugin extends Plugin
|
||||
@Inject
|
||||
private TearsOfGuthixOverlay overlay;
|
||||
|
||||
@Getter
|
||||
@Inject
|
||||
private TearsOfGuthixExperienceOverlay experienceOverlay;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Map<DecorativeObject, Instant> streams = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Skill playerLowestSkill = null;
|
||||
|
||||
@Override
|
||||
protected void startUp()
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(experienceOverlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(experienceOverlay);
|
||||
streams.clear();
|
||||
playerLowestSkill = null;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -84,6 +96,26 @@ public class TearsOfGuthixPlugin extends Plugin
|
||||
case HOPPING:
|
||||
streams.clear();
|
||||
}
|
||||
|
||||
if (event.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
if (client.getLocalPlayer().getWorldLocation().getRegionID() == TOG_REGION)
|
||||
{
|
||||
if (playerLowestSkill != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.getSkillExperience(Skill.HITPOINTS) > 0)
|
||||
{
|
||||
playerLowestSkill = getLowestPlayerSkill();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
playerLowestSkill = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -112,4 +144,24 @@ public class TearsOfGuthixPlugin extends Plugin
|
||||
DecorativeObject object = event.getDecorativeObject();
|
||||
streams.remove(object);
|
||||
}
|
||||
|
||||
private Skill getLowestPlayerSkill()
|
||||
{
|
||||
final Skill[] playerSkills = Skill.values();
|
||||
Skill lowestExperienceSkill = null;
|
||||
int lowestExperienceAmount = Integer.MAX_VALUE;
|
||||
|
||||
for (Skill skill : playerSkills)
|
||||
{
|
||||
int currentSkillExp = client.getSkillExperience(skill);
|
||||
|
||||
if (currentSkillExp < lowestExperienceAmount)
|
||||
{
|
||||
lowestExperienceAmount = currentSkillExp;
|
||||
lowestExperienceSkill = skill;
|
||||
}
|
||||
}
|
||||
|
||||
return lowestExperienceSkill;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
package net.runelite.client.plugins.theatre;
|
||||
|
||||
import net.runelite.api.*;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCDefinition;
|
||||
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.coords.WorldArea;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
import java.awt.*;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class RoomHandler
|
||||
public abstract class RoomHandler
|
||||
{
|
||||
|
||||
protected final Client client;
|
||||
@@ -29,7 +35,7 @@ public abstract class RoomHandler
|
||||
|
||||
public abstract void onStop();
|
||||
|
||||
protected void drawTile2(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha)
|
||||
protected void drawTile2(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha)
|
||||
{
|
||||
WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
|
||||
if (point.distanceTo(playerLocation) >= 32)
|
||||
@@ -71,14 +77,14 @@ public abstract class RoomHandler
|
||||
Point textLocation = Perspective.getCanvasTextLocation(client, graphics, projectilePoint, text, 0);
|
||||
if (textLocation != null)
|
||||
{
|
||||
if (projectileId == 1607)
|
||||
if (projectileId == 1607)
|
||||
{ // range
|
||||
renderTextLocation(graphics, text, 17, Font.BOLD, new Color(57, 255, 20, 255), textLocation);
|
||||
}
|
||||
}
|
||||
else if (projectileId == 1606)
|
||||
{ //mage
|
||||
renderTextLocation(graphics, text, 17, Font.BOLD, new Color(64, 224, 208, 255), textLocation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //Orb of death? i hope
|
||||
renderTextLocation(graphics, text, 20, Font.BOLD, Color.WHITE, textLocation);
|
||||
@@ -87,20 +93,26 @@ public abstract class RoomHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha)
|
||||
protected void drawTile(Graphics2D graphics, WorldPoint point, Color color, int strokeWidth, int outlineAlpha, int fillAlpha)
|
||||
{
|
||||
WorldPoint playerLocation = client.getLocalPlayer().getWorldLocation();
|
||||
|
||||
if (point.distanceTo(playerLocation) >= 32)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LocalPoint lp = LocalPoint.fromWorld(client, point);
|
||||
if (lp == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Polygon poly = Perspective.getCanvasTilePoly(client, lp);
|
||||
if (poly == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
graphics.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), outlineAlpha));
|
||||
graphics.setStroke(new BasicStroke(strokeWidth));
|
||||
@@ -109,13 +121,15 @@ public abstract class RoomHandler
|
||||
graphics.fill(poly);
|
||||
}
|
||||
|
||||
protected void renderNpcOverlay(Graphics2D graphics, NPC actor, Color color, int outlineWidth, int outlineAlpha, int fillAlpha)
|
||||
protected void renderNpcOverlay(Graphics2D graphics, NPC actor, Color color, int outlineWidth, int outlineAlpha, int fillAlpha)
|
||||
{
|
||||
int size = 1;
|
||||
|
||||
NPCDefinition composition = actor.getTransformedDefinition();
|
||||
if (composition != null)
|
||||
{
|
||||
size = composition.getSize();
|
||||
}
|
||||
|
||||
LocalPoint lp = actor.getLocalLocation();
|
||||
Polygon tilePoly = Perspective.getCanvasTileAreaPoly(client, lp, size);
|
||||
@@ -143,26 +157,6 @@ public abstract class RoomHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected List<WorldPoint> getHitSquares(WorldPoint npcLoc, int npcSize, int thickness, boolean includeUnder)
|
||||
{
|
||||
List<WorldPoint> little = new WorldArea(npcLoc, npcSize, npcSize).toWorldPointList();
|
||||
List<WorldPoint> big = new WorldArea(npcLoc.getX() - thickness, npcLoc.getY() - thickness, npcSize + (thickness * 2), npcSize + (thickness * 2), npcLoc.getPlane()).toWorldPointList();
|
||||
|
||||
if (!includeUnder)
|
||||
{
|
||||
for (Iterator<WorldPoint> it = big.iterator(); it.hasNext(); )
|
||||
{
|
||||
WorldPoint p = it.next();
|
||||
if (little.contains(p))
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return big;
|
||||
}
|
||||
|
||||
protected String twoDigitString(long number)
|
||||
{
|
||||
|
||||
|
||||
@@ -8,30 +8,15 @@
|
||||
|
||||
package net.runelite.client.plugins.theatre;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import java.awt.*;
|
||||
|
||||
@ConfigGroup("Theatre")
|
||||
|
||||
public interface TheatreConfig extends Config
|
||||
{
|
||||
enum NYLOCAS
|
||||
{
|
||||
NONE,
|
||||
MAGE,
|
||||
MELEE,
|
||||
RANGER
|
||||
}
|
||||
|
||||
enum NYLOOPTION
|
||||
{
|
||||
NONE,
|
||||
TILE,
|
||||
TIMER
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 0,
|
||||
keyName = "showMaidenBloodToss",
|
||||
@@ -39,7 +24,7 @@ public interface TheatreConfig extends Config
|
||||
description = "Displays the tile location where tossed blood will land.",
|
||||
group = "Maiden"
|
||||
)
|
||||
default boolean showMaidenBloodToss()
|
||||
default boolean showMaidenBloodToss()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -51,7 +36,19 @@ public interface TheatreConfig extends Config
|
||||
description = "Show the tiles that blood spawns will travel to.",
|
||||
group = "Maiden"
|
||||
)
|
||||
default boolean showMaidenBloodSpawns()
|
||||
default boolean showMaidenBloodSpawns()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "showNyloFreezeHighlights",
|
||||
name = "Show Nylo Freeze Highlights",
|
||||
description = "Show when to freeze Nylos at maiden. Say n1,n2,s1,s2 in chat for it to register.",
|
||||
group = "Maiden"
|
||||
)
|
||||
default boolean showNyloFreezeHighlights()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -63,7 +60,7 @@ public interface TheatreConfig extends Config
|
||||
description = "Displays Bloat's status (asleep, wake, and enrage) using color code.",
|
||||
group = "Bloat"
|
||||
)
|
||||
default boolean showBloatIndicator()
|
||||
default boolean showBloatIndicator()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -75,7 +72,7 @@ public interface TheatreConfig extends Config
|
||||
description = "Highlights the falling hands inside Bloat.",
|
||||
group = "Bloat"
|
||||
)
|
||||
default boolean showBloatHands()
|
||||
default boolean showBloatHands()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -87,8 +84,8 @@ public interface TheatreConfig extends Config
|
||||
description = "",
|
||||
group = "Bloat"
|
||||
)
|
||||
default boolean BloatFeetIndicatorRaveEdition()
|
||||
{
|
||||
default boolean BloatFeetIndicatorRaveEdition()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -135,45 +132,40 @@ public interface TheatreConfig extends Config
|
||||
description = "An overlay will appear that counts the amount of Nylocas in the room.",
|
||||
group = "Nylocas"
|
||||
)
|
||||
default boolean showNylocasAmount()
|
||||
default boolean showNylocasAmount()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
keyName = "showNylocasSpawns",
|
||||
name = "Show Nylocas Pre-spawns",
|
||||
description = "Know the contents of the next upcoming wave."
|
||||
)
|
||||
default boolean showNylocasSpawns()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 9,
|
||||
keyName = "highlightNyloRoles",
|
||||
name = "Highlight Nylo Prespawns",
|
||||
description = "Highlights the next upcoming wave based on role. FOR BEGINNERS"
|
||||
)
|
||||
default NYLOCAS highlightNyloRoles()
|
||||
{
|
||||
return NYLOCAS.NONE;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 10,
|
||||
keyName = "highlightNyloParents",
|
||||
name = "Show Nylo Parents (Un-used)",
|
||||
description = "Highlight the Nylocas that spawn outside the center."
|
||||
)
|
||||
default boolean highlightNyloParents()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
**/
|
||||
* @ConfigItem( position = 8,
|
||||
* keyName = "showNylocasSpawns",
|
||||
* name = "Show Nylocas Pre-spawns",
|
||||
* description = "Know the contents of the next upcoming wave."
|
||||
* )
|
||||
* default boolean showNylocasSpawns()
|
||||
* {
|
||||
* return true;
|
||||
* }
|
||||
* @ConfigItem( position = 9,
|
||||
* keyName = "highlightNyloRoles",
|
||||
* name = "Highlight Nylo Prespawns",
|
||||
* description = "Highlights the next upcoming wave based on role. FOR BEGINNERS"
|
||||
* )
|
||||
* default NYLOCAS highlightNyloRoles()
|
||||
* {
|
||||
* return NYLOCAS.NONE;
|
||||
* }
|
||||
* @ConfigItem( position = 10,
|
||||
* keyName = "highlightNyloParents",
|
||||
* name = "Show Nylo Parents (Un-used)",
|
||||
* description = "Highlight the Nylocas that spawn outside the center."
|
||||
* )
|
||||
* default boolean highlightNyloParents()
|
||||
* {
|
||||
* return true;
|
||||
* }
|
||||
**/
|
||||
|
||||
@ConfigItem(
|
||||
position = 11,
|
||||
@@ -218,7 +210,7 @@ public interface TheatreConfig extends Config
|
||||
description = "Marks the tiles of Sotetseg's maze while in the underworld.",
|
||||
group = "Sotetseg"
|
||||
)
|
||||
default boolean showSotetsegSolo()
|
||||
default boolean showSotetsegSolo()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -234,6 +226,7 @@ public interface TheatreConfig extends Config
|
||||
{
|
||||
return Color.WHITE;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 15,
|
||||
keyName = "showXarpusHeals",
|
||||
@@ -302,10 +295,10 @@ public interface TheatreConfig extends Config
|
||||
group = "Verzik"
|
||||
)
|
||||
default boolean VerzikTankTile()
|
||||
{
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ConfigItem(
|
||||
position = 22,
|
||||
keyName = "verzikrangeattacks",
|
||||
@@ -314,10 +307,10 @@ public interface TheatreConfig extends Config
|
||||
group = "Verzik"
|
||||
)
|
||||
default boolean verzikRangeAttacks()
|
||||
{
|
||||
return true;
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ConfigItem(
|
||||
position = 23,
|
||||
keyName = "extratimers",
|
||||
@@ -329,7 +322,7 @@ public interface TheatreConfig extends Config
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ConfigItem(
|
||||
position = 24,
|
||||
keyName = "p1attacks",
|
||||
@@ -341,7 +334,7 @@ public interface TheatreConfig extends Config
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ConfigItem(
|
||||
position = 25,
|
||||
keyName = "p2attacks",
|
||||
@@ -353,7 +346,7 @@ public interface TheatreConfig extends Config
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ConfigItem(
|
||||
position = 26,
|
||||
keyName = "p3attacks",
|
||||
@@ -365,4 +358,19 @@ public interface TheatreConfig extends Config
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
enum NYLOCAS
|
||||
{
|
||||
NONE,
|
||||
MAGE,
|
||||
MELEE,
|
||||
RANGER
|
||||
}
|
||||
|
||||
enum NYLOOPTION
|
||||
{
|
||||
NONE,
|
||||
TILE,
|
||||
TIMER
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.runelite.client.plugins.theatre;
|
||||
|
||||
public class TheatreConstant
|
||||
public class TheatreConstant
|
||||
{
|
||||
public static final int MAIDEN_BLOOD_THROW = 1579;
|
||||
|
||||
|
||||
@@ -8,28 +8,30 @@
|
||||
|
||||
package net.runelite.client.plugins.theatre;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.Client;
|
||||
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;
|
||||
|
||||
public class TheatreOverlay extends Overlay
|
||||
public class TheatreOverlay extends Overlay
|
||||
{
|
||||
|
||||
private final Client client;
|
||||
private final TheatrePlugin plugin;
|
||||
private final TheatreConfig config;
|
||||
private final ModelOutlineRenderer modelOutline;
|
||||
|
||||
@Inject
|
||||
private TheatreOverlay(Client client, TheatrePlugin plugin, TheatreConfig config)
|
||||
private TheatreOverlay(Client client, TheatrePlugin plugin, TheatreConfig config, ModelOutlineRenderer modelOutline)
|
||||
{
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.modelOutline = modelOutline;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
|
||||
@@ -9,32 +9,44 @@
|
||||
package net.runelite.client.plugins.theatre;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import net.runelite.api.events.*;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.GroundObjectSpawned;
|
||||
import net.runelite.api.events.NpcDefinitionChanged;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.ProjectileMoved;
|
||||
import net.runelite.api.events.SpotAnimationChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.graphics.ModelOutlineRenderer;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.plugins.theatre.rooms.BloatHandler;
|
||||
import net.runelite.client.plugins.theatre.rooms.MaidenHandler;
|
||||
import net.runelite.client.plugins.theatre.rooms.SotetsegHandler;
|
||||
import net.runelite.client.plugins.theatre.rooms.VerzikHandler;
|
||||
import net.runelite.client.plugins.theatre.rooms.xarpus.XarpusHandler;
|
||||
import net.runelite.client.plugins.theatre.rooms.nylocas.NyloHandler;
|
||||
import net.runelite.client.plugins.theatre.rooms.xarpus.XarpusHandler;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.awt.*;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Theatre of Blood",
|
||||
description = "All-in-one plugin for Theatre of Blood.",
|
||||
@@ -43,9 +55,9 @@ import java.awt.*;
|
||||
enabledByDefault = false
|
||||
)
|
||||
|
||||
public class TheatrePlugin extends Plugin
|
||||
@Slf4j
|
||||
public class TheatrePlugin extends Plugin
|
||||
{
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
@Setter(AccessLevel.PUBLIC)
|
||||
private TheatreRoom room;
|
||||
@@ -83,6 +95,9 @@ public class TheatrePlugin extends Plugin
|
||||
@Inject
|
||||
private TheatreConfig config;
|
||||
|
||||
@Inject
|
||||
private ModelOutlineRenderer modelOutline;
|
||||
|
||||
@Provides
|
||||
TheatreConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
@@ -94,7 +109,7 @@ public class TheatrePlugin extends Plugin
|
||||
{
|
||||
room = TheatreRoom.UNKNOWN;
|
||||
|
||||
maidenHandler = new MaidenHandler(client, this, config);
|
||||
maidenHandler = new MaidenHandler(client, this, config, modelOutline);
|
||||
bloatHandler = new BloatHandler(client, this, config);
|
||||
nyloHandler = new NyloHandler(client, this, config);
|
||||
sotetsegHandler = new SotetsegHandler(client, this, config);
|
||||
@@ -131,26 +146,56 @@ public class TheatrePlugin extends Plugin
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onSpotAnimationChanged(SpotAnimationChanged event)
|
||||
{
|
||||
if (maidenHandler != null)
|
||||
{
|
||||
maidenHandler.onSpotAnimationChanged(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcDefinitionChanged(NpcDefinitionChanged event)
|
||||
{
|
||||
if (maidenHandler != null)
|
||||
{
|
||||
maidenHandler.onNpcDefinitionChanged(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
if (maidenHandler != null)
|
||||
{
|
||||
maidenHandler.onNpcSpawned(event);
|
||||
}
|
||||
|
||||
if (bloatHandler != null)
|
||||
{
|
||||
bloatHandler.onNpcSpawned(event);
|
||||
}
|
||||
|
||||
if (nyloHandler != null)
|
||||
{
|
||||
nyloHandler.onNpcSpawned(event);
|
||||
}
|
||||
|
||||
if (sotetsegHandler != null)
|
||||
{
|
||||
sotetsegHandler.onNpcSpawned(event);
|
||||
}
|
||||
|
||||
if (xarpusHandler != null)
|
||||
{
|
||||
xarpusHandler.onNpcSpawned(event);
|
||||
}
|
||||
|
||||
if (verzikHandler != null)
|
||||
{
|
||||
verzikHandler.onNpcSpawned(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -158,19 +203,29 @@ public class TheatrePlugin extends Plugin
|
||||
public void onNpcDespawned(NpcDespawned event)
|
||||
{
|
||||
if (maidenHandler != null)
|
||||
{
|
||||
maidenHandler.onNpcDespawned(event);
|
||||
}
|
||||
|
||||
if (bloatHandler != null)
|
||||
{
|
||||
bloatHandler.onNpcDespawned(event);
|
||||
}
|
||||
|
||||
if (nyloHandler != null)
|
||||
{
|
||||
nyloHandler.onNpcDespawned(event);
|
||||
}
|
||||
|
||||
if (sotetsegHandler != null)
|
||||
{
|
||||
sotetsegHandler.onNpcDespawned(event);
|
||||
}
|
||||
|
||||
if (xarpusHandler != null)
|
||||
{
|
||||
xarpusHandler.onNpcDespawned(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -178,7 +233,18 @@ public class TheatrePlugin extends Plugin
|
||||
public void onAnimationChanged(AnimationChanged event)
|
||||
{
|
||||
if (verzikHandler != null)
|
||||
{
|
||||
verzikHandler.onAnimationChanged(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (maidenHandler != null)
|
||||
{
|
||||
maidenHandler.onChatMessage(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -204,22 +270,34 @@ public class TheatrePlugin extends Plugin
|
||||
public void onGameTick(GameTick event)
|
||||
{
|
||||
if (maidenHandler != null)
|
||||
{
|
||||
maidenHandler.onGameTick();
|
||||
}
|
||||
|
||||
if (bloatHandler != null)
|
||||
{
|
||||
bloatHandler.onGameTick();
|
||||
}
|
||||
|
||||
if (nyloHandler != null)
|
||||
{
|
||||
nyloHandler.onGameTick();
|
||||
}
|
||||
|
||||
if (sotetsegHandler != null)
|
||||
{
|
||||
sotetsegHandler.onGameTick();
|
||||
}
|
||||
|
||||
if (xarpusHandler != null)
|
||||
{
|
||||
xarpusHandler.onGameTick();
|
||||
}
|
||||
|
||||
if (verzikHandler != null)
|
||||
{
|
||||
verzikHandler.onGameTick();
|
||||
}
|
||||
|
||||
if (widget == null)
|
||||
{
|
||||
@@ -315,27 +393,37 @@ public class TheatrePlugin extends Plugin
|
||||
public void onGroundObjectSpawned(GroundObjectSpawned event)
|
||||
{
|
||||
if (sotetsegHandler != null)
|
||||
{
|
||||
sotetsegHandler.onGroundObjectSpawned(event);
|
||||
}
|
||||
|
||||
if (xarpusHandler != null)
|
||||
{
|
||||
xarpusHandler.onGroundObjectSpawned(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (nyloHandler != null)
|
||||
{
|
||||
nyloHandler.onConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
if (bloatHandler != null)
|
||||
{
|
||||
bloatHandler.onVarbitChanged(event);
|
||||
}
|
||||
|
||||
if (xarpusHandler != null)
|
||||
{
|
||||
xarpusHandler.onVarbitChanged(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.runelite.client.plugins.theatre;
|
||||
|
||||
public enum TheatreRoom
|
||||
public enum TheatreRoom
|
||||
{
|
||||
MAIDEN,
|
||||
BLOAT,
|
||||
@@ -8,5 +8,5 @@ public enum TheatreRoom
|
||||
SOTETSEG,
|
||||
XARPUS,
|
||||
VERSIK,
|
||||
UNKNOWN;
|
||||
UNKNOWN
|
||||
}
|
||||
@@ -1,42 +1,36 @@
|
||||
package net.runelite.client.plugins.theatre.rooms;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.Random;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicsObject;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.theatre.RoomHandler;
|
||||
import net.runelite.client.plugins.theatre.TheatreConfig;
|
||||
import net.runelite.client.plugins.theatre.TheatrePlugin;
|
||||
import net.runelite.client.plugins.theatre.TheatreRoom;
|
||||
import net.runelite.client.plugins.theatre.RoomHandler;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Random;
|
||||
|
||||
public class BloatHandler extends RoomHandler
|
||||
{
|
||||
|
||||
public static enum BloatState
|
||||
{
|
||||
DOWN,
|
||||
UP,
|
||||
WARN;
|
||||
}
|
||||
|
||||
private int bloatTimer;
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private NPC bloat;
|
||||
|
||||
private int counter;
|
||||
|
||||
//My variables
|
||||
private boolean bloatFlag;
|
||||
int bloatTimer;
|
||||
private Color color;
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private BloatState bloatState;
|
||||
|
||||
@@ -49,7 +43,9 @@ public class BloatHandler extends RoomHandler
|
||||
public void onStart()
|
||||
{
|
||||
if (this.plugin.getRoom() == TheatreRoom.BLOAT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.reset();
|
||||
this.plugin.setRoom(TheatreRoom.BLOAT);
|
||||
@@ -106,8 +102,8 @@ public class BloatHandler extends RoomHandler
|
||||
WorldPoint point = WorldPoint.fromLocal(client, object.getLocation());
|
||||
if (!config.BloatFeetIndicatorRaveEdition())
|
||||
{
|
||||
drawTile(graphics, point, new Color(36, 248, 229), 2, 255, 10);
|
||||
}
|
||||
drawTile(graphics, point, new Color(36, 248, 229), 2, 255, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawTile(graphics, point, color, 2, 255, 10);
|
||||
@@ -120,15 +116,15 @@ public class BloatHandler extends RoomHandler
|
||||
if (config.showBloatTimer())
|
||||
{
|
||||
final String tickCounter = String.valueOf(bloatTimer);
|
||||
int secondConversion = (int)(bloatTimer * .6);
|
||||
int secondConversion = (int) (bloatTimer * .6);
|
||||
if (bloat != null)
|
||||
{
|
||||
Point canvasPoint = bloat.getCanvasTextLocation(graphics, tickCounter, 60);
|
||||
if (bloatTimer <= 37)
|
||||
if (bloatTimer <= 37)
|
||||
{
|
||||
renderTextLocation(graphics, tickCounter + "( " + secondConversion + " )", 15, Font.BOLD, Color.WHITE, canvasPoint);
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
renderTextLocation(graphics, tickCounter + "( " + secondConversion + " )", 15, Font.BOLD, Color.RED, canvasPoint);
|
||||
}
|
||||
@@ -139,9 +135,9 @@ public class BloatHandler extends RoomHandler
|
||||
@Subscribe
|
||||
public void onVarbitChanged(VarbitChanged event)
|
||||
{
|
||||
if (client.getVar(Varbits.BLOAT_DOOR) == 1)
|
||||
if (client.getVar(Varbits.BLOAT_DOOR) == 1)
|
||||
{
|
||||
if (!bloatFlag)
|
||||
if (!bloatFlag)
|
||||
{
|
||||
bloatTimer = 0;
|
||||
bloatFlag = true;
|
||||
@@ -149,12 +145,12 @@ public class BloatHandler extends RoomHandler
|
||||
}
|
||||
}
|
||||
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
int id = npc.getId();
|
||||
|
||||
if (id == NpcID.PESTILENT_BLOAT)
|
||||
if (id == NpcID.PESTILENT_BLOAT)
|
||||
{
|
||||
this.onStart();
|
||||
bloatTimer = 0;
|
||||
@@ -162,12 +158,12 @@ public class BloatHandler extends RoomHandler
|
||||
}
|
||||
}
|
||||
|
||||
public void onNpcDespawned(NpcDespawned event)
|
||||
public void onNpcDespawned(NpcDespawned event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
int id = npc.getId();
|
||||
|
||||
if (id == NpcID.PESTILENT_BLOAT)
|
||||
if (id == NpcID.PESTILENT_BLOAT)
|
||||
{
|
||||
this.onStop();
|
||||
bloatTimer = 0;
|
||||
@@ -175,9 +171,9 @@ public class BloatHandler extends RoomHandler
|
||||
}
|
||||
}
|
||||
|
||||
public void onGameTick()
|
||||
public void onGameTick()
|
||||
{
|
||||
if (plugin.getRoom() != TheatreRoom.BLOAT)
|
||||
if (plugin.getRoom() != TheatreRoom.BLOAT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -196,39 +192,46 @@ public class BloatHandler extends RoomHandler
|
||||
|
||||
counter++;
|
||||
|
||||
if (bloat.getAnimation() == -1)
|
||||
if (bloat.getAnimation() == -1)
|
||||
{
|
||||
bloatTimer++;
|
||||
counter = 0;
|
||||
if (bloat.getHealth() == 0)
|
||||
{
|
||||
bloatState = BloatState.DOWN;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
bloatState = BloatState.UP;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (25 < counter && counter < 35)
|
||||
if (25 < counter && counter < 35)
|
||||
{
|
||||
bloatState = BloatState.WARN;
|
||||
}
|
||||
else if (counter < 26)
|
||||
}
|
||||
else if (counter < 26)
|
||||
{
|
||||
bloatTimer = 0;
|
||||
bloatState = BloatState.DOWN;
|
||||
}
|
||||
else if (bloat.getModelHeight() == 568)
|
||||
}
|
||||
else if (bloat.getModelHeight() == 568)
|
||||
{
|
||||
bloatTimer = 0;
|
||||
bloatState = BloatState.DOWN;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
bloatState = BloatState.UP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum BloatState
|
||||
{
|
||||
DOWN,
|
||||
UP,
|
||||
WARN
|
||||
}
|
||||
}
|
||||
@@ -1,162 +1,308 @@
|
||||
package net.runelite.client.plugins.theatre.rooms;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicsObject;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.NpcDefinitionChanged;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.SpotAnimationChanged;
|
||||
import net.runelite.client.graphics.ModelOutlineRenderer;
|
||||
import net.runelite.client.plugins.theatre.RoomHandler;
|
||||
import net.runelite.client.plugins.theatre.TheatreConfig;
|
||||
import net.runelite.client.plugins.theatre.TheatreConstant;
|
||||
import net.runelite.client.plugins.theatre.TheatrePlugin;
|
||||
import net.runelite.client.plugins.theatre.TheatreRoom;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MaidenHandler extends RoomHandler
|
||||
@Slf4j
|
||||
public class MaidenHandler extends RoomHandler
|
||||
{
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private static final ImmutableSet<WorldPoint> N1 = ImmutableSet.of(
|
||||
new WorldPoint(3182, 4457, 0),
|
||||
new WorldPoint(3174, 4457, 0)
|
||||
);
|
||||
private static final ImmutableSet<WorldPoint> N2 = ImmutableSet.of(
|
||||
new WorldPoint(3178, 4457, 0),
|
||||
new WorldPoint(3186, 4455, 0),
|
||||
new WorldPoint(3186, 4457, 0)
|
||||
);
|
||||
private static final ImmutableSet<WorldPoint> S1 = ImmutableSet.of(
|
||||
new WorldPoint(3174, 4437, 0),
|
||||
new WorldPoint(3182, 4437, 0)
|
||||
);
|
||||
private static final ImmutableSet<WorldPoint> S2 = ImmutableSet.of(
|
||||
new WorldPoint(3186, 4439, 0),
|
||||
new WorldPoint(3186, 4437, 0),
|
||||
new WorldPoint(3178, 4437, 0)
|
||||
);
|
||||
private static final ImmutableSet<Integer> FREEZEANIMS = ImmutableSet.of(
|
||||
361,
|
||||
363,
|
||||
367,
|
||||
369
|
||||
);
|
||||
private static final Color TRANSPARENT = new Color(0, 0, 0, 0);
|
||||
private static final Color FREEZE = new Color(0, 226, 255, 255);
|
||||
private List<WorldPoint> bloodThrows = new ArrayList<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<NPC> bloodSpawns = new ArrayList<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<WorldPoint> bloodSpawnLocation = new ArrayList<>();
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<WorldPoint> bloodSpawnTarget = new ArrayList<>();
|
||||
|
||||
private NPC maiden;
|
||||
private String nyloCall;
|
||||
private Set<Nylos> nylos = new HashSet<>();
|
||||
private List<NPC> healers = new ArrayList<>();
|
||||
private int healerCount = 0;
|
||||
private int wave = 1;
|
||||
private long startTime = 0;
|
||||
private ModelOutlineRenderer modelOutline;
|
||||
|
||||
public MaidenHandler(Client client, TheatrePlugin plugin, TheatreConfig config)
|
||||
public MaidenHandler(Client client, TheatrePlugin plugin, TheatreConfig config, ModelOutlineRenderer modelOutline)
|
||||
{
|
||||
super(client, plugin, config);
|
||||
this.modelOutline = modelOutline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart()
|
||||
public void onStart()
|
||||
{
|
||||
if (this.plugin.getRoom() == TheatreRoom.MAIDEN)
|
||||
{
|
||||
return;
|
||||
|
||||
}
|
||||
this.reset();
|
||||
|
||||
this.plugin.setRoom(TheatreRoom.MAIDEN);
|
||||
this.startTime = System.currentTimeMillis();
|
||||
System.out.println("Starting Maiden Room");
|
||||
log.debug("Starting Maiden Room");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop()
|
||||
public void onStop()
|
||||
{
|
||||
this.reset();
|
||||
this.plugin.setRoom(TheatreRoom.UNKNOWN);
|
||||
System.out.println("Stopping Maiden Room");
|
||||
log.debug("Stopping Maiden Room");
|
||||
}
|
||||
|
||||
public void reset()
|
||||
public void reset()
|
||||
{
|
||||
this.bloodThrows.clear();
|
||||
this.bloodSpawns.clear();
|
||||
this.bloodSpawnLocation.clear();
|
||||
this.bloodSpawnTarget.clear();
|
||||
|
||||
this.healers.clear();
|
||||
this.nylos.clear();
|
||||
this.healerCount = 0;
|
||||
this.startTime = -1;
|
||||
this.wave = 1;
|
||||
}
|
||||
|
||||
public void render(Graphics2D graphics)
|
||||
public void render(Graphics2D graphics)
|
||||
{
|
||||
if (config.showMaidenBloodToss())
|
||||
for (Nylos nylo : nylos)
|
||||
{
|
||||
for (WorldPoint point : bloodThrows)
|
||||
if (nylo.getNpc() == null || nylo.getNpc().getId() == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
final String location = nylo.getSpawnLocation().getName();
|
||||
|
||||
if (nyloCall == null || nyloCall.equals(""))
|
||||
{
|
||||
nyloCall = "n1";
|
||||
}
|
||||
|
||||
if (location.equals(nyloCall))
|
||||
{
|
||||
Color color = Color.WHITE;
|
||||
int width = 4;
|
||||
|
||||
if (nylo.getNpc().getWorldArea().distanceTo(maiden.getWorldArea()) <= 3)
|
||||
{
|
||||
color = FREEZE;
|
||||
width = 8;
|
||||
}
|
||||
|
||||
modelOutline.drawOutline(nylo.getNpc(), width, color, TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.showMaidenBloodToss())
|
||||
{
|
||||
for (WorldPoint point : bloodThrows)
|
||||
{
|
||||
drawTile(graphics, point, new Color(36, 248, 229), 2, 150, 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.showMaidenBloodSpawns())
|
||||
if (config.showMaidenBloodSpawns())
|
||||
{
|
||||
for (WorldPoint point : bloodSpawnLocation)
|
||||
for (WorldPoint point : bloodSpawnLocation)
|
||||
{
|
||||
drawTile(graphics, point, new Color(36, 248, 229), 2, 180, 20);
|
||||
}
|
||||
|
||||
for (WorldPoint point : bloodSpawnTarget)
|
||||
for (WorldPoint point : bloodSpawnTarget)
|
||||
{
|
||||
drawTile(graphics, point, new Color(36, 248, 229), 1, 120, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
public void onSpotAnimationChanged(SpotAnimationChanged event)
|
||||
{
|
||||
if (event.getActor() instanceof NPC)
|
||||
{
|
||||
NPC npc = (NPC) event.getActor();
|
||||
|
||||
if (npc.getId() != 8366)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int anim = npc.getSpotAnimation();
|
||||
|
||||
if (FREEZEANIMS.contains(anim))
|
||||
{
|
||||
nylos.removeIf(c -> c.getNpc() == npc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
String name = npc.getName();
|
||||
int id = npc.getId();
|
||||
|
||||
if (npc.getName() != null && name.equals("The Maiden of Sugadinti"))
|
||||
if (npc.getName() == null)
|
||||
{
|
||||
this.onStart();
|
||||
}
|
||||
else if (plugin.getRoom() == TheatreRoom.MAIDEN)
|
||||
return;
|
||||
}
|
||||
|
||||
switch (npc.getName())
|
||||
{
|
||||
if (id == NpcID.BLOOD_SPAWN)
|
||||
{
|
||||
if (!bloodSpawns.contains(npc))
|
||||
bloodSpawns.add(npc);
|
||||
}
|
||||
else if (name != null && name.equalsIgnoreCase("Nylocas Matomenos"))
|
||||
{
|
||||
case "The Maiden of Sugadinti":
|
||||
this.onStart();
|
||||
maiden = npc;
|
||||
break;
|
||||
case "Nylocas Matomenos":
|
||||
if (!config.showNyloFreezeHighlights())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.healers.add(npc);
|
||||
}
|
||||
|
||||
WorldPoint wp = WorldPoint.fromLocalInstance(client, npc.getLocalLocation());
|
||||
|
||||
if (N1.contains(wp))
|
||||
{
|
||||
addNylo(npc, Nylos.SpawnLocation.N1);
|
||||
}
|
||||
if (N2.contains(wp))
|
||||
{
|
||||
addNylo(npc, Nylos.SpawnLocation.N2);
|
||||
}
|
||||
if (S1.contains(wp))
|
||||
{
|
||||
addNylo(npc, Nylos.SpawnLocation.S1);
|
||||
}
|
||||
if (S2.contains(wp))
|
||||
{
|
||||
addNylo(npc, Nylos.SpawnLocation.S2);
|
||||
}
|
||||
if (!N1.contains(wp) && !N2.contains(wp) && !S1.contains(wp) && !S2.contains(wp))
|
||||
{
|
||||
log.info("No World Points Matched");
|
||||
log.info("Instance Loc: " + wp);
|
||||
}
|
||||
break;
|
||||
case "Blood spawn":
|
||||
if (!bloodSpawns.contains(npc))
|
||||
{
|
||||
bloodSpawns.add(npc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onNpcDespawned(NpcDespawned event)
|
||||
public void onNpcDefinitionChanged(NpcDefinitionChanged event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
String name = npc.getName();
|
||||
int id = npc.getId();
|
||||
|
||||
if (npc.getName() != null && name.equals("The Maiden of Sugadinti"))
|
||||
if (npc.getName() != null && npc.getName().equals("Nylocas Matomenos"))
|
||||
{
|
||||
this.onStop();
|
||||
}
|
||||
else if (plugin.getRoom() == TheatreRoom.MAIDEN)
|
||||
{
|
||||
if (id == NpcID.BLOOD_SPAWN)
|
||||
if (npc.getId() == -1)
|
||||
{
|
||||
bloodSpawns.remove(npc);
|
||||
nylos.removeIf(c -> c.getNpc() == npc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onGameTick()
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (plugin.getRoom() != TheatreRoom.MAIDEN)
|
||||
if (event.getSender() != null && !event.getSender().equals(client.getLocalPlayer().getName()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String msg = Text.standardize(event.getMessageNode().getValue());
|
||||
|
||||
switch (msg)
|
||||
{
|
||||
case "n1":
|
||||
case "n2":
|
||||
case "s1":
|
||||
case "s2":
|
||||
nyloCall = msg;
|
||||
log.debug("Nylo Call Assigned: " + msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onNpcDespawned(NpcDespawned event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
|
||||
if (npc.getName() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (npc.getName())
|
||||
{
|
||||
case "The Maiden of Sugadinti":
|
||||
this.onStop();
|
||||
break;
|
||||
case "Blood Spawn":
|
||||
bloodSpawns.remove(npc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onGameTick()
|
||||
{
|
||||
if (plugin.getRoom() != TheatreRoom.MAIDEN)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bloodThrows.clear();
|
||||
for (GraphicsObject o : client.getGraphicsObjects())
|
||||
|
||||
for (GraphicsObject o : client.getGraphicsObjects())
|
||||
{
|
||||
if (o.getId() == TheatreConstant.MAIDEN_BLOOD_THROW)
|
||||
if (o.getId() == TheatreConstant.MAIDEN_BLOOD_THROW)
|
||||
{
|
||||
bloodThrows.add(WorldPoint.fromLocal(client, o.getLocation()));
|
||||
}
|
||||
@@ -164,12 +310,13 @@ public class MaidenHandler extends RoomHandler
|
||||
|
||||
bloodSpawnLocation = new ArrayList<>(bloodSpawnTarget);
|
||||
bloodSpawnTarget.clear();
|
||||
for (NPC spawn : bloodSpawns)
|
||||
|
||||
for (NPC spawn : bloodSpawns)
|
||||
{
|
||||
bloodSpawnTarget.add(spawn.getWorldLocation());
|
||||
}
|
||||
|
||||
if (this.healerCount != this.healers.size())
|
||||
if (this.healerCount != this.healers.size())
|
||||
{
|
||||
this.healerCount = this.healers.size();
|
||||
|
||||
@@ -181,7 +328,15 @@ public class MaidenHandler extends RoomHandler
|
||||
|
||||
int percentage = 70 - (20 * ((wave++) - 1));
|
||||
if (config.extraTimers())
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'The Maiden of Sugadinti - " + percentage + "%' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
{
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'The Maiden of Sugadinti - " + percentage + "%' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void addNylo(NPC npc, Nylos.SpawnLocation spawnLocation)
|
||||
{
|
||||
nylos.add(new Nylos(npc, spawnLocation));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package net.runelite.client.plugins.theatre.rooms;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.NPC;
|
||||
|
||||
class Nylos
|
||||
{
|
||||
@Getter
|
||||
private NPC npc;
|
||||
@Getter
|
||||
private int npcIndex;
|
||||
@Getter
|
||||
@Setter
|
||||
private SpawnLocation spawnLocation;
|
||||
|
||||
Nylos(NPC npc, SpawnLocation spawnLocation)
|
||||
{
|
||||
this.npc = npc;
|
||||
this.npcIndex = npc.getIndex();
|
||||
this.spawnLocation = spawnLocation;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
enum SpawnLocation
|
||||
{
|
||||
N1("n1"),
|
||||
N2("n2"),
|
||||
S1("s1"),
|
||||
S2("s2");
|
||||
|
||||
private String name;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,23 @@
|
||||
package net.runelite.client.plugins.theatre.rooms;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.*;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GroundObject;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.Projectile;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.GroundObjectSpawned;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
@@ -16,33 +30,24 @@ import net.runelite.client.plugins.theatre.TheatrePlugin;
|
||||
import net.runelite.client.plugins.theatre.TheatreRoom;
|
||||
import net.runelite.client.ui.overlay.OverlayUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class SotetsegHandler extends RoomHandler
|
||||
{
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private final Map<GroundObject, Tile> redTiles = new LinkedHashMap<>();
|
||||
|
||||
//My variables
|
||||
private int playerX;
|
||||
private int playerY;
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private List<WorldPoint> redOverworld = new ArrayList<>();
|
||||
|
||||
private List<WorldPoint> blackOverworld = new ArrayList<>();
|
||||
|
||||
private List<WorldPoint> blackUnderworld = new ArrayList<>();
|
||||
|
||||
private List<WorldPoint> redUnderworld = new ArrayList<>();
|
||||
|
||||
private List<Point> gridPath = new ArrayList<>();
|
||||
|
||||
//My variables
|
||||
int playerX;
|
||||
int playerY;
|
||||
private Map<Projectile, WorldPoint> soteyProjectiles = new HashMap<>();
|
||||
private NPC npc;
|
||||
private long startTime = 0;
|
||||
|
||||
public SotetsegHandler(Client client, TheatrePlugin plugin, TheatreConfig config)
|
||||
{
|
||||
super(client, plugin, config);
|
||||
@@ -52,7 +57,9 @@ public class SotetsegHandler extends RoomHandler
|
||||
public void onStart()
|
||||
{
|
||||
if (this.plugin.getRoom() == TheatreRoom.SOTETSEG)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.reset();
|
||||
this.plugin.setRoom(TheatreRoom.SOTETSEG);
|
||||
@@ -125,68 +132,16 @@ public class SotetsegHandler extends RoomHandler
|
||||
String countdownStr;
|
||||
if (id == 1607)
|
||||
{
|
||||
countdownStr = "R " + String.valueOf(ticksRemaining);
|
||||
countdownStr = "R " + ticksRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
countdownStr = "M " + String.valueOf(ticksRemaining);
|
||||
countdownStr = "M " + ticksRemaining;
|
||||
}
|
||||
|
||||
projectileMap.put(p, countdownStr);
|
||||
}
|
||||
renderProjectiles(graphics, projectileMap);
|
||||
//Legacy code from yuri, works great but shows all projectiles not just ones targetting local player
|
||||
/**
|
||||
for (Projectile projectile : client.getProjectiles())
|
||||
{
|
||||
int id = projectile.getId();
|
||||
|
||||
String name = null;
|
||||
Color color = null;
|
||||
|
||||
double millis = projectile.getRemainingCycles();
|
||||
double ticks = millis / 60; // 10 millis per cycle, 0.6 ticks per second, 10/0.6 = 60
|
||||
double round = Math.round(ticks * 10d) / 10d;
|
||||
if (id == TheatreConstant.SOTETSEG_BOMB)
|
||||
{
|
||||
name = "" + round;
|
||||
color = Color.WHITE;
|
||||
}
|
||||
else if (id == TheatreConstant.SOTETSEG_MAGE)
|
||||
{
|
||||
|
||||
name = "" + round;
|
||||
color = new Color(64, 224, 208, 255);
|
||||
}
|
||||
else if (id == TheatreConstant.SOTETSEG_RANGE)
|
||||
{
|
||||
name = "" + round;
|
||||
color = new Color(57, 255, 20, 255);
|
||||
}
|
||||
|
||||
if (name != null)
|
||||
{
|
||||
int x = (int) projectile.getX();
|
||||
int y = (int) projectile.getY();
|
||||
|
||||
LocalPoint point = new LocalPoint(x, y);
|
||||
Point loc = Perspective.getCanvasTextLocation(client, graphics, point, name, 0);
|
||||
|
||||
if (loc != null)
|
||||
{
|
||||
if (id == TheatreConstant.SOTETSEG_BOMB)
|
||||
{
|
||||
graphics.setFont(new Font("Arial", Font.BOLD, 20));
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.setFont(new Font("Arial", Font.BOLD, 17));
|
||||
}
|
||||
|
||||
OverlayUtil.renderTextLocation(graphics, loc, name, color);
|
||||
}
|
||||
}
|
||||
}**/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,12 +197,16 @@ public class SotetsegHandler extends RoomHandler
|
||||
if (t.getPlane() == 0)
|
||||
{
|
||||
if (!blackOverworld.contains(p))
|
||||
{
|
||||
blackOverworld.add(p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!blackUnderworld.contains(p))
|
||||
{
|
||||
blackUnderworld.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,7 +224,9 @@ public class SotetsegHandler extends RoomHandler
|
||||
else
|
||||
{
|
||||
if (!redUnderworld.contains(p))
|
||||
{
|
||||
redUnderworld.add(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,19 +243,10 @@ public class SotetsegHandler extends RoomHandler
|
||||
playerY = client.getLocalPlayer().getLocalLocation().getY();
|
||||
|
||||
|
||||
|
||||
|
||||
//Remove projectiles that are about to die
|
||||
if (!soteyProjectiles.isEmpty())
|
||||
{
|
||||
for (Iterator<Projectile> it = soteyProjectiles.keySet().iterator(); it.hasNext(); )
|
||||
{
|
||||
Projectile projectile = it.next();
|
||||
if (projectile.getRemainingCycles() < 1)
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
soteyProjectiles.keySet().removeIf(p -> p.getRemainingCycles() < 1);
|
||||
}
|
||||
|
||||
boolean sotetsegFighting = false;
|
||||
@@ -338,7 +290,7 @@ public class SotetsegHandler extends RoomHandler
|
||||
WorldPoint pW = new WorldPoint(p.getX() - 1, p.getY(), p.getPlane());
|
||||
|
||||
if (!((redUnderworld.contains(pN) && redUnderworld.contains(pS)) ||
|
||||
(redUnderworld.contains(pE) && redUnderworld.contains(pW))))
|
||||
(redUnderworld.contains(pE) && redUnderworld.contains(pW))))
|
||||
{
|
||||
gridPath.add(new Point(p.getX() - minX, p.getY() - minY));
|
||||
if (!messageSent)
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
package net.runelite.client.plugins.theatre.rooms;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Actor;
|
||||
@@ -22,38 +29,26 @@ import net.runelite.client.plugins.theatre.TheatreConfig;
|
||||
import net.runelite.client.plugins.theatre.TheatreConstant;
|
||||
import net.runelite.client.plugins.theatre.TheatrePlugin;
|
||||
import net.runelite.client.plugins.theatre.TheatreRoom;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class VerzikHandler extends RoomHandler
|
||||
{
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final Map<Projectile, WorldPoint> Verzik_RangeProjectiles = new HashMap<>();
|
||||
|
||||
//My variables
|
||||
private int redCrabsTimer;
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private int versikCounter = 0;
|
||||
private int attacksLeft = 0;
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private NPC npc;
|
||||
|
||||
private int lastId = -1;
|
||||
|
||||
private int autosSinceYellows;
|
||||
private int yellows;
|
||||
|
||||
private boolean tornados;
|
||||
|
||||
private int attackTick = -1;
|
||||
|
||||
private long startTime = 0;
|
||||
|
||||
//My variables
|
||||
int redCrabsTimer;
|
||||
|
||||
public VerzikHandler(Client client, TheatrePlugin plugin, TheatreConfig config)
|
||||
{
|
||||
super(client, plugin, config);
|
||||
@@ -63,7 +58,9 @@ public class VerzikHandler extends RoomHandler
|
||||
public void onStart()
|
||||
{
|
||||
if (this.plugin.getRoom() == TheatreRoom.VERSIK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.reset();
|
||||
this.plugin.setRoom(TheatreRoom.VERSIK);
|
||||
@@ -117,10 +114,10 @@ public class VerzikHandler extends RoomHandler
|
||||
if (this.versikCounter >= 0)
|
||||
{
|
||||
String str = Integer.toString(versikCounter);
|
||||
|
||||
|
||||
LocalPoint lp = npc.getLocalLocation();
|
||||
Point point = Perspective.getCanvasTextLocation(client, graphics, lp, str, 0);
|
||||
|
||||
|
||||
renderTextLocation(graphics, str, 20, Font.BOLD, Color.CYAN, point);
|
||||
}
|
||||
}
|
||||
@@ -141,19 +138,6 @@ public class VerzikHandler extends RoomHandler
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (npc.getAnimation() == 8117){
|
||||
if (this.redCrabsTimer > 0){
|
||||
String str = Integer.toString(redCrabsTimer);
|
||||
|
||||
LocalPoint lp = npc.getLocalLocation();
|
||||
Point point = Perspective.getCanvasTextLocation(client, graphics, lp, str, 60);
|
||||
renderTextLocation(graphics, str, 15, Font.BOLD, Color.WHITE, point);
|
||||
}
|
||||
|
||||
|
||||
}*/
|
||||
|
||||
else if (id == TheatreConstant.VERZIK_ID_P3)
|
||||
{
|
||||
if (config.p3attacks())
|
||||
@@ -162,10 +146,10 @@ public class VerzikHandler extends RoomHandler
|
||||
if (versikCounter > 0 && versikCounter < 8)
|
||||
{
|
||||
String str = Math.max(versikCounter, 0) + "";// + " | " + model.getModelHeight();// + " | " + model.getRadius();
|
||||
|
||||
|
||||
LocalPoint lp = npc.getLocalLocation();
|
||||
Point point = Perspective.getCanvasTextLocation(client, graphics, lp, str, 0);
|
||||
|
||||
|
||||
renderTextLocation(graphics, str, 15, Font.BOLD, Color.WHITE, point);
|
||||
}
|
||||
}
|
||||
@@ -210,16 +194,22 @@ public class VerzikHandler extends RoomHandler
|
||||
for (NPC npc : client.getNpcs())
|
||||
{
|
||||
if (npc.getName() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Pattern p = Pattern.compile("Nylocas (Hagios|Toxobolos|Ischyros)");
|
||||
Matcher m = p.matcher(npc.getName());
|
||||
if (!m.matches())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Actor target = npc.getInteracting();
|
||||
if (target == null || target.getName() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
LocalPoint lp = npc.getLocalLocation();
|
||||
Color color = local.getName().equals(target.getName()) ? Color.RED : Color.GREEN;
|
||||
@@ -231,15 +221,17 @@ public class VerzikHandler extends RoomHandler
|
||||
}
|
||||
|
||||
}
|
||||
public void onProjectileMoved(ProjectileMoved event)
|
||||
{
|
||||
Projectile projectile = event.getProjectile();
|
||||
if (projectile.getId() == 1583)
|
||||
|
||||
public void onProjectileMoved(ProjectileMoved event)
|
||||
{
|
||||
WorldPoint p = WorldPoint.fromLocal(client, event.getPosition());
|
||||
Verzik_RangeProjectiles.put(projectile, p);
|
||||
Projectile projectile = event.getProjectile();
|
||||
if (projectile.getId() == 1583)
|
||||
{
|
||||
WorldPoint p = WorldPoint.fromLocal(client, event.getPosition());
|
||||
Verzik_RangeProjectiles.put(projectile, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
@@ -282,7 +274,9 @@ public void onProjectileMoved(ProjectileMoved event)
|
||||
|
||||
Actor actor = event.getActor();
|
||||
if (!(actor instanceof NPC))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
NPC npc = (NPC) actor;
|
||||
int id = npc.getId();
|
||||
@@ -325,29 +319,22 @@ public void onProjectileMoved(ProjectileMoved event)
|
||||
}
|
||||
if (!Verzik_RangeProjectiles.isEmpty())
|
||||
{
|
||||
for (Iterator<Projectile> it = Verzik_RangeProjectiles.keySet().iterator(); it.hasNext();)
|
||||
{
|
||||
Projectile projectile = it.next();
|
||||
if (projectile.getRemainingCycles() < 1)
|
||||
{
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
Verzik_RangeProjectiles.keySet().removeIf(p -> p.getRemainingCycles() < 1);
|
||||
}
|
||||
if (this.yellows == 0)
|
||||
{
|
||||
//if (this.autosSinceYellows > 0){
|
||||
for (GraphicsObject object : client.getGraphicsObjects())
|
||||
for (GraphicsObject object : client.getGraphicsObjects())
|
||||
{
|
||||
if (object.getId() == TheatreConstant.GRAPHIC_ID_YELLOWS)
|
||||
{
|
||||
if (object.getId() == TheatreConstant.GRAPHIC_ID_YELLOWS)
|
||||
{
|
||||
this.yellows = 14;
|
||||
this.yellows = 14;
|
||||
// this.versikCounter = 22;
|
||||
this.autosSinceYellows = 0;
|
||||
System.out.println("Yellows have spawned.");
|
||||
break;
|
||||
}
|
||||
this.autosSinceYellows = 0;
|
||||
System.out.println("Yellows have spawned.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
else
|
||||
@@ -380,7 +367,9 @@ public void onProjectileMoved(ProjectileMoved event)
|
||||
}
|
||||
|
||||
if (foundTornado && foundVerzik)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundVerzik)
|
||||
@@ -390,7 +379,9 @@ public void onProjectileMoved(ProjectileMoved event)
|
||||
}
|
||||
|
||||
if (npc == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int id = npc.getId();
|
||||
|
||||
@@ -410,7 +401,9 @@ public void onProjectileMoved(ProjectileMoved event)
|
||||
long minutes = seconds / 60L;
|
||||
seconds = seconds % 60;
|
||||
if (config.extraTimers())
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'The Final Challenge - Part 1' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
{
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'The Final Challenge - Part 1' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
}
|
||||
}
|
||||
else if (id == TheatreConstant.VERZIK_ID_P2_TRANSFORM && this.startTime != 0)
|
||||
{
|
||||
@@ -424,7 +417,9 @@ public void onProjectileMoved(ProjectileMoved event)
|
||||
this.versikCounter = -1;
|
||||
this.attacksLeft = 9;
|
||||
if (config.extraTimers())
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'The Final Challenge - Part 2' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
{
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'The Final Challenge - Part 2' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,7 +438,9 @@ public void onProjectileMoved(ProjectileMoved event)
|
||||
{
|
||||
versikCounter--;
|
||||
if (versikCounter < 0)
|
||||
{
|
||||
versikCounter = 0;
|
||||
}
|
||||
}
|
||||
else if (id == TheatreConstant.VERZIK_ID_P3)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
package net.runelite.client.plugins.theatre.rooms.nylocas;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -18,41 +30,26 @@ import net.runelite.client.plugins.theatre.TheatreConstant;
|
||||
import net.runelite.client.plugins.theatre.TheatrePlugin;
|
||||
import net.runelite.client.plugins.theatre.TheatreRoom;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class NyloHandler extends RoomHandler
|
||||
public class NyloHandler extends RoomHandler
|
||||
{
|
||||
|
||||
public long startTime = 0L;
|
||||
int startTick = 0;
|
||||
ArrayList<NPC> waveSpawns = new ArrayList<NPC>();
|
||||
ArrayList<NPC> waveAgros = new ArrayList<NPC>();
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private Map<NPC, Integer> pillars = new HashMap<>();
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private Map<NPC, Integer> spiders = new HashMap<>();
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private int wave = 0;
|
||||
|
||||
private NyloOverlay overlay = null;
|
||||
private NyloPredictor predictor = null;
|
||||
|
||||
private Point south = new Point(64, 41);
|
||||
private Point west = new Point(49, 56);
|
||||
private Point east = new Point(78, 56);
|
||||
|
||||
public long startTime = 0L;
|
||||
public int startTick = 0;
|
||||
|
||||
public ArrayList<NPC> waveSpawns = new ArrayList<NPC>();
|
||||
public ArrayList<NPC> waveAgros = new ArrayList<NPC>();
|
||||
|
||||
public NyloHandler(Client client, TheatrePlugin plugin, TheatreConfig config)
|
||||
{
|
||||
super(client, plugin, config);
|
||||
@@ -62,7 +59,9 @@ public class NyloHandler extends RoomHandler
|
||||
public void onStart()
|
||||
{
|
||||
if (this.plugin.getRoom() == TheatreRoom.NYLOCAS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.reset();
|
||||
|
||||
@@ -102,7 +101,9 @@ public class NyloHandler extends RoomHandler
|
||||
if (this.startTime != 0)
|
||||
{
|
||||
if (config.extraTimers())
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'The Nylocas - Waves' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
{
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'The Nylocas - Waves' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
}
|
||||
}
|
||||
System.out.println("Stopping Nylocas Room");
|
||||
}
|
||||
@@ -159,7 +160,7 @@ public class NyloHandler extends RoomHandler
|
||||
for (NPC npc : pillars.keySet())
|
||||
{
|
||||
final int health = pillars.get(npc);
|
||||
final String healthStr = String.valueOf(health) + "%";
|
||||
final String healthStr = health + "%";
|
||||
WorldPoint p = npc.getWorldLocation();
|
||||
LocalPoint lp = LocalPoint.fromWorld(client, p.getX() + 1, p.getY() + 1);
|
||||
|
||||
@@ -203,45 +204,21 @@ public class NyloHandler extends RoomHandler
|
||||
|
||||
Set<NPC> toHighlight = new HashSet<NPC>();
|
||||
|
||||
/**
|
||||
if (config.highlightNyloParents())
|
||||
{
|
||||
for (NPC npc : new ArrayList<NPC>(this.waveSpawns))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (npc.getHealthRatio() == 0 || npc.isDead())
|
||||
{
|
||||
this.waveSpawns.remove(npc);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!toHighlight.contains(npc))
|
||||
toHighlight.add(npc);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}**/
|
||||
|
||||
if (config.highlightNyloAgros())
|
||||
if (config.highlightNyloAgros())
|
||||
{
|
||||
for (NPC npc : new ArrayList<NPC>(this.waveAgros))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (npc.getHealthRatio() == 0 || npc.isDead())
|
||||
if (npc.getHealthRatio() == 0 || npc.isDead())
|
||||
{
|
||||
this.waveAgros.remove(npc);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!toHighlight.contains(npc))
|
||||
toHighlight.add(npc);
|
||||
}
|
||||
catch (Exception ex)
|
||||
toHighlight.add(npc);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -258,58 +235,25 @@ public class NyloHandler extends RoomHandler
|
||||
String name = npc.getName() != null ? npc.getName() : "";
|
||||
|
||||
if (name.contains("Hagios"))
|
||||
{
|
||||
color = Color.CYAN;
|
||||
}
|
||||
else if (name.contains("Toxobolos"))
|
||||
{
|
||||
color = Color.GREEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
color = Color.LIGHT_GRAY;
|
||||
}
|
||||
|
||||
renderPoly(graphics, color, objectClickbox);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
if (config.showNylocasSpawns() && predictor != null)
|
||||
{
|
||||
NyloPredictor.Wave nextWave = predictor.getNextWave();
|
||||
if (nextWave != null)
|
||||
{
|
||||
TheatreConfig.NYLOCAS mark = config.highlightNyloRoles();
|
||||
|
||||
String southStr = predictor.getSpawnStr(NyloPredictor.Spawn.SOUTH, nextWave);
|
||||
if (southStr != null && south != null)
|
||||
{
|
||||
LocalPoint lp = LocalPoint.fromScene(south.getX(), south.getY());
|
||||
Point point = Perspective.getCanvasTextLocation(client, graphics, lp, southStr, 1);
|
||||
Color color = mark != TheatreConfig.NYLOCAS.NONE ? (((southStr.contains("Mage") && mark == TheatreConfig.NYLOCAS.MAGE) || (southStr.contains("Range") && mark == TheatreConfig.NYLOCAS.RANGER) || (southStr.contains("Melee") && mark == TheatreConfig.NYLOCAS.MELEE)) ? Color.MAGENTA : Color.RED) : Color.RED;
|
||||
renderTextLocation(graphics, southStr, 18, Font.BOLD, color, point);
|
||||
// drawTile(graphics, WorldPoint.fromLocal(client, lp), new Color(0, 150, 200), 2, 150, 10);
|
||||
}
|
||||
|
||||
String westStr = predictor.getSpawnStr(NyloPredictor.Spawn.WEST, nextWave);
|
||||
if (westStr != null && west != null)
|
||||
{
|
||||
LocalPoint lp = LocalPoint.fromScene(west.getX(), west.getY());
|
||||
Point point = Perspective.getCanvasTextLocation(client, graphics, lp, westStr, 1);
|
||||
Color color = mark != TheatreConfig.NYLOCAS.NONE ? (((westStr.contains("Mage") && mark == TheatreConfig.NYLOCAS.MAGE) || (westStr.contains("Range") && mark == TheatreConfig.NYLOCAS.RANGER) || (westStr.contains("Melee") && mark == TheatreConfig.NYLOCAS.MELEE)) ? Color.MAGENTA : Color.RED) : Color.RED;
|
||||
renderTextLocation(graphics, westStr, 18, Font.BOLD, color, point);
|
||||
// drawTile(graphics, WorldPoint.fromLocal(client, lp), new Color(0, 150, 200), 2, 150, 10);
|
||||
}
|
||||
|
||||
String eastStr = predictor.getSpawnStr(NyloPredictor.Spawn.EAST, nextWave);
|
||||
if (eastStr != null && east != null)
|
||||
{
|
||||
LocalPoint lp = LocalPoint.fromScene(east.getX(), east.getY());
|
||||
Point point = Perspective.getCanvasTextLocation(client, graphics, lp, eastStr, 1);
|
||||
Color color = mark != TheatreConfig.NYLOCAS.NONE ? (((eastStr.contains("Mage") && mark == TheatreConfig.NYLOCAS.MAGE) || (eastStr.contains("Range") && mark == TheatreConfig.NYLOCAS.RANGER) || (eastStr.contains("Melee") && mark == TheatreConfig.NYLOCAS.MELEE)) ? Color.MAGENTA : Color.RED) : Color.RED;
|
||||
renderTextLocation(graphics, eastStr, 18, Font.BOLD, color, point);
|
||||
// drawTile(graphics, WorldPoint.fromLocal(client, lp), new Color(0, 150, 200), 2, 150, 10);
|
||||
}
|
||||
}
|
||||
}**/
|
||||
}
|
||||
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
@@ -351,15 +295,9 @@ public class NyloHandler extends RoomHandler
|
||||
NPC npc = event.getNpc();
|
||||
int id = npc.getId();
|
||||
|
||||
if (this.waveSpawns.contains(npc))
|
||||
{
|
||||
this.waveSpawns.remove(npc);
|
||||
}
|
||||
this.waveSpawns.remove(npc);
|
||||
|
||||
if (this.waveAgros.contains(npc))
|
||||
{
|
||||
this.waveAgros.remove(npc);
|
||||
}
|
||||
this.waveAgros.remove(npc);
|
||||
|
||||
if (id == TheatreConstant.NPC_ID_NYLOCAS_PILLAR)
|
||||
{
|
||||
@@ -393,7 +331,7 @@ public class NyloHandler extends RoomHandler
|
||||
if (plugin.getRoom() != TheatreRoom.NYLOCAS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean findPillar = false;
|
||||
|
||||
@@ -39,21 +39,21 @@ 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.table.TableAlignment;
|
||||
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
class NyloOverlay extends Overlay
|
||||
class NyloOverlay extends Overlay
|
||||
{
|
||||
|
||||
private final Client client;
|
||||
|
||||
private final TheatrePlugin plugin;
|
||||
private final TheatreConfig config;
|
||||
private final PanelComponent panelComponent = new PanelComponent();
|
||||
|
||||
private NyloHandler nylohandler;
|
||||
|
||||
public NyloOverlay(Client client, TheatrePlugin plugin, TheatreConfig config, NyloHandler nylohandler)
|
||||
NyloOverlay(Client client, TheatrePlugin plugin, TheatreConfig config, NyloHandler nylohandler)
|
||||
{
|
||||
super(plugin);
|
||||
|
||||
@@ -62,7 +62,6 @@ class NyloOverlay extends Overlay
|
||||
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.config = config;
|
||||
this.nylohandler = nylohandler;
|
||||
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Nylocas Overlay"));
|
||||
@@ -102,6 +101,7 @@ class NyloOverlay extends Overlay
|
||||
|
||||
panelComponent.getChildren().clear();
|
||||
TableComponent tableComponent = new TableComponent();
|
||||
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
|
||||
|
||||
int nyloCount = (hagios + toxobolos + ischyros);
|
||||
if (nylohandler.getWave() < 21)
|
||||
@@ -109,14 +109,14 @@ class NyloOverlay extends Overlay
|
||||
if (nyloCount > 12)
|
||||
{
|
||||
tableComponent.addRow("Total Nylocas:", ColorUtil.prependColorTag(nyloCount + " / 12", Color.RED));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tableComponent.addRow("Total Nylocas:", ColorUtil.prependColorTag(nyloCount + " / 12", Color.GREEN));
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nyloCount > 24)
|
||||
{
|
||||
@@ -130,23 +130,6 @@ class NyloOverlay extends Overlay
|
||||
|
||||
panelComponent.getChildren().add(tableComponent);
|
||||
|
||||
|
||||
/**
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Ischyros:")
|
||||
.right(Integer.toString(ischyros))
|
||||
.build());
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Toxobolos:")
|
||||
.right(Integer.toString(toxobolos))
|
||||
.build());
|
||||
|
||||
panelComponent.getChildren().add(LineComponent.builder()
|
||||
.left("Hagios:")
|
||||
.right(Integer.toString(hagios))
|
||||
.build());
|
||||
**/
|
||||
return panelComponent.render(graphics);
|
||||
}
|
||||
}
|
||||
@@ -1,91 +1,19 @@
|
||||
package net.runelite.client.plugins.theatre.rooms.nylocas;
|
||||
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
|
||||
public class NyloPredictor
|
||||
{
|
||||
|
||||
public enum NylocasType
|
||||
{
|
||||
MELEE_162,
|
||||
RANGE_162,
|
||||
MAGE_162,
|
||||
MELEE_260,
|
||||
RANGE_260,
|
||||
MAGE_260;
|
||||
}
|
||||
|
||||
public enum Spawn
|
||||
{
|
||||
WEST,
|
||||
SOUTH,
|
||||
EAST;
|
||||
}
|
||||
|
||||
public static class Nylocas
|
||||
{
|
||||
|
||||
private NylocasType type;
|
||||
private Spawn spawn;
|
||||
|
||||
public Nylocas(NylocasType type, Spawn spawn)
|
||||
private static final Wave[] NYLOCAS_WAVES = new Wave[]
|
||||
{
|
||||
this.type = type;
|
||||
this.spawn = spawn;
|
||||
}
|
||||
|
||||
public NylocasType getType()
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Spawn getSpawn()
|
||||
{
|
||||
return this.spawn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
if (object != null && (object instanceof Nylocas))
|
||||
{
|
||||
Nylocas nylo = (Nylocas) object;
|
||||
if (nylo.getType() == this.type && nylo.getSpawn() == this.spawn)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Wave
|
||||
{
|
||||
|
||||
private Nylocas[] spawns;
|
||||
|
||||
public Wave(Nylocas... nylocas)
|
||||
{
|
||||
this.spawns = nylocas;
|
||||
}
|
||||
|
||||
public Nylocas[] getSpawns()
|
||||
{
|
||||
return this.spawns;
|
||||
}
|
||||
}
|
||||
|
||||
public static final Wave[] NYLOCAS_WAVES = new Wave[]
|
||||
{
|
||||
new Wave(new Nylocas(NylocasType.RANGE_162, Spawn.WEST), new Nylocas(NylocasType.MAGE_162, Spawn.SOUTH), new Nylocas(NylocasType.MELEE_162, Spawn.EAST)),
|
||||
new Wave(new Nylocas(NylocasType.MAGE_162, Spawn.WEST), new Nylocas(NylocasType.MELEE_162, Spawn.SOUTH), new Nylocas(NylocasType.RANGE_162, Spawn.EAST)),
|
||||
new Wave(new Nylocas(NylocasType.MELEE_162, Spawn.WEST), new Nylocas(NylocasType.RANGE_162, Spawn.SOUTH), new Nylocas(NylocasType.MAGE_162, Spawn.EAST)),
|
||||
@@ -117,15 +45,16 @@ public class NyloPredictor
|
||||
new Wave(new Nylocas(NylocasType.MELEE_162, Spawn.WEST), new Nylocas(NylocasType.RANGE_162, Spawn.WEST), new Nylocas(NylocasType.MELEE_260, Spawn.SOUTH), new Nylocas(NylocasType.RANGE_162, Spawn.EAST), new Nylocas(NylocasType.MAGE_162, Spawn.EAST)),
|
||||
new Wave(new Nylocas(NylocasType.RANGE_260, Spawn.WEST), new Nylocas(NylocasType.MAGE_162, Spawn.SOUTH), new Nylocas(NylocasType.MELEE_162, Spawn.SOUTH), new Nylocas(NylocasType.MAGE_260, Spawn.EAST)),
|
||||
new Wave(new Nylocas(NylocasType.MELEE_162, Spawn.WEST), new Nylocas(NylocasType.RANGE_162, Spawn.WEST), new Nylocas(NylocasType.MAGE_162, Spawn.SOUTH), new Nylocas(NylocasType.MELEE_162, Spawn.SOUTH), new Nylocas(NylocasType.RANGE_162, Spawn.EAST), new Nylocas(NylocasType.MAGE_162, Spawn.EAST))
|
||||
};
|
||||
|
||||
};
|
||||
public Client client;
|
||||
public NyloHandler handler;
|
||||
int westBound = 50;
|
||||
int eastBound = 77;
|
||||
int southBound = 42;
|
||||
private NyloHandler handler;
|
||||
private Map<Nylocas, NPC> currentSpawns = new HashMap<Nylocas, NPC>();
|
||||
private int currentIndex = -1;
|
||||
|
||||
public Map<Nylocas, NPC> currentSpawns = new HashMap<Nylocas, NPC>();
|
||||
public int currentIndex = -1;
|
||||
|
||||
public NyloPredictor(Client client, NyloHandler handler)
|
||||
NyloPredictor(Client client, NyloHandler handler)
|
||||
{
|
||||
this.client = client;
|
||||
this.handler = handler;
|
||||
@@ -138,12 +67,6 @@ public class NyloPredictor
|
||||
this.currentIndex = -1;
|
||||
}
|
||||
|
||||
public int westBound = 50;
|
||||
|
||||
public int eastBound = 77;
|
||||
|
||||
public int southBound = 42;
|
||||
|
||||
public void onNpcSpawned(NpcSpawned event)
|
||||
{
|
||||
NPC npc = event.getNpc();
|
||||
@@ -157,11 +80,11 @@ public class NyloPredictor
|
||||
if (x <= westBound)
|
||||
{
|
||||
spawn = Spawn.WEST;
|
||||
}
|
||||
}
|
||||
else if (x >= eastBound)
|
||||
{
|
||||
spawn = Spawn.EAST;
|
||||
}
|
||||
}
|
||||
else if (y <= southBound)
|
||||
{
|
||||
spawn = Spawn.SOUTH;
|
||||
@@ -175,11 +98,11 @@ public class NyloPredictor
|
||||
if (name.contains("Hagios"))
|
||||
{
|
||||
type = NylocasType.valueOf("MAGE_" + level);
|
||||
}
|
||||
}
|
||||
else if (name.contains("Toxobolos"))
|
||||
{
|
||||
type = NylocasType.valueOf("RANGE_" + level);
|
||||
}
|
||||
}
|
||||
else if (name.contains("Ischyros"))
|
||||
{
|
||||
type = NylocasType.valueOf("MELEE_" + level);
|
||||
@@ -213,7 +136,7 @@ public class NyloPredictor
|
||||
int index = queue.indexOf(nylocas);
|
||||
Nylocas hashed = queue.remove(index);
|
||||
npcs.put(currentSpawns.get(hashed), hashed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
found = false;
|
||||
@@ -257,12 +180,14 @@ public class NyloPredictor
|
||||
for (NPC npc : client.getNpcs())
|
||||
{
|
||||
if (npc.getHealthRatio() == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (npc.getName().equalsIgnoreCase("Nylocas Hagios"))
|
||||
{
|
||||
mage_level += npc.getCombatLevel();
|
||||
mage_count += 1;
|
||||
}
|
||||
}
|
||||
else if (npc.getName().equalsIgnoreCase("Nylocas Toxobolos"))
|
||||
{
|
||||
range_level += npc.getCombatLevel();
|
||||
@@ -300,7 +225,7 @@ public class NyloPredictor
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAgressive(NylocasType type, Spawn spawn, int wave)
|
||||
private boolean isAgressive(NylocasType type, Spawn spawn, int wave)
|
||||
{
|
||||
if (wave == 0 && spawn == Spawn.WEST)
|
||||
{
|
||||
@@ -329,9 +254,13 @@ public class NyloPredictor
|
||||
else if (wave == 9)
|
||||
{
|
||||
if (spawn == Spawn.EAST && type == NylocasType.RANGE_162)
|
||||
{
|
||||
return true;
|
||||
else if (spawn == Spawn.WEST)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return spawn == Spawn.WEST;
|
||||
}
|
||||
}
|
||||
else if (wave == 10 && (spawn == Spawn.EAST || spawn == Spawn.WEST))
|
||||
{
|
||||
@@ -344,23 +273,35 @@ public class NyloPredictor
|
||||
else if (wave == 12)
|
||||
{
|
||||
if (spawn == Spawn.WEST && type == NylocasType.MAGE_162)
|
||||
{
|
||||
return true;
|
||||
else if (spawn == Spawn.EAST)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return spawn == Spawn.EAST;
|
||||
}
|
||||
}
|
||||
else if (wave == 13)
|
||||
{
|
||||
if (spawn == Spawn.WEST && type == NylocasType.MELEE_162)
|
||||
{
|
||||
return true;
|
||||
else if (spawn == Spawn.EAST)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return spawn == Spawn.EAST;
|
||||
}
|
||||
}
|
||||
else if (wave == 14)
|
||||
{
|
||||
if (spawn == Spawn.WEST && type == NylocasType.RANGE_162)
|
||||
{
|
||||
return true;
|
||||
else if (spawn == Spawn.EAST && type == NylocasType.MAGE_162)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return spawn == Spawn.EAST && type == NylocasType.MAGE_162;
|
||||
}
|
||||
}
|
||||
else if (wave == 17 && spawn == Spawn.WEST)
|
||||
{
|
||||
@@ -405,17 +346,20 @@ public class NyloPredictor
|
||||
else if (wave == 28)
|
||||
{
|
||||
if (spawn == Spawn.EAST && type == NylocasType.RANGE_162)
|
||||
{
|
||||
return true;
|
||||
else if (spawn == Spawn.WEST && type == NylocasType.MELEE_162)
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return spawn == Spawn.WEST && type == NylocasType.MELEE_162;
|
||||
}
|
||||
|
||||
}
|
||||
else if (wave == 29 && spawn == Spawn.EAST)
|
||||
else
|
||||
{
|
||||
return true;
|
||||
return wave == 29 && spawn == Spawn.EAST;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getCurrentWave()
|
||||
@@ -487,4 +431,72 @@ public class NyloPredictor
|
||||
return types.length() > 0 ? types : null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum NylocasType
|
||||
{
|
||||
MELEE_162,
|
||||
RANGE_162,
|
||||
MAGE_162,
|
||||
MELEE_260,
|
||||
RANGE_260,
|
||||
MAGE_260
|
||||
}
|
||||
|
||||
public enum Spawn
|
||||
{
|
||||
WEST,
|
||||
SOUTH,
|
||||
EAST
|
||||
}
|
||||
|
||||
public static class Nylocas
|
||||
{
|
||||
|
||||
private NylocasType type;
|
||||
private Spawn spawn;
|
||||
|
||||
public Nylocas(NylocasType type, Spawn spawn)
|
||||
{
|
||||
this.type = type;
|
||||
this.spawn = spawn;
|
||||
}
|
||||
|
||||
public NylocasType getType()
|
||||
{
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public Spawn getSpawn()
|
||||
{
|
||||
return this.spawn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
if (object != null && (object instanceof Nylocas))
|
||||
{
|
||||
Nylocas nylo = (Nylocas) object;
|
||||
return nylo.getType() == this.type && nylo.getSpawn() == this.spawn;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Wave
|
||||
{
|
||||
|
||||
private Nylocas[] spawns;
|
||||
|
||||
public Wave(Nylocas... nylocas)
|
||||
{
|
||||
this.spawns = nylocas;
|
||||
}
|
||||
|
||||
public Nylocas[] getSpawns()
|
||||
{
|
||||
return this.spawns;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.components.PanelComponent;
|
||||
import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
import net.runelite.client.ui.overlay.components.table.TableAlignment;
|
||||
import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
|
||||
public class XarpusCounter extends Overlay
|
||||
@@ -21,10 +22,8 @@ public class XarpusCounter extends Overlay
|
||||
private final Client client;
|
||||
private final TheatrePlugin plugin;
|
||||
private final TheatreConfig config;
|
||||
|
||||
private XarpusHandler xarpusHandler;
|
||||
|
||||
PanelComponent panelComponent = new PanelComponent();
|
||||
private XarpusHandler xarpusHandler;
|
||||
|
||||
public XarpusCounter(Client client, TheatrePlugin plugin, TheatreConfig config, XarpusHandler xarpushandler)
|
||||
{
|
||||
@@ -50,16 +49,17 @@ public class XarpusCounter extends Overlay
|
||||
|
||||
// Build overlay title
|
||||
panelComponent.getChildren().add(TitleComponent.builder()
|
||||
.text(overlayTitle)
|
||||
.color(Color.GREEN)
|
||||
.build());
|
||||
.text(overlayTitle)
|
||||
.color(Color.GREEN)
|
||||
.build());
|
||||
|
||||
//Set the size of overlay
|
||||
panelComponent.setPreferredSize(new Dimension(
|
||||
graphics.getFontMetrics().stringWidth(overlayTitle) + 30, 0
|
||||
graphics.getFontMetrics().stringWidth(overlayTitle) + 30, 0
|
||||
));
|
||||
|
||||
TableComponent tableComponent = new TableComponent();
|
||||
tableComponent.setColumnAlignments(TableAlignment.LEFT, TableAlignment.RIGHT);
|
||||
tableComponent.addRow("Exhumes", String.valueOf(xarpusHandler.getExhumesCount()));
|
||||
|
||||
panelComponent.getChildren().add(tableComponent);
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
package net.runelite.client.plugins.theatre.rooms.xarpus;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Polygon;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
@@ -19,20 +27,13 @@ import net.runelite.client.plugins.theatre.TheatreConfig;
|
||||
import net.runelite.client.plugins.theatre.TheatreConstant;
|
||||
import net.runelite.client.plugins.theatre.TheatrePlugin;
|
||||
import net.runelite.client.plugins.theatre.TheatreRoom;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class XarpusHandler extends RoomHandler
|
||||
{
|
||||
|
||||
private int previousTurn;
|
||||
|
||||
private boolean staring;
|
||||
|
||||
private final Map<GroundObject, Integer> exhumes = new HashMap<>();
|
||||
|
||||
private int previousTurn;
|
||||
private boolean staring;
|
||||
private int ticksUntilShoot = 8;
|
||||
|
||||
@Getter
|
||||
@@ -56,7 +57,9 @@ public class XarpusHandler extends RoomHandler
|
||||
public void onStart()
|
||||
{
|
||||
if (this.plugin.getRoom() == TheatreRoom.XARPUS)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.reset();
|
||||
this.plugin.setRoom(TheatreRoom.XARPUS);
|
||||
@@ -102,7 +105,9 @@ public class XarpusHandler extends RoomHandler
|
||||
public void render(Graphics2D graphics)
|
||||
{
|
||||
if (npc == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (npc.getId() == NpcID.XARPUS_8340) //&& !staring&& config.showXarpusTick())
|
||||
{
|
||||
@@ -111,13 +116,15 @@ public class XarpusHandler extends RoomHandler
|
||||
this.up = true;
|
||||
long elapsedTime = System.currentTimeMillis() - this.startTime;
|
||||
long seconds = elapsedTime / 1000L;
|
||||
|
||||
|
||||
long minutes = seconds / 60L;
|
||||
seconds = seconds % 60;
|
||||
|
||||
|
||||
this.ticksUntilShoot = 8;
|
||||
if (config.extraTimers())
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'Xarpus - Recovery' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
{
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'Xarpus - Recovery' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
}
|
||||
}
|
||||
|
||||
final String ticksLeftStr = String.valueOf(ticksUntilShoot);
|
||||
@@ -257,7 +264,9 @@ public class XarpusHandler extends RoomHandler
|
||||
long minutes = seconds / 60L;
|
||||
seconds = seconds % 60;
|
||||
if (config.extraTimers())
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'Xarpus - Acid' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
{
|
||||
this.client.addChatMessage(ChatMessageType.GAMEMESSAGE, "", "Wave 'Xarpus - Acid' completed! Duration: <col=ff0000>" + minutes + ":" + twoDigitString(seconds), null);
|
||||
}
|
||||
}
|
||||
|
||||
ticksUntilShoot = 6;
|
||||
@@ -275,7 +284,7 @@ public class XarpusHandler extends RoomHandler
|
||||
if (staring)
|
||||
{
|
||||
ticksUntilShoot = 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ticksUntilShoot = 4;
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package net.runelite.client.plugins.theatre.timers;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.inject.Inject;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.client.plugins.theatre.TheatrePlugin;
|
||||
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 javax.inject.Inject;
|
||||
import java.awt.*;
|
||||
import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
|
||||
import static net.runelite.client.ui.overlay.OverlayManager.OPTION_CONFIGURE;
|
||||
|
||||
public class RoomTimer extends Overlay
|
||||
{
|
||||
@@ -25,9 +27,9 @@ public class RoomTimer extends Overlay
|
||||
|
||||
|
||||
@Inject
|
||||
public RoomTimer (Client client, TheatrePlugin plugin)
|
||||
public RoomTimer(Client client, TheatrePlugin plugin)
|
||||
{
|
||||
super (plugin);
|
||||
super(plugin);
|
||||
|
||||
setPosition(OverlayPosition.ABOVE_CHATBOX_RIGHT);
|
||||
setPriority(OverlayPriority.HIGH);
|
||||
@@ -40,15 +42,17 @@ public class RoomTimer extends Overlay
|
||||
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
panelComponent.getChildren().clear();
|
||||
|
||||
Player local = client.getLocalPlayer();
|
||||
if (local == null || local.getName() == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
switch (plugin.getRoom())
|
||||
switch (plugin.getRoom())
|
||||
{
|
||||
case MAIDEN:
|
||||
plugin.getMaidenHandler().render(graphics);
|
||||
|
||||
@@ -4,5 +4,5 @@ import java.util.HashMap;
|
||||
|
||||
public interface Timeable
|
||||
{
|
||||
public abstract HashMap<String, Long> getTimes();
|
||||
HashMap<String, Long> getTimes();
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public class WorldHopperPlugin extends Plugin
|
||||
{
|
||||
private static final int WORLD_FETCH_TIMER = 10;
|
||||
private static final int WORLD_PING_TIMER = 10;
|
||||
private static final int REFRESH_THROTTLE = 60_000; // ms
|
||||
private static final int REFRESH_THROTTLE = 60_000; // ms
|
||||
private static final int TICK_THROTTLE = (int) Duration.ofMinutes(10).toMillis();
|
||||
|
||||
private static final int DISPLAY_SWITCHER_MAX_ATTEMPTS = 3;
|
||||
|
||||
@@ -67,6 +67,7 @@ enum RareTreeLocation
|
||||
new WorldPoint(1640, 3496, 0),
|
||||
new WorldPoint(1613, 3494, 0),
|
||||
new WorldPoint(1560, 3636, 0),
|
||||
new WorldPoint(1646, 3590, 0),
|
||||
|
||||
// Miscellania
|
||||
new WorldPoint(2550, 3869, 0),
|
||||
@@ -109,9 +110,8 @@ enum RareTreeLocation
|
||||
new WorldPoint(1353, 3731, 0),
|
||||
new WorldPoint(1529, 3452, 0),
|
||||
new WorldPoint(1591, 3421, 0),
|
||||
new WorldPoint(1647, 3510, 0),
|
||||
new WorldPoint(1632, 3509, 0),
|
||||
new WorldPoint(1623, 3512, 0),
|
||||
new WorldPoint(1647, 3508, 0),
|
||||
new WorldPoint(1621, 3512, 0),
|
||||
new WorldPoint(1593, 3491, 0),
|
||||
new WorldPoint(1583, 3499, 0),
|
||||
new WorldPoint(1696, 3554, 0),
|
||||
@@ -119,6 +119,9 @@ enum RareTreeLocation
|
||||
new WorldPoint(1625, 3669, 0),
|
||||
new WorldPoint(1642, 3683, 0),
|
||||
new WorldPoint(1642, 3663, 0),
|
||||
new WorldPoint(1642, 3533, 0),
|
||||
new WorldPoint(1671, 3657, 0),
|
||||
new WorldPoint(1680, 3657, 0),
|
||||
|
||||
// Tirannwn
|
||||
new WorldPoint(2217, 3141, 0),
|
||||
@@ -187,8 +190,10 @@ enum RareTreeLocation
|
||||
new WorldPoint(1389, 3821, 0),
|
||||
new WorldPoint(1610, 3443, 0),
|
||||
new WorldPoint(1578, 3488, 0),
|
||||
new WorldPoint(1772, 3510, 0),
|
||||
new WorldPoint(1685, 3740, 0),
|
||||
new WorldPoint(1681, 3689, 0),
|
||||
new WorldPoint(1751, 3564, 0),
|
||||
new WorldPoint(1796, 3600, 0),
|
||||
|
||||
// Misthalin
|
||||
new WorldPoint(3355, 3312, 0),
|
||||
|
||||
@@ -28,6 +28,9 @@ package net.runelite.client.plugins.xptracker;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -79,12 +82,13 @@ class XpInfoBox extends JPanel
|
||||
/* The tracker's wrapping container */
|
||||
private final JPanel container = new JPanel();
|
||||
|
||||
/* Contains the skill icon and the stats panel */
|
||||
private final JPanel headerPanel = new JPanel();
|
||||
/* Contains the skill icon */
|
||||
private final JPanel skillWrapper = new JPanel();
|
||||
|
||||
/* Contains all the skill information (exp gained, per hour, etc) */
|
||||
private final JPanel statsPanel = new JPanel();
|
||||
|
||||
private final JPanel progressWrapper = new JPanel();
|
||||
private final ProgressBar progressBar = new ProgressBar();
|
||||
|
||||
private final JLabel expGained = new JLabel();
|
||||
@@ -98,6 +102,14 @@ class XpInfoBox extends JPanel
|
||||
|
||||
private boolean paused = false;
|
||||
|
||||
private Style style = Style.FULL;
|
||||
|
||||
private enum Style
|
||||
{
|
||||
FULL,
|
||||
SIMPLE
|
||||
}
|
||||
|
||||
XpInfoBox(XpTrackerPlugin xpTrackerPlugin, XpTrackerConfig xpTrackerConfig, Client client, JPanel panel, Skill skill, SkillIconManager iconManager)
|
||||
{
|
||||
this.xpTrackerConfig = xpTrackerConfig;
|
||||
@@ -134,6 +146,10 @@ class XpInfoBox extends JPanel
|
||||
popupMenu.add(pauseSkill);
|
||||
popupMenu.add(canvasItem);
|
||||
|
||||
skillWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
skillWrapper.setLayout(new BorderLayout());
|
||||
skillWrapper.setBorder(new EmptyBorder(0, 5, 0, 0));
|
||||
|
||||
canvasItem.addActionListener(e ->
|
||||
{
|
||||
if (canvasItem.getText().equals(REMOVE_STATE))
|
||||
@@ -151,14 +167,13 @@ class XpInfoBox extends JPanel
|
||||
JLabel skillIcon = new JLabel(new ImageIcon(iconManager.getSkillImage(skill)));
|
||||
skillIcon.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
skillIcon.setVerticalAlignment(SwingConstants.CENTER);
|
||||
skillIcon.setPreferredSize(new Dimension(35, 35));
|
||||
skillIcon.setPreferredSize(new Dimension(30, 30));
|
||||
|
||||
headerPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
headerPanel.setLayout(new BorderLayout());
|
||||
skillWrapper.add(skillIcon, BorderLayout.NORTH);
|
||||
|
||||
statsPanel.setLayout(new DynamicGridLayout(2, 2));
|
||||
statsPanel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
statsPanel.setBorder(new EmptyBorder(9, 2, 9, 2));
|
||||
statsPanel.setBorder(new EmptyBorder(6, 5, 0, 2));
|
||||
|
||||
expGained.setFont(FontManager.getRunescapeSmallFont());
|
||||
expHour.setFont(FontManager.getRunescapeSmallFont());
|
||||
@@ -170,13 +185,8 @@ class XpInfoBox extends JPanel
|
||||
statsPanel.add(expHour);
|
||||
statsPanel.add(actionsLeft);
|
||||
|
||||
headerPanel.add(skillIcon, BorderLayout.WEST);
|
||||
headerPanel.add(statsPanel, BorderLayout.CENTER);
|
||||
|
||||
JPanel progressWrapper = new JPanel();
|
||||
progressWrapper.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
progressWrapper.setLayout(new BorderLayout());
|
||||
progressWrapper.setBorder(new EmptyBorder(0, 7, 7, 7));
|
||||
|
||||
progressBar.setMaximumValue(100);
|
||||
progressBar.setBackground(new Color(61, 56, 49));
|
||||
@@ -185,15 +195,48 @@ class XpInfoBox extends JPanel
|
||||
|
||||
progressWrapper.add(progressBar, BorderLayout.NORTH);
|
||||
|
||||
container.add(headerPanel, BorderLayout.NORTH);
|
||||
container.add(progressWrapper, BorderLayout.SOUTH);
|
||||
|
||||
container.setComponentPopupMenu(popupMenu);
|
||||
progressBar.setComponentPopupMenu(popupMenu);
|
||||
|
||||
MouseListener mouseListener = new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
if (SwingUtilities.isLeftMouseButton(e))
|
||||
{
|
||||
toggleStyle();
|
||||
}
|
||||
}
|
||||
};
|
||||
container.addMouseListener(mouseListener);
|
||||
progressBar.addMouseListener(mouseListener);
|
||||
|
||||
add(container, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
void setStyle(Style style)
|
||||
{
|
||||
container.removeAll();
|
||||
|
||||
if (style == Style.SIMPLE)
|
||||
{
|
||||
progressWrapper.setBorder(new EmptyBorder(7, 7, 7, 7));
|
||||
container.add(skillWrapper, BorderLayout.WEST);
|
||||
container.add(progressWrapper, BorderLayout.CENTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
progressWrapper.setBorder(new EmptyBorder(4, 7, 7, 7));
|
||||
container.add(skillWrapper, BorderLayout.WEST);
|
||||
container.add(statsPanel, BorderLayout.CENTER);
|
||||
container.add(progressWrapper, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
panel.revalidate();
|
||||
this.style = style;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
canvasItem.setText(ADD_STATE);
|
||||
@@ -214,7 +257,7 @@ class XpInfoBox extends JPanel
|
||||
if (getParent() != panel)
|
||||
{
|
||||
panel.add(this);
|
||||
panel.revalidate();
|
||||
setStyle(style);
|
||||
}
|
||||
|
||||
paused = skillPaused;
|
||||
@@ -284,6 +327,18 @@ class XpInfoBox extends JPanel
|
||||
expHour.setText(htmlLabel("XP/Hour: ", xpSnapshotSingle.getXpPerHour()));
|
||||
}
|
||||
|
||||
private void toggleStyle()
|
||||
{
|
||||
if (style == Style.FULL)
|
||||
{
|
||||
setStyle(Style.SIMPLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setStyle(Style.FULL);
|
||||
}
|
||||
}
|
||||
|
||||
static String htmlLabel(String key, int value)
|
||||
{
|
||||
String valueStr = StackFormatter.quantityToRSDecimalStack(value, true);
|
||||
|
||||
Reference in New Issue
Block a user