Merge branch 'master' of https://github.com/open-osrs/runelite into spawn
# Conflicts: # runelite-client/src/main/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPlugin.java # runelite-client/src/test/java/net/runelite/client/plugins/npchighlight/NpcIndicatorsPluginTest.java
This commit is contained in:
@@ -58,7 +58,7 @@ public class ClientSessionManager
|
||||
}
|
||||
|
||||
@Schedule(period = 10, unit = ChronoUnit.MINUTES, asynchronous = true)
|
||||
private void ping()
|
||||
public void ping()
|
||||
{
|
||||
if (sessionId == null)
|
||||
{
|
||||
|
||||
@@ -32,6 +32,8 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.sentry.Sentry;
|
||||
import io.sentry.SentryClient;
|
||||
import java.io.File;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
@@ -59,6 +61,7 @@ import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.game.ClanManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.LootManager;
|
||||
import net.runelite.client.game.XpDropManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.graphics.ModelOutlineRenderer;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
@@ -76,7 +79,6 @@ import net.runelite.client.ui.overlay.arrow.ArrowWorldOverlay;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxOverlay;
|
||||
import net.runelite.client.ui.overlay.tooltip.TooltipOverlay;
|
||||
import net.runelite.client.ui.overlay.worldmap.WorldMapOverlay;
|
||||
import net.runelite.client.util.bootstrap.Bootstrapper;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
@@ -151,6 +153,9 @@ public class RuneLite
|
||||
@Inject
|
||||
private Provider<LootManager> lootManager;
|
||||
|
||||
@Inject
|
||||
private Provider<XpDropManager> xpDropManager;
|
||||
|
||||
@Inject
|
||||
private Provider<ChatboxPanelManager> chatboxPanelManager;
|
||||
|
||||
@@ -178,8 +183,6 @@ public class RuneLite
|
||||
parser.accepts("developer-mode", "Enable developer tools");
|
||||
parser.accepts("debug", "Show extra debugging output");
|
||||
parser.accepts("no-splash", "Do not show the splash screen");
|
||||
parser.accepts("bootstrap", "Builds a bootstrap with locally built jars");
|
||||
parser.accepts("bootstrap-staging", "Builds a testing bootstrap with locally built jars");
|
||||
final ArgumentAcceptingOptionSpec<String> proxyInfo = parser
|
||||
.accepts("proxy")
|
||||
.withRequiredArg().ofType(String.class);
|
||||
@@ -213,18 +216,6 @@ public class RuneLite
|
||||
logger.setLevel(Level.DEBUG);
|
||||
}
|
||||
|
||||
if (options.has("bootstrap"))
|
||||
{
|
||||
Bootstrapper.main(false);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
if (options.has("bootstrap-staging"))
|
||||
{
|
||||
Bootstrapper.main(true);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
if (options.has("proxy"))
|
||||
{
|
||||
String[] proxy = options.valueOf(proxyInfo).split(":");
|
||||
@@ -255,6 +246,10 @@ public class RuneLite
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SentryClient client = Sentry.init("https://fa31d674e44247fa93966c69a903770f@sentry.io/1811856");
|
||||
client.setRelease(RuneLiteProperties.getPlusVersion());
|
||||
|
||||
final ClientLoader clientLoader = new ClientLoader(options.valueOf(updateMode));
|
||||
Completable.fromAction(clientLoader::get)
|
||||
.subscribeOn(Schedulers.single())
|
||||
@@ -368,6 +363,7 @@ public class RuneLite
|
||||
chatMessageManager.get();
|
||||
commandManager.get();
|
||||
lootManager.get();
|
||||
xpDropManager.get();
|
||||
chatboxPanelManager.get();
|
||||
|
||||
eventBus.subscribe(GameStateChanged.class, this, hooks::onGameStateChanged);
|
||||
|
||||
@@ -27,6 +27,7 @@ package net.runelite.client;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RuneLiteProperties
|
||||
{
|
||||
@@ -40,7 +41,7 @@ public class RuneLiteProperties
|
||||
private static final String GITHUB_LINK = "runelite.github.link";
|
||||
private static final String WIKI_LINK = "runelite.wiki.link";
|
||||
private static final String PATREON_LINK = "runelite.patreon.link";
|
||||
private static final String LAUNCHER_VERSION_PROPERTY = "runelite.launcher.version";
|
||||
private static final String LAUNCHER_VERSION_PROPERTY = "launcher.version";
|
||||
private static final String TROUBLESHOOTING_LINK = "runelite.wiki.troubleshooting.link";
|
||||
private static final String BUILDING_LINK = "runelite.wiki.building.link";
|
||||
private static final String DNS_CHANGE_LINK = "runelite.dnschange.link";
|
||||
@@ -129,4 +130,11 @@ public class RuneLiteProperties
|
||||
{
|
||||
return properties.getProperty(DNS_CHANGE_LINK);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getLauncherVersion()
|
||||
{
|
||||
String launcherVersion = properties.getProperty(LAUNCHER_VERSION_PROPERTY);
|
||||
return launcherVersion.equals("-1") ? null : launcherVersion;
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,8 @@
|
||||
*/
|
||||
package net.runelite.client.chat;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiPredicate;
|
||||
@@ -42,7 +42,7 @@ import net.runelite.client.events.PrivateMessageInput;
|
||||
@Singleton
|
||||
public class ChatCommandManager implements ChatboxInputListener
|
||||
{
|
||||
private final Map<String, ChatCommand> commands = new HashMap<>();
|
||||
private final Map<String, ChatCommand> commands = new ConcurrentHashMap<>();
|
||||
|
||||
private final Client client;
|
||||
private final ScheduledExecutorService scheduledExecutorService;
|
||||
|
||||
@@ -46,7 +46,7 @@ import net.runelite.api.MessageNode;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.ResizeableChanged;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
@@ -558,16 +558,9 @@ public class ChatMessageManager
|
||||
|
||||
public void process()
|
||||
{
|
||||
if (!queuedMessages.isEmpty())
|
||||
for (QueuedMessage msg; (msg = queuedMessages.poll()) != null; )
|
||||
{
|
||||
try
|
||||
{
|
||||
queuedMessages.forEach(this::add);
|
||||
}
|
||||
finally
|
||||
{
|
||||
queuedMessages.clear();
|
||||
}
|
||||
add(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
*/
|
||||
package net.runelite.client.chat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -54,7 +54,7 @@ public class CommandManager
|
||||
private final ClientThread clientThread;
|
||||
private boolean sending;
|
||||
|
||||
private final List<ChatboxInputListener> chatboxInputListenerList = new ArrayList<>();
|
||||
private final List<ChatboxInputListener> chatboxInputListenerList = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Inject
|
||||
private CommandManager(
|
||||
|
||||
@@ -164,7 +164,7 @@ public interface ChatColorConfig extends Config
|
||||
position = 45,
|
||||
keyName = "opaqueServerMessage",
|
||||
name = "Server message",
|
||||
description = "Color of Server Messages (eg. 'Welcome to Runescape')"
|
||||
description = "Color of Server Messages (eg. 'Welcome to RuneScape')"
|
||||
)
|
||||
Color opaqueServerMessage();
|
||||
|
||||
@@ -404,7 +404,7 @@ public interface ChatColorConfig extends Config
|
||||
position = 75,
|
||||
keyName = "transparentServerMessage",
|
||||
name = "Server message (transparent)",
|
||||
description = "Color of Server Messages (eg. 'Welcome to Runescape') (transparent)"
|
||||
description = "Color of Server Messages (eg. 'Welcome to RuneScape') (transparent)"
|
||||
)
|
||||
Color transparentServerMessage();
|
||||
|
||||
|
||||
@@ -24,63 +24,56 @@
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
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;
|
||||
|
||||
@Slf4j
|
||||
class ConfigInvocationHandler implements InvocationHandler
|
||||
{
|
||||
// Special object to represent null values in the cache
|
||||
private static final Object NULL = new Object();
|
||||
|
||||
private final ConfigManager manager;
|
||||
private final Cache<Method, Object> cache = CacheBuilder.newBuilder()
|
||||
.maximumSize(128)
|
||||
.build();
|
||||
|
||||
// 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)
|
||||
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
|
||||
{
|
||||
String itemKeyName, groupValue;
|
||||
try
|
||||
// Use cached configuration value if available
|
||||
if (args == null)
|
||||
{
|
||||
groupValue = groupValueCache.computeIfAbsent(proxy.getClass(), ConfigInvocationHandler::groupValueFromProxy);
|
||||
Object cachedValue = cache.getIfPresent(method);
|
||||
if (cachedValue != null)
|
||||
{
|
||||
return cachedValue == NULL ? null : cachedValue;
|
||||
}
|
||||
}
|
||||
catch (NullPointerException e)
|
||||
|
||||
Class<?> iface = proxy.getClass().getInterfaces()[0];
|
||||
|
||||
ConfigGroup group = iface.getAnnotation(ConfigGroup.class);
|
||||
ConfigItem item = method.getAnnotation(ConfigItem.class);
|
||||
|
||||
if (group == null)
|
||||
{
|
||||
log.warn("Configuration proxy class {} has no @ConfigGroup!", proxy.getClass());
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
itemKeyName = methodKeyNameCache.computeIfAbsent(method, ConfigInvocationHandler::keyNameFromMethod);
|
||||
}
|
||||
catch (NullPointerException e)
|
||||
if (item == null)
|
||||
{
|
||||
log.warn("Configuration method {} has no @ConfigItem!", method);
|
||||
return null;
|
||||
@@ -88,48 +81,46 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
|
||||
if (args == null)
|
||||
{
|
||||
log.trace("cache miss (size: {}, group: {}, key: {})", cache.size(), group.value(), item.keyName());
|
||||
|
||||
// Getting configuration item
|
||||
return manager.getConfigObjectFromCacheOrElse(groupValue, itemKeyName, (value) ->
|
||||
String value = manager.getConfiguration(group.value(), item.keyName());
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
try
|
||||
if (method.isDefault())
|
||||
{
|
||||
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())
|
||||
{
|
||||
Object defaultValue = callDefaultMethod(proxy, method, null);
|
||||
|
||||
manager.setConfiguration(groupValue, itemKeyName, defaultValue);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Object defaultValue = callDefaultMethod(proxy, method, null);
|
||||
cache.put(method, defaultValue == null ? NULL : defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
catch (Throwable throwable)
|
||||
|
||||
cache.put(method, NULL);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert value to return type
|
||||
Class<?> returnType = method.getReturnType();
|
||||
|
||||
try
|
||||
{
|
||||
Object objectValue = ConfigManager.stringToObject(value, returnType);
|
||||
cache.put(method, objectValue == null ? NULL : objectValue);
|
||||
return objectValue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e);
|
||||
if (method.isDefault())
|
||||
{
|
||||
log.error("Unable to resolve configuration value {}.{}", groupValue, itemKeyName, throwable);
|
||||
return null;
|
||||
Object defaultValue = callDefaultMethod(proxy, method, null);
|
||||
|
||||
manager.setConfiguration(group.value(), item.keyName(), defaultValue);
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -137,13 +128,13 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
|
||||
if (args.length != 1)
|
||||
{
|
||||
throw new RuntimeException("Invalid number of arguments to configuration method");
|
||||
throw new RuntimeException("Invalid number of arguents to configuration method");
|
||||
}
|
||||
|
||||
Object newValue = args[0];
|
||||
|
||||
Class<?> type = method.getParameterTypes()[0];
|
||||
Object oldValue = manager.getConfiguration(groupValue, itemKeyName, type);
|
||||
Object oldValue = manager.getConfiguration(group.value(), item.keyName(), type);
|
||||
|
||||
if (Objects.equals(oldValue, newValue))
|
||||
{
|
||||
@@ -158,19 +149,19 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
if (Objects.equals(newValue, defaultValue))
|
||||
{
|
||||
// Just unset if it goes back to the default
|
||||
manager.unsetConfiguration(groupValue, itemKeyName);
|
||||
manager.unsetConfiguration(group.value(), item.keyName());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (newValue == null)
|
||||
{
|
||||
manager.unsetConfiguration(groupValue, itemKeyName);
|
||||
manager.unsetConfiguration(group.value(), item.keyName());
|
||||
}
|
||||
else
|
||||
{
|
||||
String newValueStr = ConfigManager.objectToString(newValue);
|
||||
manager.setConfiguration(groupValue, itemKeyName, newValueStr);
|
||||
manager.setConfiguration(group.value(), item.keyName(), newValueStr);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -188,4 +179,10 @@ class ConfigInvocationHandler implements InvocationHandler
|
||||
.bindTo(proxy)
|
||||
.invokeWithArguments(args);
|
||||
}
|
||||
}
|
||||
|
||||
void invalidate()
|
||||
{
|
||||
log.trace("cache invalidate");
|
||||
cache.invalidateAll();
|
||||
}
|
||||
}
|
||||
@@ -54,13 +54,12 @@ 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;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.RuneLite;
|
||||
import static net.runelite.client.RuneLite.PROFILES_DIR;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
@@ -81,7 +80,6 @@ public class ConfigManager
|
||||
|
||||
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
|
||||
@@ -154,6 +152,7 @@ public class ConfigManager
|
||||
|
||||
private synchronized void loadFromFile()
|
||||
{
|
||||
handler.invalidate();
|
||||
properties.clear();
|
||||
|
||||
try (FileInputStream in = new FileInputStream(SETTINGS_FILE))
|
||||
@@ -219,20 +218,6 @@ 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.class, configChanged);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getConfig(Class<T> clazz)
|
||||
{
|
||||
@@ -257,11 +242,6 @@ public class ConfigManager
|
||||
return properties.getProperty(groupName + "." + key);
|
||||
}
|
||||
|
||||
public String getConfiguration(String propertyKey)
|
||||
{
|
||||
return properties.getProperty(propertyKey);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getConfiguration(String groupName, String key, Class<T> clazz)
|
||||
{
|
||||
@@ -290,6 +270,7 @@ public class ConfigManager
|
||||
}
|
||||
|
||||
log.debug("Setting configuration value for {}.{} to {}", groupName, key, value);
|
||||
handler.invalidate();
|
||||
|
||||
synchronized (pendingChanges)
|
||||
{
|
||||
@@ -302,7 +283,7 @@ public class ConfigManager
|
||||
configChanged.setOldValue(oldValue);
|
||||
configChanged.setNewValue(value);
|
||||
|
||||
postConfigChanged(configChanged);
|
||||
eventBus.post(ConfigChanged.class, configChanged);
|
||||
}
|
||||
|
||||
public void setConfiguration(String groupName, String key, Object value)
|
||||
@@ -320,6 +301,7 @@ public class ConfigManager
|
||||
}
|
||||
|
||||
log.debug("Unsetting configuration value for {}.{}", groupName, key);
|
||||
handler.invalidate();
|
||||
|
||||
synchronized (pendingChanges)
|
||||
{
|
||||
|
||||
@@ -26,9 +26,53 @@
|
||||
*/
|
||||
package net.runelite.client.config;
|
||||
|
||||
import java.awt.Color;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@ConfigGroup("openosrs")
|
||||
public interface OpenOSRSConfig extends Config
|
||||
{
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
@AllArgsConstructor
|
||||
enum SortStyle
|
||||
{
|
||||
CATEGORY("Category"),
|
||||
ALPHABETICALLY("Alphabetically");
|
||||
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigTitleSection(
|
||||
keyName = "logTitle",
|
||||
name = "Error data",
|
||||
description = "",
|
||||
position = 1
|
||||
)
|
||||
default Title logTitle()
|
||||
{
|
||||
return new Title();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "shareLogs",
|
||||
name = "Anonymous error data",
|
||||
description = "Share anonymous error data with the OpenOSRS developers",
|
||||
titleSection = "logTitle"
|
||||
)
|
||||
default boolean shareLogs()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigTitleSection(
|
||||
keyName = "pluginsTitle",
|
||||
name = "Plugins",
|
||||
@@ -40,12 +84,215 @@ public interface OpenOSRSConfig extends Config
|
||||
return new Title();
|
||||
}
|
||||
|
||||
@ConfigTitleSection(
|
||||
keyName = "pluginSortingTitle",
|
||||
name = "Sorting",
|
||||
description = "",
|
||||
position = 2,
|
||||
titleSection = "pluginsTitle"
|
||||
)
|
||||
default Title pluginSortingTitle()
|
||||
{
|
||||
return new Title();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 3,
|
||||
keyName = "pluginSortMode",
|
||||
name = "Sorting mode",
|
||||
description = "Sorts plugins ",
|
||||
titleSection = "pluginSortingTitle"
|
||||
)
|
||||
default SortStyle pluginSortMode()
|
||||
{
|
||||
return SortStyle.CATEGORY;
|
||||
}
|
||||
|
||||
@ConfigTitleSection(
|
||||
keyName = "hidePluginsTitle",
|
||||
name = "Hide By Type",
|
||||
description = "",
|
||||
position = 4,
|
||||
titleSection = "pluginsTitle"
|
||||
)
|
||||
default Title hidePluginsTitle()
|
||||
{
|
||||
return new Title();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 5,
|
||||
keyName = "hidePlugins",
|
||||
name = "Hide All Plugins",
|
||||
description = "Hides all OpenOSRS plugins if checked",
|
||||
titleSection = "hidePluginsTitle",
|
||||
hide = "hidePvmPlugins || hidePvpPlugins || hideSkillingPlugins || hideUtilityPlugins || hideExternalPlugins"
|
||||
)
|
||||
default boolean hidePlugins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 6,
|
||||
keyName = "hideExternalPlugins",
|
||||
name = "Hide External Plugins",
|
||||
description = "Hides all OpenOSRS external plugins if checked",
|
||||
titleSection = "hidePluginsTitle",
|
||||
hide = "hidePlugins"
|
||||
)
|
||||
default boolean hideExternalPlugins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 7,
|
||||
keyName = "hidePvmPlugins",
|
||||
name = "Hide PvM Plugins",
|
||||
description = "Hides all OpenOSRS PvM plugins if checked",
|
||||
titleSection = "hidePluginsTitle",
|
||||
hide = "hidePlugins"
|
||||
)
|
||||
default boolean hidePvmPlugins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
keyName = "hideSkillingPlugins",
|
||||
name = "Hide Skilling Plugins",
|
||||
description = "Hides all OpenOSRS skilling plugins if checked",
|
||||
titleSection = "hidePluginsTitle",
|
||||
hide = "hidePlugins"
|
||||
)
|
||||
default boolean hideSkillingPlugins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 9,
|
||||
keyName = "hidePvpPlugins",
|
||||
name = "Hide PvP Plugins",
|
||||
description = "Hides all OpenOSRS Pvp plugins if checked",
|
||||
titleSection = "hidePluginsTitle",
|
||||
hide = "hidePlugins"
|
||||
)
|
||||
default boolean hidePvpPlugins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 10,
|
||||
keyName = "hideUtilityPlugins",
|
||||
name = "Hide Utility Plugins",
|
||||
description = "Hides all OpenOSRS utility plugins if checked",
|
||||
titleSection = "hidePluginsTitle",
|
||||
hide = "hidePlugins"
|
||||
)
|
||||
default boolean hideUtilityPlugins()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigTitleSection(
|
||||
keyName = "pluginsColorTitle",
|
||||
name = "Colors",
|
||||
description = "",
|
||||
position = 11,
|
||||
titleSection = "pluginsTitle"
|
||||
)
|
||||
default Title pluginsColorTitle()
|
||||
{
|
||||
return new Title();
|
||||
}
|
||||
|
||||
@Alpha
|
||||
@ConfigItem(
|
||||
position = 12,
|
||||
keyName = "externalColor",
|
||||
name = "External color",
|
||||
description = "Configure the color of external plugins",
|
||||
titleSection = "pluginsColorTitle"
|
||||
)
|
||||
default Color externalColor()
|
||||
{
|
||||
return new Color(177, 156, 217, 255);
|
||||
}
|
||||
|
||||
@Alpha
|
||||
@ConfigItem(
|
||||
position = 13,
|
||||
keyName = "pvmColor",
|
||||
name = "PVM color",
|
||||
description = "Configure the color of PVM related plugins",
|
||||
titleSection = "pluginsColorTitle"
|
||||
)
|
||||
default Color pvmColor()
|
||||
{
|
||||
return new Color(119, 221, 119, 255);
|
||||
}
|
||||
|
||||
@Alpha
|
||||
@ConfigItem(
|
||||
position = 14,
|
||||
keyName = "pvpColor",
|
||||
name = "PVP color",
|
||||
description = "Configure the color of PVP related plugins",
|
||||
titleSection = "pluginsColorTitle"
|
||||
)
|
||||
default Color pvpColor()
|
||||
{
|
||||
return new Color(255, 105, 97, 255);
|
||||
}
|
||||
|
||||
@Alpha
|
||||
@ConfigItem(
|
||||
position = 15,
|
||||
keyName = "skillingColor",
|
||||
name = "Skilling color",
|
||||
description = "Configure the color of Skilling related plugins",
|
||||
titleSection = "pluginsColorTitle"
|
||||
)
|
||||
default Color skillingColor()
|
||||
{
|
||||
return new Color(252, 252, 100, 255);
|
||||
}
|
||||
|
||||
@Alpha
|
||||
@ConfigItem(
|
||||
position = 16,
|
||||
keyName = "utilityColor",
|
||||
name = "Utility color",
|
||||
description = "Configure the color of Utility related plugins",
|
||||
titleSection = "pluginsColorTitle"
|
||||
)
|
||||
default Color utilityColor()
|
||||
{
|
||||
return new Color(144, 212, 237, 255);
|
||||
}
|
||||
|
||||
@ConfigTitleSection(
|
||||
keyName = "externalPluginsTitle",
|
||||
name = "External",
|
||||
description = "",
|
||||
position = 17,
|
||||
titleSection = "pluginsTitle"
|
||||
)
|
||||
default Title externalPluginsTitle()
|
||||
{
|
||||
return new Title();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "enablePlugins",
|
||||
name = "Enable loading of external plugins",
|
||||
description = "Enable loading of external plugins",
|
||||
position = 2,
|
||||
titleSection = "pluginsTitle"
|
||||
position = 18,
|
||||
titleSection = "externalPluginsTitle"
|
||||
)
|
||||
default boolean enablePlugins()
|
||||
{
|
||||
@@ -56,7 +303,7 @@ public interface OpenOSRSConfig extends Config
|
||||
keyName = "opacityTitle",
|
||||
name = "Opacity",
|
||||
description = "",
|
||||
position = 3
|
||||
position = 19
|
||||
)
|
||||
default Title opacityTitle()
|
||||
{
|
||||
@@ -67,7 +314,7 @@ public interface OpenOSRSConfig extends Config
|
||||
keyName = "enableOpacity",
|
||||
name = "Enable opacity",
|
||||
description = "Enables opacity for the whole window.<br>NOTE: This only stays enabled if your pc supports this!",
|
||||
position = 4,
|
||||
position = 20,
|
||||
titleSection = "opacityTitle"
|
||||
)
|
||||
default boolean enableOpacity()
|
||||
@@ -83,7 +330,7 @@ public interface OpenOSRSConfig extends Config
|
||||
keyName = "opacityPercentage",
|
||||
name = "Opacity percentage",
|
||||
description = "Changes the opacity of the window if opacity is enabled",
|
||||
position = 5,
|
||||
position = 21,
|
||||
titleSection = "opacityTitle"
|
||||
)
|
||||
default int opacityPercentage()
|
||||
@@ -95,7 +342,7 @@ public interface OpenOSRSConfig extends Config
|
||||
keyName = "miscTitle",
|
||||
name = "Miscellaneous",
|
||||
description = "",
|
||||
position = 6
|
||||
position = 22
|
||||
)
|
||||
default Title miscTitle()
|
||||
{
|
||||
@@ -106,7 +353,7 @@ public interface OpenOSRSConfig extends Config
|
||||
keyName = "keyboardPin",
|
||||
name = "Keyboard bank pin",
|
||||
description = "Enables you to type your bank pin",
|
||||
position = 7,
|
||||
position = 23,
|
||||
titleSection = "miscTitle"
|
||||
)
|
||||
default boolean keyboardPin()
|
||||
@@ -118,7 +365,7 @@ public interface OpenOSRSConfig extends Config
|
||||
keyName = "detachHotkey",
|
||||
name = "Detach Cam",
|
||||
description = "Detach Camera hotkey, press this and it will activate detatched camera.",
|
||||
position = 8,
|
||||
position = 24,
|
||||
titleSection = "miscTitle"
|
||||
)
|
||||
default Keybind detachHotkey()
|
||||
|
||||
@@ -6,12 +6,16 @@ import io.reactivex.annotations.NonNull;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.sentry.Sentry;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.events.Event;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import net.runelite.client.config.OpenOSRSConfig;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
@@ -21,6 +25,9 @@ public class EventBus implements EventBusInterface
|
||||
private Map<Class<?>, Relay<Object>> subjectList = new HashMap<>();
|
||||
private Map<Object, CompositeDisposable> subscriptionsMap = new HashMap<>();
|
||||
|
||||
@Inject
|
||||
private OpenOSRSConfig openOSRSConfig;
|
||||
|
||||
@NonNull
|
||||
private <T> Relay<Object> getSubject(Class<T> eventClass)
|
||||
{
|
||||
@@ -52,7 +59,15 @@ public class EventBus implements EventBusInterface
|
||||
Disposable disposable = getSubject(eventClass)
|
||||
.filter(Objects::nonNull) // Filter out null objects, better safe than sorry
|
||||
.cast(eventClass) // Cast it for easier usage
|
||||
.subscribe(action, error -> log.error("Error in eventbus", error));
|
||||
.subscribe(action, error ->
|
||||
{
|
||||
log.error("Exception in eventbus", error);
|
||||
|
||||
if (RuneLiteProperties.getLauncherVersion() != null && openOSRSConfig.shareLogs())
|
||||
{
|
||||
Sentry.capture(error);
|
||||
}
|
||||
});
|
||||
|
||||
getCompositeDisposable(lifecycle).add(disposable);
|
||||
subscriptionList.put(lifecycle, eventClass);
|
||||
@@ -71,7 +86,15 @@ public class EventBus implements EventBusInterface
|
||||
.cast(eventClass) // Cast it for easier usage
|
||||
.take(takeUntil)
|
||||
.doFinally(() -> unregister(lifecycle))
|
||||
.subscribe(action, error -> log.error("Error in eventbus", error));
|
||||
.subscribe(action, error ->
|
||||
{
|
||||
log.error("Exception in eventbus", error);
|
||||
|
||||
if (RuneLiteProperties.getLauncherVersion() != null && openOSRSConfig.shareLogs())
|
||||
{
|
||||
Sentry.capture(error);
|
||||
}
|
||||
});
|
||||
|
||||
getCompositeDisposable(lifecycle).add(disposable);
|
||||
subscriptionList.put(lifecycle, eventClass);
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.events;
|
||||
|
||||
import lombok.Data;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
/**
|
||||
* An event where a configuration entry has been modified.
|
||||
*/
|
||||
@Data
|
||||
public class ConfigChanged implements Event
|
||||
{
|
||||
/**
|
||||
* The parent group for the key.
|
||||
* <p>
|
||||
* Typically set to the name of a plugin to prevent potential collisions
|
||||
* between other key values that may have the same name.
|
||||
*/
|
||||
private String group;
|
||||
/**
|
||||
* The configuration key that has been modified.
|
||||
*/
|
||||
private String key;
|
||||
/**
|
||||
* The previous value of the entry.
|
||||
*/
|
||||
private String oldValue;
|
||||
/**
|
||||
* The new value of the entry, null if the entry has been unset.
|
||||
*/
|
||||
private String newValue;
|
||||
}
|
||||
@@ -326,12 +326,21 @@ public class ItemManager
|
||||
return (int) Math.max(1, getItemDefinition(itemID).getPrice() * HIGH_ALCHEMY_MULTIPLIER);
|
||||
}
|
||||
|
||||
public int getBrokenValue(int itemId)
|
||||
public int getRepairValue(int itemId)
|
||||
{
|
||||
PvPValueBrokenItem b = PvPValueBrokenItem.of(itemId);
|
||||
return getRepairValue(itemId, false);
|
||||
}
|
||||
|
||||
public int getRepairValue(int itemId, boolean fullValue)
|
||||
{
|
||||
final ItemReclaimCost b = ItemReclaimCost.of(itemId);
|
||||
|
||||
if (b != null)
|
||||
{
|
||||
if (fullValue || b.getItemID() == GRANITE_MAUL_24225 || b.getItemID() == GRANITE_MAUL_24227)
|
||||
{
|
||||
return b.getValue();
|
||||
}
|
||||
return (int) (b.getValue() * (75.0f / 100.0f));
|
||||
}
|
||||
|
||||
|
||||
@@ -85,6 +85,16 @@ public enum ItemMapping
|
||||
ITEM_DRAGON_BOOTS(DRAGON_BOOTS, DRAGON_BOOTS_G),
|
||||
ITEM_DRAGON_BOOTS_ORNAMENT_KIT(DRAGON_BOOTS_ORNAMENT_KIT, DRAGON_BOOTS_G),
|
||||
|
||||
// Rune ornament kits
|
||||
ITEM_RUNE_SCIMITAR_GUTHIX(RUNE_SCIMITAR, RUNE_SCIMITAR_23330),
|
||||
ITEM_RUNE_SCIMITAR_ORNAMENT_KIT_GUTHIX(RUNE_SCIMITAR_ORNAMENT_KIT_GUTHIX, RUNE_SCIMITAR_23330),
|
||||
ITEM_RUNE_SCIMITAR_SARADOMIN(RUNE_SCIMITAR, RUNE_SCIMITAR_23332),
|
||||
ITEM_RUNE_SCIMITAR_ORNAMENT_KIT_SARADOMIN(RUNE_SCIMITAR_ORNAMENT_KIT_SARADOMIN, RUNE_SCIMITAR_23332),
|
||||
ITEM_RUNE_SCIMITAR_ZAMORAK(RUNE_SCIMITAR, RUNE_SCIMITAR_23334),
|
||||
ITEM_RUNE_SCIMITAR_ORNAMENT_KIT_ZAMORAK(RUNE_SCIMITAR_ORNAMENT_KIT_ZAMORAK, RUNE_SCIMITAR_23334),
|
||||
ITEM_RUNE_DEFENDER(RUNE_DEFENDER, RUNE_DEFENDER_T),
|
||||
ITEM_RUNE_DEFENDER_ORNAMENT_KIT(RUNE_DEFENDER_ORNAMENT_KIT, RUNE_DEFENDER_T),
|
||||
|
||||
// Godsword ornament kits
|
||||
ITEM_ARMADYL_GODSWORD(ARMADYL_GODSWORD, ARMADYL_GODSWORD_OR),
|
||||
ITEM_ARMADYL_GODSWORD_ORNAMENT_KIT(ARMADYL_GODSWORD_ORNAMENT_KIT, ARMADYL_GODSWORD_OR),
|
||||
@@ -106,6 +116,8 @@ public enum ItemMapping
|
||||
ITEM_FURY_ORNAMENT_KIT(FURY_ORNAMENT_KIT, AMULET_OF_FURY_OR),
|
||||
ITEM_TORMENTED_BRACELET(TORMENTED_BRACELET, TORMENTED_BRACELET_OR),
|
||||
ITEM_TORMENTED_ORNAMENT_KIT(TORMENTED_ORNAMENT_KIT, TORMENTED_BRACELET_OR),
|
||||
ITEM_BERSERKER_NECKLACE(BERSERKER_NECKLACE, BERSERKER_NECKLACE_OR),
|
||||
ITEM_BERSERKER_NECKLACE_ORNAMENT_KIT(BERSERKER_NECKLACE_ORNAMENT_KIT, BERSERKER_NECKLACE_OR),
|
||||
|
||||
// Ensouled heads
|
||||
ITEM_ENSOULED_GOBLIN_HEAD(ENSOULED_GOBLIN_HEAD_13448, ENSOULED_GOBLIN_HEAD),
|
||||
@@ -194,6 +206,8 @@ public enum ItemMapping
|
||||
ITEM_MALEDICTION_WARD(MALEDICTION_WARD, MALEDICTION_WARD_12806),
|
||||
ITEM_STEAM_BATTLESTAFF(STEAM_BATTLESTAFF, STEAM_BATTLESTAFF_12795),
|
||||
ITEM_LAVA_BATTLESTAFF(LAVA_BATTLESTAFF, LAVA_BATTLESTAFF_21198),
|
||||
ITEM_TZHAARKETOM(TZHAARKETOM, TZHAARKETOM_T),
|
||||
ITEM_TZHAARKETOM_ORNAMENT_KIT(TZHAARKETOM_ORNAMENT_KIT, TZHAARKETOM_T),
|
||||
|
||||
// Slayer helm/black mask
|
||||
ITEM_BLACK_MASK(
|
||||
|
||||
@@ -37,15 +37,21 @@ import net.runelite.api.ItemID;
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum PvPValueBrokenItem
|
||||
public enum ItemReclaimCost
|
||||
{
|
||||
// Capes
|
||||
FIRE_CAPE(ItemID.FIRE_CAPE, 50000),
|
||||
FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE, 50000),
|
||||
FIRE_MAX_CAPE(ItemID.FIRE_MAX_CAPE, 99000),
|
||||
INFERNAL_CAPE(ItemID.INFERNAL_CAPE, 50000),
|
||||
INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE, 50000),
|
||||
INFERNAL_MAX_CAPE(ItemID.INFERNAL_MAX_CAPE, 99000),
|
||||
AVAS_ASSEMBLER(ItemID.AVAS_ASSEMBLER, 75000),
|
||||
ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE, 75000),
|
||||
ASSEMBLER_MAX_CAPE(ItemID.ASSEMBLER_MAX_CAPE, 99000),
|
||||
IMBUED_GUTHIX_CAPE(ItemID.IMBUED_GUTHIX_CAPE, 75000),
|
||||
IMBUED_GUTHIX_MAX_CAPE(ItemID.GUTHIX_MAX_CAPE, 99000),
|
||||
IMBUED_SARADOMIN_CAPE(ItemID.IMBUED_SARADOMIN_CAPE, 75000),
|
||||
IMBUED_SARADOMIN_MAX_CAPE(ItemID.SARADOMIN_MAX_CAPE, 99000),
|
||||
IMBUED_ZAMORAK_CAPE(ItemID.IMBUED_ZAMORAK_CAPE, 75000),
|
||||
IMBUED_ZAMORAK_MAX_CAPE(ItemID.ZAMORAK_MAX_CAPE, 99000),
|
||||
|
||||
// Defenders
|
||||
BRONZE_DEFENDER(ItemID.BRONZE_DEFENDER, 1000),
|
||||
@@ -90,15 +96,19 @@ public enum PvPValueBrokenItem
|
||||
GOLD_DECORATIVE_LEGS(ItemID.DECORATIVE_ARMOUR_4510, 5000),
|
||||
GOLD_DECORATIVE_SKIRT(ItemID.DECORATIVE_ARMOUR_11895, 5000),
|
||||
GOLD_DECORATIVE_SHIELD(ItemID.DECORATIVE_SHIELD_4512, 5000),
|
||||
GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508, 5000);
|
||||
GOLD_DECORATIVE_SWORD(ItemID.DECORATIVE_SWORD_4508, 5000),
|
||||
|
||||
private static final ImmutableMap<Integer, PvPValueBrokenItem> idMap;
|
||||
// Granite Maul
|
||||
GRANITE_MAUL(ItemID.GRANITE_MAUL_24225, 375000),
|
||||
GRANITE_MAUL_OR(ItemID.GRANITE_MAUL_24227, 375000);
|
||||
|
||||
private static final ImmutableMap<Integer, ItemReclaimCost> idMap;
|
||||
|
||||
static
|
||||
{
|
||||
ImmutableMap.Builder<Integer, PvPValueBrokenItem> builder = ImmutableMap.builder();
|
||||
ImmutableMap.Builder<Integer, ItemReclaimCost> builder = ImmutableMap.builder();
|
||||
|
||||
for (PvPValueBrokenItem items : values())
|
||||
for (ItemReclaimCost items : values())
|
||||
{
|
||||
builder.put(items.itemID, items);
|
||||
}
|
||||
@@ -110,7 +120,7 @@ public enum PvPValueBrokenItem
|
||||
private final int value;
|
||||
|
||||
@Nullable
|
||||
public static PvPValueBrokenItem of(int itemId)
|
||||
public static ItemReclaimCost of(int itemId)
|
||||
{
|
||||
return idMap.get(itemId);
|
||||
}
|
||||
@@ -1,322 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.game;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.TileItem;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ItemDespawned;
|
||||
import net.runelite.api.events.ItemQuantityChanged;
|
||||
import net.runelite.api.events.ItemSpawned;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.PlayerDespawned;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.NpcLootReceived;
|
||||
import net.runelite.client.events.PlayerLootReceived;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class LootManager
|
||||
{
|
||||
private static final Map<Integer, Integer> NPC_DEATH_ANIMATIONS = ImmutableMap.of(
|
||||
NpcID.CAVE_KRAKEN, AnimationID.CAVE_KRAKEN_DEATH
|
||||
);
|
||||
|
||||
private final EventBus eventBus;
|
||||
private final Client client;
|
||||
private final ListMultimap<Integer, ItemStack> itemSpawns = ArrayListMultimap.create();
|
||||
private final Set<LocalPoint> killPoints = new HashSet<>();
|
||||
private WorldPoint playerLocationLastTick;
|
||||
private WorldPoint krakenPlayerLocation;
|
||||
|
||||
@Inject
|
||||
private LootManager(
|
||||
final EventBus eventBus,
|
||||
final Client client
|
||||
)
|
||||
{
|
||||
this.eventBus = eventBus;
|
||||
this.client = client;
|
||||
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
eventBus.subscribe(NpcDespawned.class, this, this::onNpcDespawned);
|
||||
eventBus.subscribe(PlayerDespawned.class, this, this::onPlayerDespawned);
|
||||
eventBus.subscribe(ItemSpawned.class, this, this::onItemSpawned);
|
||||
eventBus.subscribe(ItemDespawned.class, this, this::onItemDespawned);
|
||||
eventBus.subscribe(ItemQuantityChanged.class, this, this::onItemQuantityChanged);
|
||||
eventBus.subscribe(AnimationChanged.class, this, this::onAnimationChanged);
|
||||
}
|
||||
|
||||
private void onNpcDespawned(NpcDespawned npcDespawned)
|
||||
{
|
||||
final NPC npc = npcDespawned.getNpc();
|
||||
if (!npc.isDead())
|
||||
{
|
||||
int id = npc.getId();
|
||||
switch (id)
|
||||
{
|
||||
case NpcID.GARGOYLE:
|
||||
case NpcID.GARGOYLE_413:
|
||||
case NpcID.GARGOYLE_1543:
|
||||
case NpcID.MARBLE_GARGOYLE:
|
||||
case NpcID.MARBLE_GARGOYLE_7408:
|
||||
case NpcID.DUSK_7888:
|
||||
case NpcID.DUSK_7889:
|
||||
|
||||
case NpcID.ROCKSLUG:
|
||||
case NpcID.ROCKSLUG_422:
|
||||
case NpcID.GIANT_ROCKSLUG:
|
||||
|
||||
case NpcID.SMALL_LIZARD:
|
||||
case NpcID.SMALL_LIZARD_463:
|
||||
case NpcID.DESERT_LIZARD:
|
||||
case NpcID.DESERT_LIZARD_460:
|
||||
case NpcID.DESERT_LIZARD_461:
|
||||
case NpcID.LIZARD:
|
||||
|
||||
case NpcID.ZYGOMITE:
|
||||
case NpcID.ZYGOMITE_1024:
|
||||
case NpcID.ANCIENT_ZYGOMITE:
|
||||
|
||||
// these monsters die with >0 hp, so we just look for coincident
|
||||
// item spawn with despawn
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
processNpcLoot(npc);
|
||||
}
|
||||
|
||||
private void onPlayerDespawned(PlayerDespawned playerDespawned)
|
||||
{
|
||||
final Player player = playerDespawned.getPlayer();
|
||||
// Only care about dead Players
|
||||
if (player.getHealthRatio() != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final LocalPoint location = LocalPoint.fromWorld(client, player.getWorldLocation());
|
||||
if (location == null || killPoints.contains(location))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final int x = location.getSceneX();
|
||||
final int y = location.getSceneY();
|
||||
final int packed = x << 8 | y;
|
||||
final Collection<ItemStack> items = itemSpawns.get(packed);
|
||||
|
||||
if (items.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
killPoints.add(location);
|
||||
eventBus.post(PlayerLootReceived.class, new PlayerLootReceived(player, items));
|
||||
}
|
||||
|
||||
private void onItemSpawned(ItemSpawned itemSpawned)
|
||||
{
|
||||
final TileItem item = itemSpawned.getItem();
|
||||
final Tile tile = itemSpawned.getTile();
|
||||
final LocalPoint location = tile.getLocalLocation();
|
||||
final int packed = location.getSceneX() << 8 | location.getSceneY();
|
||||
itemSpawns.put(packed, new ItemStack(item.getId(), item.getQuantity(), location));
|
||||
log.debug("Item spawn {} ({}) location {}", item.getId(), item.getQuantity(), location);
|
||||
}
|
||||
|
||||
private void onItemDespawned(ItemDespawned itemDespawned)
|
||||
{
|
||||
final TileItem item = itemDespawned.getItem();
|
||||
final LocalPoint location = itemDespawned.getTile().getLocalLocation();
|
||||
log.debug("Item despawn {} ({}) location {}", item.getId(), item.getQuantity(), location);
|
||||
}
|
||||
|
||||
private void onItemQuantityChanged(ItemQuantityChanged itemQuantityChanged)
|
||||
{
|
||||
final TileItem item = itemQuantityChanged.getItem();
|
||||
final Tile tile = itemQuantityChanged.getTile();
|
||||
final LocalPoint location = tile.getLocalLocation();
|
||||
final int packed = location.getSceneX() << 8 | location.getSceneY();
|
||||
final int diff = itemQuantityChanged.getNewQuantity() - itemQuantityChanged.getOldQuantity();
|
||||
|
||||
if (diff <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
itemSpawns.put(packed, new ItemStack(item.getId(), diff, location));
|
||||
}
|
||||
|
||||
private void onAnimationChanged(AnimationChanged e)
|
||||
{
|
||||
if (!(e.getActor() instanceof NPC))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final NPC npc = (NPC) e.getActor();
|
||||
int id = npc.getId();
|
||||
|
||||
// We only care about certain NPCs
|
||||
final Integer deathAnim = NPC_DEATH_ANIMATIONS.get(id);
|
||||
|
||||
// Current animation is death animation?
|
||||
if (deathAnim != null && deathAnim == npc.getAnimation())
|
||||
{
|
||||
if (id == NpcID.CAVE_KRAKEN)
|
||||
{
|
||||
// Big Kraken drops loot wherever player is standing when animation starts.
|
||||
krakenPlayerLocation = client.getLocalPlayer().getWorldLocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
// These NPCs drop loot on death animation, which is right now.
|
||||
processNpcLoot(npc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onGameTick(GameTick gameTick)
|
||||
{
|
||||
playerLocationLastTick = client.getLocalPlayer().getWorldLocation();
|
||||
itemSpawns.clear();
|
||||
killPoints.clear();
|
||||
}
|
||||
|
||||
private void processNpcLoot(NPC npc)
|
||||
{
|
||||
final LocalPoint location = LocalPoint.fromWorld(client, getDropLocation(npc, npc.getWorldLocation()));
|
||||
if (location == null || killPoints.contains(location))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final int x = location.getSceneX();
|
||||
final int y = location.getSceneY();
|
||||
final int size = npc.getDefinition().getSize();
|
||||
|
||||
// Some NPCs drop items onto multiple tiles
|
||||
final List<ItemStack> allItems = new ArrayList<>();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
for (int j = 0; j < size; ++j)
|
||||
{
|
||||
final int packed = (x + i) << 8 | (y + j);
|
||||
final Collection<ItemStack> items = itemSpawns.get(packed);
|
||||
allItems.addAll(items);
|
||||
}
|
||||
}
|
||||
|
||||
if (allItems.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
killPoints.add(location);
|
||||
eventBus.post(NpcLootReceived.class, new NpcLootReceived(npc, allItems));
|
||||
}
|
||||
|
||||
private WorldPoint getDropLocation(NPC npc, WorldPoint worldLocation)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case NpcID.KRAKEN:
|
||||
case NpcID.KRAKEN_6640:
|
||||
case NpcID.KRAKEN_6656:
|
||||
worldLocation = playerLocationLastTick;
|
||||
break;
|
||||
case NpcID.CAVE_KRAKEN:
|
||||
worldLocation = krakenPlayerLocation;
|
||||
break;
|
||||
case NpcID.ZULRAH: // Green
|
||||
case NpcID.ZULRAH_2043: // Red
|
||||
case NpcID.ZULRAH_2044: // Blue
|
||||
for (Map.Entry<Integer, ItemStack> entry : itemSpawns.entries())
|
||||
{
|
||||
if (entry.getValue().getId() == ItemID.ZULRAHS_SCALES)
|
||||
{
|
||||
int packed = entry.getKey();
|
||||
int unpackedX = packed >> 8;
|
||||
int unpackedY = packed & 0xFF;
|
||||
worldLocation = WorldPoint.fromScene(client, unpackedX, unpackedY, worldLocation.getPlane());
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NpcID.VORKATH:
|
||||
case NpcID.VORKATH_8058:
|
||||
case NpcID.VORKATH_8059:
|
||||
case NpcID.VORKATH_8060:
|
||||
case NpcID.VORKATH_8061:
|
||||
int x = worldLocation.getX() + 3;
|
||||
int y = worldLocation.getY() + 3;
|
||||
if (playerLocationLastTick.getX() < x)
|
||||
{
|
||||
x -= 4;
|
||||
}
|
||||
else if (playerLocationLastTick.getX() > x)
|
||||
{
|
||||
x += 4;
|
||||
}
|
||||
if (playerLocationLastTick.getY() < y)
|
||||
{
|
||||
y -= 4;
|
||||
}
|
||||
else if (playerLocationLastTick.getY() > y)
|
||||
{
|
||||
y += 4;
|
||||
}
|
||||
worldLocation = new WorldPoint(x, y, worldLocation.getPlane());
|
||||
break;
|
||||
}
|
||||
|
||||
return worldLocation;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.game;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.AnimationID;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.TileItem;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ItemDespawned;
|
||||
import net.runelite.api.events.ItemQuantityChanged;
|
||||
import net.runelite.api.events.ItemSpawned;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.PlayerDespawned;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.NpcLootReceived;
|
||||
import net.runelite.client.events.PlayerLootReceived;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
public class LootManager
|
||||
{
|
||||
private static final Map<Integer, Integer> NPC_DEATH_ANIMATIONS = ImmutableMap.<Integer, Integer>builder()
|
||||
.put(NpcID.CAVE_KRAKEN, AnimationID.CAVE_KRAKEN_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_BAT, AnimationID.CRYSTALLINE_BAT_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_RAT, AnimationID.CRYSTALLINE_RAT_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_SPIDER, AnimationID.CRYSTALLINE_SPIDER_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_WOLF, AnimationID.CRYSTALLINE_WOLF_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_UNICORN, AnimationID.CRYSTALLINE_UNICORN_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_SCORPION, AnimationID.CORRUPTED_SCORPION_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_DRAGON, AnimationID.CRYSTALLINE_DRAGON_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_DARK_BEAST, AnimationID.CRYSTALLINE_DARK_BEAST_DEATH)
|
||||
.put(NpcID.CRYSTALLINE_BEAR, AnimationID.CRYSTALLINE_BEAR_DEATH)
|
||||
.put(NpcID.CORRUPTED_BAT, AnimationID.CRYSTALLINE_BAT_DEATH)
|
||||
.put(NpcID.CORRUPTED_RAT, AnimationID.CRYSTALLINE_RAT_DEATH)
|
||||
.put(NpcID.CORRUPTED_SPIDER, AnimationID.CRYSTALLINE_SPIDER_DEATH)
|
||||
.put(NpcID.CORRUPTED_WOLF, AnimationID.CRYSTALLINE_WOLF_DEATH)
|
||||
.put(NpcID.CORRUPTED_UNICORN, AnimationID.CRYSTALLINE_UNICORN_DEATH)
|
||||
.put(NpcID.CORRUPTED_SCORPION, AnimationID.CORRUPTED_SCORPION_DEATH)
|
||||
.put(NpcID.CORRUPTED_DRAGON, AnimationID.CRYSTALLINE_DRAGON_DEATH)
|
||||
.put(NpcID.CORRUPTED_DARK_BEAST, AnimationID.CRYSTALLINE_DARK_BEAST_DEATH)
|
||||
.put(NpcID.CORRUPTED_BEAR, AnimationID.CRYSTALLINE_BEAR_DEATH)
|
||||
.build();
|
||||
|
||||
private final EventBus eventBus;
|
||||
private final Client client;
|
||||
private final ListMultimap<Integer, ItemStack> itemSpawns = ArrayListMultimap.create();
|
||||
private final Set<LocalPoint> killPoints = new HashSet<>();
|
||||
private WorldPoint playerLocationLastTick;
|
||||
private WorldPoint krakenPlayerLocation;
|
||||
|
||||
@Inject
|
||||
private LootManager(
|
||||
final EventBus eventBus,
|
||||
final Client client
|
||||
)
|
||||
{
|
||||
this.eventBus = eventBus;
|
||||
this.client = client;
|
||||
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
eventBus.subscribe(NpcDespawned.class, this, this::onNpcDespawned);
|
||||
eventBus.subscribe(PlayerDespawned.class, this, this::onPlayerDespawned);
|
||||
eventBus.subscribe(ItemSpawned.class, this, this::onItemSpawned);
|
||||
eventBus.subscribe(ItemDespawned.class, this, this::onItemDespawned);
|
||||
eventBus.subscribe(ItemQuantityChanged.class, this, this::onItemQuantityChanged);
|
||||
eventBus.subscribe(AnimationChanged.class, this, this::onAnimationChanged);
|
||||
}
|
||||
|
||||
private void onNpcDespawned(NpcDespawned npcDespawned)
|
||||
{
|
||||
final NPC npc = npcDespawned.getNpc();
|
||||
if (!npc.isDead())
|
||||
{
|
||||
int id = npc.getId();
|
||||
switch (id)
|
||||
{
|
||||
case NpcID.GARGOYLE:
|
||||
case NpcID.GARGOYLE_413:
|
||||
case NpcID.GARGOYLE_1543:
|
||||
case NpcID.MARBLE_GARGOYLE:
|
||||
case NpcID.MARBLE_GARGOYLE_7408:
|
||||
case NpcID.DUSK_7888:
|
||||
case NpcID.DUSK_7889:
|
||||
|
||||
case NpcID.ROCKSLUG:
|
||||
case NpcID.ROCKSLUG_422:
|
||||
case NpcID.GIANT_ROCKSLUG:
|
||||
|
||||
case NpcID.SMALL_LIZARD:
|
||||
case NpcID.SMALL_LIZARD_463:
|
||||
case NpcID.DESERT_LIZARD:
|
||||
case NpcID.DESERT_LIZARD_460:
|
||||
case NpcID.DESERT_LIZARD_461:
|
||||
case NpcID.LIZARD:
|
||||
|
||||
case NpcID.ZYGOMITE:
|
||||
case NpcID.ZYGOMITE_1024:
|
||||
case NpcID.ANCIENT_ZYGOMITE:
|
||||
|
||||
// these monsters die with >0 hp, so we just look for coincident
|
||||
// item spawn with despawn
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
processNpcLoot(npc);
|
||||
}
|
||||
|
||||
private void onPlayerDespawned(PlayerDespawned playerDespawned)
|
||||
{
|
||||
final Player player = playerDespawned.getPlayer();
|
||||
// Only care about dead Players
|
||||
if (player.getHealthRatio() != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final LocalPoint location = LocalPoint.fromWorld(client, player.getWorldLocation());
|
||||
if (location == null || killPoints.contains(location))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final int x = location.getSceneX();
|
||||
final int y = location.getSceneY();
|
||||
final int packed = x << 8 | y;
|
||||
final Collection<ItemStack> items = itemSpawns.get(packed);
|
||||
|
||||
if (items.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
killPoints.add(location);
|
||||
eventBus.post(PlayerLootReceived.class, new PlayerLootReceived(player, items));
|
||||
}
|
||||
|
||||
private void onItemSpawned(ItemSpawned itemSpawned)
|
||||
{
|
||||
final TileItem item = itemSpawned.getItem();
|
||||
final Tile tile = itemSpawned.getTile();
|
||||
final LocalPoint location = tile.getLocalLocation();
|
||||
final int packed = location.getSceneX() << 8 | location.getSceneY();
|
||||
itemSpawns.put(packed, new ItemStack(item.getId(), item.getQuantity(), location));
|
||||
log.debug("Item spawn {} ({}) location {}", item.getId(), item.getQuantity(), location);
|
||||
}
|
||||
|
||||
private void onItemDespawned(ItemDespawned itemDespawned)
|
||||
{
|
||||
final TileItem item = itemDespawned.getItem();
|
||||
final LocalPoint location = itemDespawned.getTile().getLocalLocation();
|
||||
log.debug("Item despawn {} ({}) location {}", item.getId(), item.getQuantity(), location);
|
||||
}
|
||||
|
||||
private void onItemQuantityChanged(ItemQuantityChanged itemQuantityChanged)
|
||||
{
|
||||
final TileItem item = itemQuantityChanged.getItem();
|
||||
final Tile tile = itemQuantityChanged.getTile();
|
||||
final LocalPoint location = tile.getLocalLocation();
|
||||
final int packed = location.getSceneX() << 8 | location.getSceneY();
|
||||
final int diff = itemQuantityChanged.getNewQuantity() - itemQuantityChanged.getOldQuantity();
|
||||
|
||||
if (diff <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
itemSpawns.put(packed, new ItemStack(item.getId(), diff, location));
|
||||
}
|
||||
|
||||
private void onAnimationChanged(AnimationChanged e)
|
||||
{
|
||||
if (!(e.getActor() instanceof NPC))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final NPC npc = (NPC) e.getActor();
|
||||
int id = npc.getId();
|
||||
|
||||
// We only care about certain NPCs
|
||||
final Integer deathAnim = NPC_DEATH_ANIMATIONS.get(id);
|
||||
|
||||
// Current animation is death animation?
|
||||
if (deathAnim != null && deathAnim == npc.getAnimation())
|
||||
{
|
||||
if (id == NpcID.CAVE_KRAKEN)
|
||||
{
|
||||
// Big Kraken drops loot wherever player is standing when animation starts.
|
||||
krakenPlayerLocation = client.getLocalPlayer().getWorldLocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
// These NPCs drop loot on death animation, which is right now.
|
||||
processNpcLoot(npc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onGameTick(GameTick gameTick)
|
||||
{
|
||||
playerLocationLastTick = client.getLocalPlayer().getWorldLocation();
|
||||
itemSpawns.clear();
|
||||
killPoints.clear();
|
||||
}
|
||||
|
||||
private void processNpcLoot(NPC npc)
|
||||
{
|
||||
final LocalPoint location = LocalPoint.fromWorld(client, getDropLocation(npc, npc.getWorldLocation()));
|
||||
if (location == null || killPoints.contains(location))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final int x = location.getSceneX();
|
||||
final int y = location.getSceneY();
|
||||
final int size = npc.getDefinition().getSize();
|
||||
|
||||
// Some NPCs drop items onto multiple tiles
|
||||
final List<ItemStack> allItems = new ArrayList<>();
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
for (int j = 0; j < size; ++j)
|
||||
{
|
||||
final int packed = (x + i) << 8 | (y + j);
|
||||
final Collection<ItemStack> items = itemSpawns.get(packed);
|
||||
allItems.addAll(items);
|
||||
}
|
||||
}
|
||||
|
||||
if (allItems.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
killPoints.add(location);
|
||||
eventBus.post(NpcLootReceived.class, new NpcLootReceived(npc, allItems));
|
||||
}
|
||||
|
||||
private WorldPoint getDropLocation(NPC npc, WorldPoint worldLocation)
|
||||
{
|
||||
switch (npc.getId())
|
||||
{
|
||||
case NpcID.KRAKEN:
|
||||
case NpcID.KRAKEN_6640:
|
||||
case NpcID.KRAKEN_6656:
|
||||
worldLocation = playerLocationLastTick;
|
||||
break;
|
||||
case NpcID.CAVE_KRAKEN:
|
||||
worldLocation = krakenPlayerLocation;
|
||||
break;
|
||||
case NpcID.ZULRAH: // Green
|
||||
case NpcID.ZULRAH_2043: // Red
|
||||
case NpcID.ZULRAH_2044: // Blue
|
||||
for (Map.Entry<Integer, ItemStack> entry : itemSpawns.entries())
|
||||
{
|
||||
if (entry.getValue().getId() == ItemID.ZULRAHS_SCALES)
|
||||
{
|
||||
int packed = entry.getKey();
|
||||
int unpackedX = packed >> 8;
|
||||
int unpackedY = packed & 0xFF;
|
||||
worldLocation = WorldPoint.fromScene(client, unpackedX, unpackedY, worldLocation.getPlane());
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NpcID.VORKATH:
|
||||
case NpcID.VORKATH_8058:
|
||||
case NpcID.VORKATH_8059:
|
||||
case NpcID.VORKATH_8060:
|
||||
case NpcID.VORKATH_8061:
|
||||
int x = worldLocation.getX() + 3;
|
||||
int y = worldLocation.getY() + 3;
|
||||
if (playerLocationLastTick.getX() < x)
|
||||
{
|
||||
x -= 4;
|
||||
}
|
||||
else if (playerLocationLastTick.getX() > x)
|
||||
{
|
||||
x += 4;
|
||||
}
|
||||
if (playerLocationLastTick.getY() < y)
|
||||
{
|
||||
y -= 4;
|
||||
}
|
||||
else if (playerLocationLastTick.getY() > y)
|
||||
{
|
||||
y += 4;
|
||||
}
|
||||
worldLocation = new WorldPoint(x, y, worldLocation.getPlane());
|
||||
break;
|
||||
}
|
||||
|
||||
return worldLocation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,18 @@ public enum UntradeableItemMapping
|
||||
CRYSTAL_LEGS(ItemID.CRYSTAL_LEGS, 2, ItemID.CRYSTAL_ARMOUR_SEED),
|
||||
CRYSTAL_LEGS_INACTIVE(ItemID.CRYSTAL_LEGS_INACTIVE, 2, ItemID.CRYSTAL_ARMOUR_SEED),
|
||||
CRYSTAL_BODY(ItemID.CRYSTAL_BODY, 3, ItemID.CRYSTAL_ARMOUR_SEED),
|
||||
CRYSTAL_BODY_INACTIVE(ItemID.CRYSTAL_BODY_INACTIVE, 3, ItemID.CRYSTAL_ARMOUR_SEED);
|
||||
CRYSTAL_BODY_INACTIVE(ItemID.CRYSTAL_BODY_INACTIVE, 3, ItemID.CRYSTAL_ARMOUR_SEED),
|
||||
|
||||
TATTERED_MOON_PAGE(ItemID.TATTERED_MOON_PAGE, 1000, ItemID.COINS_995),
|
||||
TATTERED_SUN_PAGE(ItemID.TATTERED_SUN_PAGE, 1000, ItemID.COINS_995),
|
||||
TATTERED_TEMPLE_PAGE(ItemID.TATTERED_TEMPLE_PAGE, 1000, ItemID.COINS_995),
|
||||
|
||||
LONG_BONE(ItemID.LONG_BONE, 1000, ItemID.COINS_995),
|
||||
CURVED_BONE(ItemID.CURVED_BONE, 2000, ItemID.COINS_995),
|
||||
PERFECT_SHELL(ItemID.PERFECT_SHELL, 600, ItemID.COINS_995),
|
||||
PERFECT_SNAIL_SHELL(ItemID.PERFECT_SNAIL_SHELL, 600, ItemID.COINS_995),
|
||||
SNAIL_SHELL(ItemID.SNAIL_SHELL, 600, ItemID.COINS_995),
|
||||
TORTOISE_SHELL(ItemID.TORTOISE_SHELL, 250, ItemID.COINS_995);
|
||||
|
||||
private static final ImmutableMap<Integer, UntradeableItemMapping> UNTRADEABLE_RECLAIM_MAP;
|
||||
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
|
||||
package net.runelite.client.game;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.coords.WorldArea;
|
||||
@@ -193,6 +192,20 @@ public enum WorldLocation
|
||||
private final WorldArea worldArea;
|
||||
@Getter
|
||||
private final Location location;
|
||||
@Getter
|
||||
private static final Map<WorldArea, String> LOCATION_MAP;
|
||||
|
||||
static
|
||||
{
|
||||
ImmutableMap.Builder<WorldArea, String> builder = ImmutableMap.builder();
|
||||
|
||||
for (WorldLocation value : values())
|
||||
{
|
||||
builder.put(value.getWorldArea(), value.getName());
|
||||
}
|
||||
|
||||
LOCATION_MAP = builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a location used to get the name of a location by a WorldPoint
|
||||
@@ -210,6 +223,7 @@ public enum WorldLocation
|
||||
|
||||
/**
|
||||
* Returns all locations that aren't in the wild
|
||||
*
|
||||
* @return - A Collection of non-wilderness WorldLocations
|
||||
*/
|
||||
public static Collection<WorldLocation> getNonWildernessLocations()
|
||||
@@ -220,6 +234,7 @@ public enum WorldLocation
|
||||
|
||||
/**
|
||||
* Returns only the WorldLocations that are in the wilderness
|
||||
*
|
||||
* @return - A Collection of WorldLocations in the wilderness
|
||||
*/
|
||||
public static Collection<WorldLocation> getWildernessLocations()
|
||||
@@ -228,63 +243,70 @@ public enum WorldLocation
|
||||
PvPUtil.getWildernessLevelFrom(loc.worldArea.toWorldPoint()) > 0).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static Map<WorldArea, String> getLocationMap()
|
||||
{
|
||||
Map<WorldArea, String> hashMap = new HashMap<>();
|
||||
Arrays.stream(values()).forEach(worldLocation ->
|
||||
hashMap.put(worldLocation.getWorldArea(), worldLocation.getName()));
|
||||
return hashMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the WorldLocation that a WorldPoint is in, or the closest WorldLocation to the point
|
||||
*
|
||||
* @param worldPoint - the WorldPoint to find the WorldLocation of
|
||||
* @return - Containing location or closest location if it isn't in any
|
||||
*/
|
||||
public static String location(WorldPoint worldPoint)
|
||||
{
|
||||
final Map<WorldArea, String> locationMap = getLocationMap();
|
||||
int dist = 10000;
|
||||
String s = "";
|
||||
WorldArea closestArea = null;
|
||||
for (Map.Entry<WorldArea, String> entry : locationMap.entrySet())
|
||||
|
||||
for (Map.Entry<WorldArea, String> entry : LOCATION_MAP.entrySet())
|
||||
{
|
||||
WorldArea worldArea = entry.getKey();
|
||||
final WorldArea worldArea = entry.getKey();
|
||||
|
||||
if (worldArea.toWorldPointList().contains(worldPoint))
|
||||
{
|
||||
s = entry.getValue();
|
||||
return s;
|
||||
}
|
||||
int distTo = worldArea.distanceTo(worldPoint);
|
||||
|
||||
final int distTo = worldArea.distanceTo(worldPoint);
|
||||
|
||||
if (distTo < dist)
|
||||
{
|
||||
dist = distTo;
|
||||
closestArea = worldArea;
|
||||
}
|
||||
}
|
||||
if (worldPoint.getY() > (Objects.requireNonNull(closestArea).toWorldPoint().getY() + closestArea.getHeight()))
|
||||
|
||||
if (closestArea == null)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
if (worldPoint.getY() > closestArea.toWorldPoint().getY() + closestArea.getHeight())
|
||||
{
|
||||
s = s + "N";
|
||||
}
|
||||
|
||||
if (worldPoint.getY() < closestArea.toWorldPoint().getY())
|
||||
{
|
||||
s = s + "S";
|
||||
}
|
||||
|
||||
if (worldPoint.getX() < closestArea.toWorldPoint().getX())
|
||||
{
|
||||
s = s + "W";
|
||||
}
|
||||
|
||||
if (worldPoint.getX() > (closestArea.toWorldPoint().getX() + closestArea.getWidth()))
|
||||
{
|
||||
s = s + "E";
|
||||
}
|
||||
|
||||
s = s + " of ";
|
||||
s = s + locationMap.get(closestArea);
|
||||
s = s + LOCATION_MAP.get(closestArea);
|
||||
|
||||
if (s.startsWith(" of "))
|
||||
{
|
||||
s = s.substring(3);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
import lombok.Data;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.events.Event;
|
||||
|
||||
@Data
|
||||
public class XpDropEvent implements Event
|
||||
{
|
||||
private Skill skill;
|
||||
private int exp;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package net.runelite.client.game;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
|
||||
@Singleton
|
||||
public class XpDropManager
|
||||
{
|
||||
|
||||
private final Map<Skill, Integer> previousSkillExpTable = new EnumMap<>(Skill.class);
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int damage = 0;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private int tickShow = 0;
|
||||
private int previousExpGained;
|
||||
private Client client;
|
||||
private EventBus eventBus;
|
||||
|
||||
@Inject
|
||||
private XpDropManager(
|
||||
final EventBus eventBus,
|
||||
final Client client
|
||||
)
|
||||
{
|
||||
this.client = client;
|
||||
this.eventBus = eventBus;
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventBus.subscribe(StatChanged.class, this, this::onStatChanged);
|
||||
}
|
||||
|
||||
private void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
damage = 0;
|
||||
tickShow = 0;
|
||||
}
|
||||
|
||||
private void onStatChanged(StatChanged event)
|
||||
{
|
||||
final Skill skill = event.getSkill();
|
||||
final int xp = client.getSkillExperience(skill);
|
||||
Integer previous = previousSkillExpTable.put(skill, xp);
|
||||
if (previous != null)
|
||||
{
|
||||
previousExpGained = xp - previous;
|
||||
XpDropEvent xpDropEvent = new XpDropEvent();
|
||||
xpDropEvent.setExp(previousExpGained);
|
||||
xpDropEvent.setSkill(skill);
|
||||
eventBus.post(XpDropEvent.class, xpDropEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ import net.runelite.api.MenuOpcode;
|
||||
import static net.runelite.api.MenuOpcode.MENU_ACTION_DEPRIORITIZE_OFFSET;
|
||||
import net.runelite.api.NPCDefinition;
|
||||
import net.runelite.api.events.BeforeRender;
|
||||
import net.runelite.api.events.ClientTick;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOpened;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
@@ -89,7 +90,8 @@ public class MenuManager
|
||||
private final Map<AbstractComparableEntry, AbstractComparableEntry> swaps = new HashMap<>();
|
||||
|
||||
private MenuEntry leftClickEntry = null;
|
||||
private MenuEntry firstEntry = null;
|
||||
|
||||
private int playerAttackIdx = -1;
|
||||
|
||||
@Inject
|
||||
private MenuManager(Client client, EventBus eventBus)
|
||||
@@ -100,11 +102,15 @@ public class MenuManager
|
||||
|
||||
eventBus.subscribe(MenuOpened.class, this, this::onMenuOpened);
|
||||
eventBus.subscribe(MenuEntryAdded.class, this, this::onMenuEntryAdded);
|
||||
eventBus.subscribe(BeforeRender.class, this, this::onBeforeRender);
|
||||
eventBus.subscribe(PlayerMenuOptionsChanged.class, this, this::onPlayerMenuOptionsChanged);
|
||||
eventBus.subscribe(NpcActionChanged.class, this, this::onNpcActionChanged);
|
||||
eventBus.subscribe(WidgetPressed.class, this, this::onWidgetPressed);
|
||||
eventBus.subscribe(MenuOptionClicked.class, this, this::onMenuOptionClicked);
|
||||
|
||||
// Make sure last tick's entry gets cleared
|
||||
eventBus.subscribe(ClientTick.class, this, tick -> leftClickEntry = null);
|
||||
// Rebuild left click menu for top left entry
|
||||
eventBus.subscribe(BeforeRender.class, this, br -> rebuildLeftClickMenu());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,7 +157,7 @@ public class MenuManager
|
||||
// Need to reorder the list to normal, then rebuild with swaps
|
||||
MenuEntry[] oldEntries = event.getMenuEntries();
|
||||
|
||||
firstEntry = null;
|
||||
leftClickEntry = null;
|
||||
|
||||
List<MenuEntry> newEntries = Lists.newArrayList(oldEntries);
|
||||
|
||||
@@ -245,6 +251,11 @@ public class MenuManager
|
||||
|
||||
private void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
if (client.isSpellSelected())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (AbstractComparableEntry e : hiddenEntries)
|
||||
{
|
||||
if (e.matches(event))
|
||||
@@ -274,25 +285,20 @@ public class MenuManager
|
||||
}
|
||||
}
|
||||
|
||||
private void onBeforeRender(BeforeRender event)
|
||||
{
|
||||
rebuildLeftClickMenu();
|
||||
}
|
||||
|
||||
private MenuEntry rebuildLeftClickMenu()
|
||||
private void rebuildLeftClickMenu()
|
||||
{
|
||||
leftClickEntry = null;
|
||||
if (client.isMenuOpen())
|
||||
{
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
int menuOptionCount = client.getMenuOptionCount();
|
||||
if (menuOptionCount <= 2)
|
||||
{
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
firstEntry = null;
|
||||
MenuEntry[] entries = new MenuEntry[menuOptionCount + priorityEntries.size()];
|
||||
System.arraycopy(client.getMenuEntries(), 0, entries, 0, menuOptionCount);
|
||||
|
||||
@@ -301,21 +307,19 @@ public class MenuManager
|
||||
indexPriorityEntries(entries, menuOptionCount);
|
||||
}
|
||||
|
||||
if (firstEntry == null && !swaps.isEmpty())
|
||||
if (leftClickEntry == null && !swaps.isEmpty())
|
||||
{
|
||||
indexSwapEntries(entries, menuOptionCount);
|
||||
}
|
||||
|
||||
|
||||
if (firstEntry == null)
|
||||
if (leftClickEntry == null)
|
||||
{
|
||||
// stop being null smh
|
||||
firstEntry = entries[menuOptionCount - 1];
|
||||
leftClickEntry = entries[menuOptionCount - 1];
|
||||
}
|
||||
|
||||
client.setMenuEntries(entries);
|
||||
|
||||
return firstEntry;
|
||||
}
|
||||
|
||||
public void addPlayerMenuItem(String menuText)
|
||||
@@ -419,16 +423,18 @@ public class MenuManager
|
||||
|
||||
private void onWidgetPressed(WidgetPressed event)
|
||||
{
|
||||
leftClickEntry = rebuildLeftClickMenu();
|
||||
rebuildLeftClickMenu();
|
||||
client.setTempMenuEntry(leftClickEntry);
|
||||
}
|
||||
|
||||
private void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
if (!client.isMenuOpen() && event.isAuthentic())
|
||||
// option and target will be the same if this one came from "tempMenuAction"
|
||||
if (!client.isMenuOpen() && !event.getOption().equals(event.getTarget()) && event.isAuthentic())
|
||||
{
|
||||
if (event.getMouseButton() != 0)
|
||||
if (!event.equals(leftClickEntry))
|
||||
{
|
||||
leftClickEntry = rebuildLeftClickMenu();
|
||||
rebuildLeftClickMenu();
|
||||
}
|
||||
|
||||
if (leftClickEntry != null)
|
||||
@@ -500,6 +506,29 @@ public class MenuManager
|
||||
return index;
|
||||
}
|
||||
|
||||
public int getPlayerAttackOpcode()
|
||||
{
|
||||
final String[] playerMenuOptions = client.getPlayerOptions();
|
||||
|
||||
if (playerAttackIdx != -1 && playerMenuOptions[playerAttackIdx].equals("Attack"))
|
||||
{
|
||||
return client.getPlayerMenuTypes()[playerAttackIdx];
|
||||
}
|
||||
|
||||
playerAttackIdx = -1;
|
||||
|
||||
for (int i = IDX_LOWER; i < IDX_UPPER; i++)
|
||||
{
|
||||
if ("Attack".equals(playerMenuOptions[i]))
|
||||
{
|
||||
playerAttackIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return playerAttackIdx >= 0 ? client.getPlayerMenuTypes()[playerAttackIdx] : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds to the set of menu entries which when present, will remove all entries except for this one
|
||||
*/
|
||||
@@ -522,7 +551,7 @@ public class MenuManager
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, target);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
priorityEntries.remove(entry);
|
||||
}
|
||||
|
||||
|
||||
@@ -562,7 +591,7 @@ public class MenuManager
|
||||
|
||||
public void removePriorityEntry(AbstractComparableEntry entry)
|
||||
{
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
priorityEntries.remove(entry);
|
||||
}
|
||||
|
||||
public void removePriorityEntry(String option)
|
||||
@@ -571,7 +600,7 @@ public class MenuManager
|
||||
|
||||
AbstractComparableEntry entry = newBaseComparableEntry(option, "", false);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
priorityEntries.remove(entry);
|
||||
}
|
||||
|
||||
public void removePriorityEntry(String option, boolean strictOption)
|
||||
@@ -581,7 +610,17 @@ public class MenuManager
|
||||
AbstractComparableEntry entry =
|
||||
newBaseComparableEntry(option, "", -1, -1, false, strictOption);
|
||||
|
||||
priorityEntries.removeIf(entry::equals);
|
||||
priorityEntries.remove(entry);
|
||||
}
|
||||
|
||||
public void addPriorityEntries(Collection<AbstractComparableEntry> entries)
|
||||
{
|
||||
priorityEntries.addAll(entries);
|
||||
}
|
||||
|
||||
public void removePriorityEntries(Collection<AbstractComparableEntry> entries)
|
||||
{
|
||||
priorityEntries.removeAll(entries);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -713,9 +752,9 @@ public class MenuManager
|
||||
for (String target : fromTarget)
|
||||
{
|
||||
final String s = Text.standardize(target);
|
||||
swaps.keySet().removeIf(e -> e.getTarget().equals(s));
|
||||
priorityEntries.removeIf(e -> e.getTarget().equals(s));
|
||||
hiddenEntries.removeIf(e -> e.getTarget().equals(s));
|
||||
swaps.keySet().removeIf(e -> e.getTarget() != null && e.getTarget().equals(s));
|
||||
priorityEntries.removeIf(e -> e.getTarget() != null && e.getTarget().equals(s));
|
||||
hiddenEntries.removeIf(e -> e.getTarget() != null && e.getTarget().equals(s));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -839,7 +878,7 @@ public class MenuManager
|
||||
entries[menuOptionCount + i] = prios[i].entry;
|
||||
}
|
||||
|
||||
firstEntry = entries[menuOptionCount + i - 1];
|
||||
leftClickEntry = entries[menuOptionCount + i - 1];
|
||||
|
||||
}
|
||||
|
||||
@@ -882,7 +921,7 @@ public class MenuManager
|
||||
|
||||
entries[i] = first;
|
||||
entries[menuOptionCount - 1] = entry;
|
||||
firstEntry = entry;
|
||||
leftClickEntry = entry;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,5 @@ public enum PluginType
|
||||
UTILITY,
|
||||
GENERAL_USE,
|
||||
EXTERNAL,
|
||||
PLUGIN_ORGANIZER,
|
||||
IMPORTANT
|
||||
}
|
||||
|
||||
@@ -120,9 +120,6 @@ public class KaramjaDiaryRequirement extends GenericDiaryRequirement
|
||||
new CombatLevelRequirement(100),
|
||||
new SkillRequirement(Skill.SLAYER, 50),
|
||||
new QuestRequirement(Quest.SHILO_VILLAGE));
|
||||
add("Kill a metal dragon in Brimhaven Dungeon.",
|
||||
new SkillRequirement(Skill.AGILITY, 12),
|
||||
new SkillRequirement(Skill.WOODCUTTING, 34));
|
||||
|
||||
// ELITE
|
||||
add("Craft 56 Nature runes at once.",
|
||||
|
||||
@@ -78,7 +78,7 @@ public class WesternDiaryRequirement extends GenericDiaryRequirement
|
||||
add("Make a Chocolate Bomb at the Grand Tree.",
|
||||
new SkillRequirement(Skill.COOKING, 42));
|
||||
add("Complete a delivery for the Gnome Restaurant.",
|
||||
new SkillRequirement(Skill.COOKING, 42));
|
||||
new SkillRequirement(Skill.COOKING, 29));
|
||||
add("Turn your small crystal seed into a Crystal saw.",
|
||||
new QuestRequirement(Quest.THE_EYES_OF_GLOUPHRIE));
|
||||
add("Mine some Gold ore underneath the Grand Tree.",
|
||||
|
||||
@@ -50,12 +50,9 @@ import net.runelite.api.TileItem;
|
||||
import net.runelite.api.TileObject;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.BeforeRender;
|
||||
import net.runelite.api.events.BoostedLevelChanged;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.DecorativeObjectChanged;
|
||||
import net.runelite.api.events.DecorativeObjectDespawned;
|
||||
import net.runelite.api.events.DecorativeObjectSpawned;
|
||||
import net.runelite.api.events.ExperienceChanged;
|
||||
import net.runelite.api.events.GameObjectChanged;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
@@ -67,12 +64,14 @@ import net.runelite.api.events.GroundObjectSpawned;
|
||||
import net.runelite.api.events.ItemDespawned;
|
||||
import net.runelite.api.events.ItemSpawned;
|
||||
import net.runelite.api.events.MenuOpened;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
import net.runelite.api.events.WallObjectChanged;
|
||||
import net.runelite.api.events.WallObjectDespawned;
|
||||
import net.runelite.api.events.WallObjectSpawned;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.AgilityShortcut;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
@@ -201,8 +200,7 @@ public class AgilityPlugin extends Plugin
|
||||
{
|
||||
eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventBus.subscribe(ExperienceChanged.class, this, this::onExperienceChanged);
|
||||
eventBus.subscribe(BoostedLevelChanged.class, this, this::onBoostedLevelChanged);
|
||||
eventBus.subscribe(StatChanged .class, this, this::onStatChanged);
|
||||
eventBus.subscribe(ItemSpawned.class, this, this::onItemSpawned);
|
||||
eventBus.subscribe(ItemDespawned.class, this, this::onItemDespawned);
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
@@ -295,9 +293,16 @@ public class AgilityPlugin extends Plugin
|
||||
this.showAgilityArenaTimer = config.showAgilityArenaTimer();
|
||||
}
|
||||
|
||||
private void onExperienceChanged(ExperienceChanged event)
|
||||
public void onStatChanged(StatChanged statChanged)
|
||||
{
|
||||
if (event.getSkill() != AGILITY || !this.showLapCount)
|
||||
if (statChanged.getSkill() != AGILITY)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
agilityLevel = statChanged.getBoostedLevel();
|
||||
|
||||
if (!this.showLapCount)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -330,15 +335,6 @@ public class AgilityPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private void onBoostedLevelChanged(BoostedLevelChanged boostedLevelChanged)
|
||||
{
|
||||
Skill skill = boostedLevelChanged.getSkill();
|
||||
if (skill == AGILITY)
|
||||
{
|
||||
agilityLevel = client.getBoostedSkillLevel(skill);
|
||||
}
|
||||
}
|
||||
|
||||
private void onItemSpawned(ItemSpawned itemSpawned)
|
||||
{
|
||||
if (obstacles.isEmpty())
|
||||
|
||||
@@ -45,13 +45,13 @@ import net.runelite.api.Projectile;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.ProjectileMoved;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
|
||||
@@ -28,7 +28,7 @@ import com.google.inject.Provides;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
|
||||
@@ -30,12 +30,12 @@ import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.FocusChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.config.Keybind;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
@@ -47,7 +47,6 @@ import net.runelite.api.NullObjectID;
|
||||
import net.runelite.api.ObjectID;
|
||||
import net.runelite.api.Projectile;
|
||||
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;
|
||||
@@ -57,6 +56,7 @@ import net.runelite.api.events.ProjectileSpawned;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
|
||||
@@ -40,7 +40,7 @@ import net.runelite.api.GameState;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.VarPlayer;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.events.WidgetHiddenChanged;
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
package net.runelite.client.plugins.bank;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.inject.Provides;
|
||||
@@ -43,14 +43,13 @@ import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.Constants.HIGH_ALCHEMY_MULTIPLIER;
|
||||
import net.runelite.api.FontID;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.FontID;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.VarClientStr;
|
||||
@@ -68,6 +67,7 @@ import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
@@ -51,7 +51,14 @@ class ContainerCalculation
|
||||
ContainerPrices calculate(Item[] items)
|
||||
{
|
||||
// Returns last calculation if inventory hasn't changed
|
||||
|
||||
if (items == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
final int newHash = hashItems(items);
|
||||
|
||||
if (containerPrices != null && hash == newHash)
|
||||
{
|
||||
return containerPrices;
|
||||
@@ -86,7 +93,7 @@ class ContainerCalculation
|
||||
final long storePrice = itemManager.getItemDefinition(id).getPrice();
|
||||
final long alchPrice = (long) (storePrice * Constants.HIGH_ALCHEMY_MULTIPLIER);
|
||||
alch += alchPrice * qty;
|
||||
ge += itemManager.getItemPrice(id) * qty;
|
||||
ge += (long) itemManager.getItemPrice(id) * qty;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,23 +36,23 @@ import java.awt.event.MouseWheelEvent;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import static net.runelite.api.Constants.HIGH_ALCHEMY_MULTIPLIER;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.Constants.HIGH_ALCHEMY_MULTIPLIER;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.VarClientStr;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.DraggingWidgetChanged;
|
||||
import net.runelite.api.events.FocusChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
@@ -61,6 +61,7 @@ import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.vars.InputType;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
@@ -83,7 +84,6 @@ import net.runelite.client.plugins.banktags.tabs.TabInterface;
|
||||
import static net.runelite.client.plugins.banktags.tabs.TabInterface.FILTERED_CHARS;
|
||||
import net.runelite.client.plugins.banktags.tabs.TabSprites;
|
||||
import net.runelite.client.plugins.cluescrolls.ClueScrollPlugin;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.util.QuantityFormatter;
|
||||
|
||||
@PluginDescriptor(
|
||||
|
||||
@@ -56,8 +56,8 @@ import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.ScriptEvent;
|
||||
import net.runelite.api.ScriptID;
|
||||
@@ -68,6 +68,7 @@ import net.runelite.api.VarClientStr;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.vars.InputType;
|
||||
import net.runelite.api.widgets.ItemQuantityMode;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
@@ -90,7 +91,6 @@ import static net.runelite.client.plugins.banktags.tabs.MenuIndexes.NewTab;
|
||||
import static net.runelite.client.plugins.banktags.tabs.MenuIndexes.Tab;
|
||||
import net.runelite.client.ui.JagexColors;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.api.util.Text;
|
||||
|
||||
@Singleton
|
||||
public class TabInterface
|
||||
@@ -599,9 +599,11 @@ public class TabInterface
|
||||
chatboxPanelManager.close();
|
||||
}
|
||||
|
||||
if (event.getIdentifier() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
|
||||
if ((event.getIdentifier() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
|
||||
|| event.getIdentifier() == WidgetInfo.BANK_INVENTORY_ITEMS_CONTAINER.getId())
|
||||
&& event.getMenuOpcode() == MenuOpcode.EXAMINE_ITEM_BANK_EQ
|
||||
&& event.getOption().equalsIgnoreCase("withdraw-x"))
|
||||
&& (event.getOption().equalsIgnoreCase("withdraw-x")
|
||||
|| event.getOption().equalsIgnoreCase("deposit-x")))
|
||||
{
|
||||
waitSearchTick = true;
|
||||
rememberedSearch = client.getVar(VarClientStr.INPUT_TEXT);
|
||||
|
||||
@@ -26,13 +26,9 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.banlist;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.inject.Provides;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@@ -41,14 +37,13 @@ import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.ClanMember;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ClanMemberJoined;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.WidgetHiddenChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import static net.runelite.api.widgets.WidgetID.TRADING_SCREEN;
|
||||
import static net.runelite.api.widgets.WidgetID.PLAYER_TRADE_SCREEN_GROUP_ID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.chat.ChatColorType;
|
||||
@@ -57,15 +52,16 @@ import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
import okhttp3.Call;
|
||||
import okhttp3.Callback;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Ban List",
|
||||
@@ -83,16 +79,22 @@ public class BanListPlugin extends Plugin
|
||||
private final Set<String> wdrToxicSet = new HashSet<>();
|
||||
private final Set<String> runeWatchSet = new HashSet<>();
|
||||
private final Set<String> manualBans = new HashSet<>();
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private BanListConfig config;
|
||||
|
||||
@Inject
|
||||
private ChatMessageManager chatMessageManager;
|
||||
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
private String tobNames = "";
|
||||
private boolean enableWDRScam;
|
||||
private boolean enableWDRToxic;
|
||||
@@ -111,12 +113,9 @@ public class BanListPlugin extends Plugin
|
||||
{
|
||||
updateConfig();
|
||||
addSubscriptions();
|
||||
List<String> bannedPlayers = Splitter
|
||||
.on(",")
|
||||
.trimResults()
|
||||
.omitEmptyStrings()
|
||||
.splitToList(config.getBannedPlayers());
|
||||
manualBans.addAll(bannedPlayers);
|
||||
|
||||
manualBans.addAll(Text.fromCSV(Text.standardize(config.getBannedPlayers())));
|
||||
|
||||
fetchFromWebsites();
|
||||
}
|
||||
|
||||
@@ -144,19 +143,11 @@ public class BanListPlugin extends Plugin
|
||||
{
|
||||
if (event.getGroup().equals("banlist") && event.getKey().equals("bannedPlayers"))
|
||||
{
|
||||
List<String> bannedPlayers = Splitter
|
||||
.on(",")
|
||||
.trimResults()
|
||||
.omitEmptyStrings()
|
||||
.splitToList(config.getBannedPlayers());
|
||||
manualBans.clear();
|
||||
|
||||
for (String bannedPlayer : bannedPlayers)
|
||||
{
|
||||
if (!manualBans.contains(bannedPlayer))
|
||||
{
|
||||
manualBans.add(Text.standardize(bannedPlayer));
|
||||
}
|
||||
}
|
||||
String newValue = event.getNewValue();
|
||||
|
||||
manualBans.addAll(Text.fromCSV(Text.standardize(newValue)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,11 +215,12 @@ public class BanListPlugin extends Plugin
|
||||
*/
|
||||
private void onWidgetLoaded(WidgetLoaded widgetLoaded)
|
||||
{
|
||||
if (this.highlightInTrade && widgetLoaded.getGroupId() == TRADING_SCREEN)
|
||||
if (this.highlightInTrade && widgetLoaded.getGroupId() == PLAYER_TRADE_SCREEN_GROUP_ID)
|
||||
{ //if trading window was loaded
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
Widget tradingWith = client.getWidget(335, 31);
|
||||
Widget tradingWith = client.getWidget(WidgetInfo.TRADING_WITH);
|
||||
|
||||
String name = tradingWith.getText().replaceAll("Trading With: ", "").toLowerCase();
|
||||
if (checkScamList(name) != null)
|
||||
{
|
||||
@@ -244,13 +236,12 @@ public class BanListPlugin extends Plugin
|
||||
|
||||
private void onGameTick(GameTick event)
|
||||
{
|
||||
|
||||
if (client.getWidget(WidgetInfo.THEATRE_OF_BLOOD_RAIDING_PARTY) == null)
|
||||
final Widget raidingParty = client.getWidget(WidgetInfo.THEATRE_OF_BLOOD_RAIDING_PARTY);
|
||||
if (raidingParty == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widget raidingParty = client.getWidget(WidgetInfo.THEATRE_OF_BLOOD_RAIDING_PARTY);
|
||||
String allNames = raidingParty.getText();
|
||||
|
||||
if (allNames.equalsIgnoreCase(tobNames))
|
||||
@@ -262,19 +253,20 @@ public class BanListPlugin extends Plugin
|
||||
|
||||
String[] split = allNames.split("<br>");
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
for (String name : split)
|
||||
{
|
||||
String name = split[i];
|
||||
if (!name.equalsIgnoreCase("-"))
|
||||
if (!name.equals("-"))
|
||||
{
|
||||
ListType scamList = checkScamList(Text.standardize(name));
|
||||
String stdName = Text.standardize(name);
|
||||
|
||||
ListType scamList = checkScamList(stdName);
|
||||
|
||||
if (scamList != null)
|
||||
{
|
||||
sendWarning(name, scamList);
|
||||
}
|
||||
|
||||
ListType toxicList = checkToxicList(Text.standardize(name));
|
||||
ListType toxicList = checkToxicList(stdName);
|
||||
|
||||
if (toxicList != null)
|
||||
{
|
||||
@@ -284,29 +276,22 @@ public class BanListPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean inTobParty()
|
||||
{
|
||||
return client.getVar(Varbits.THEATRE_OF_BLOOD) == 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares player name to everything in the ban lists
|
||||
*/
|
||||
private ListType checkScamList(String nameToBeChecked)
|
||||
{
|
||||
if (wdrScamSet.size() > 0 && this.enableWDRScam && wdrScamSet.contains(nameToBeChecked))
|
||||
if (this.enableWDRScam && wdrScamSet.contains(nameToBeChecked))
|
||||
{
|
||||
return ListType.WEDORAIDSSCAM_LIST;
|
||||
}
|
||||
|
||||
if (runeWatchSet.size() > 0 && this.enableRuneWatch && runeWatchSet.contains(nameToBeChecked))
|
||||
if (this.enableRuneWatch && runeWatchSet.contains(nameToBeChecked))
|
||||
{
|
||||
return ListType.RUNEWATCH_LIST;
|
||||
}
|
||||
|
||||
if (manualBans.size() > 0 && manualBans.contains(nameToBeChecked))
|
||||
if (manualBans.contains(nameToBeChecked))
|
||||
{
|
||||
return ListType.MANUAL_LIST;
|
||||
}
|
||||
@@ -316,8 +301,7 @@ public class BanListPlugin extends Plugin
|
||||
|
||||
private ListType checkToxicList(String nameToBeChecked)
|
||||
{
|
||||
|
||||
if (wdrToxicSet.size() > 0 && this.enableWDRToxic && wdrToxicSet.contains(nameToBeChecked))
|
||||
if (this.enableWDRToxic && wdrToxicSet.contains(nameToBeChecked))
|
||||
{
|
||||
return ListType.WEDORAIDSTOXIC_LIST;
|
||||
}
|
||||
@@ -393,29 +377,7 @@ public class BanListPlugin extends Plugin
|
||||
Request request = new Request.Builder()
|
||||
.url("https://wdrdev.github.io/index")
|
||||
.build();
|
||||
RuneLiteAPI.CLIENT.newCall(request).enqueue(new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
{
|
||||
log.debug("error retrieving names from wdr");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException
|
||||
{
|
||||
String text = response.body().string();
|
||||
text = text.substring(text.indexOf("<p>") + 3, text.indexOf("</p>"));
|
||||
text = text.replace("/", ",");
|
||||
text = text.replace(", $", "");
|
||||
|
||||
ArrayList<String> wdrList = new ArrayList<>(Arrays.asList(text.split(",")));
|
||||
ArrayList<String> wdrList2 = new ArrayList<>();
|
||||
wdrList.forEach((name) -> wdrList2.add(Text.standardize(name).toLowerCase()));
|
||||
|
||||
wdrScamSet.addAll(wdrList2);
|
||||
}
|
||||
});
|
||||
fetchAndParseWdr(request, wdrScamSet);
|
||||
|
||||
|
||||
Request secondRequest = new Request.Builder()
|
||||
@@ -424,13 +386,13 @@ public class BanListPlugin extends Plugin
|
||||
RuneLiteAPI.CLIENT.newCall(secondRequest).enqueue(new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e)
|
||||
{
|
||||
log.debug("error retrieving names from runewatch");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException
|
||||
{
|
||||
String text = response.body().string();
|
||||
String mytext = text.substring(text.indexOf("lcp_instance_0"), text.indexOf("strong>Evidence Quality Suggestion"));
|
||||
@@ -450,27 +412,28 @@ public class BanListPlugin extends Plugin
|
||||
Request thirdRequest = new Request.Builder()
|
||||
.url("https://wdrdev.github.io/toxic")
|
||||
.build();
|
||||
RuneLiteAPI.CLIENT.newCall(thirdRequest).enqueue(new Callback()
|
||||
fetchAndParseWdr(thirdRequest, wdrToxicSet);
|
||||
}
|
||||
|
||||
private void fetchAndParseWdr(Request req, Set<String> tgtSet)
|
||||
{
|
||||
RuneLiteAPI.CLIENT.newCall(req).enqueue(new Callback()
|
||||
{
|
||||
@Override
|
||||
public void onFailure(Call call, IOException e)
|
||||
public void onFailure(@NotNull Call call, @NotNull IOException e)
|
||||
{
|
||||
log.debug("error retrieving names from wdr");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(Call call, Response response) throws IOException
|
||||
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException
|
||||
{
|
||||
String text = response.body().string();
|
||||
text = text.substring(text.indexOf("<p>") + 3, text.indexOf("</p>"));
|
||||
text = text.replace("/", ",");
|
||||
text = text.replace(", $", "");
|
||||
|
||||
ArrayList<String> wdrToxicList = new ArrayList<>(Arrays.asList(text.split(",")));
|
||||
ArrayList<String> wdrToxicList2 = new ArrayList<>();
|
||||
wdrToxicList.forEach((name) -> wdrToxicList2.add(Text.standardize(name).toLowerCase()));
|
||||
|
||||
wdrToxicSet.addAll(wdrToxicList2);
|
||||
Text.fromCSV(text).forEach(str -> tgtSet.add(Text.standardize(str)));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -485,16 +448,15 @@ public class BanListPlugin extends Plugin
|
||||
Widget widget = client.getWidget(WidgetInfo.CLAN_CHAT_LIST);
|
||||
for (Widget widgetChild : widget.getDynamicChildren())
|
||||
{
|
||||
ListType scamList = checkScamList(widgetChild.getText().toLowerCase());
|
||||
ListType toxicList = checkToxicList(widgetChild.getText().toLowerCase());
|
||||
String text = widgetChild.getText(), lc = text.toLowerCase();
|
||||
|
||||
if (scamList != null)
|
||||
if (checkScamList(lc) != null)
|
||||
{
|
||||
widgetChild.setText("<col=ff0000>" + widgetChild.getText() + "</col>");
|
||||
widgetChild.setText("<col=ff0000>" + text + "</col>");
|
||||
}
|
||||
else if (toxicList != null)
|
||||
else if (checkToxicList(lc) != null)
|
||||
{
|
||||
widgetChild.setText("<col=ff6400>" + widgetChild.getText() + "</col>");
|
||||
widgetChild.setText("<col=ff6400>" + text + "</col>");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -60,7 +60,6 @@ import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.BeforeRender;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.InteractingChanged;
|
||||
import net.runelite.api.events.ItemDespawned;
|
||||
@@ -72,6 +71,7 @@ import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.ProjectileSpawned;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
@@ -83,6 +83,7 @@ import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
@@ -97,7 +98,6 @@ import net.runelite.client.ui.overlay.infobox.InfoBox;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.api.util.Text;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ import net.runelite.api.NullObjectID;
|
||||
import net.runelite.api.ObjectID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.WallObject;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameObjectChanged;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
@@ -56,6 +55,7 @@ import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.SpriteManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
@@ -35,12 +35,12 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.menus.AbstractComparableEntry;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
|
||||
@@ -38,21 +38,21 @@ import net.runelite.api.GameState;
|
||||
import static net.runelite.api.NullObjectID.NULL_9092;
|
||||
import static net.runelite.api.ObjectID.CONVEYOR_BELT;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.api.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Blast Furnace",
|
||||
|
||||
@@ -39,10 +39,10 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.Constants;
|
||||
import net.runelite.api.Prayer;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.events.BoostedLevelChanged;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
@@ -174,7 +174,7 @@ public class BoostsPlugin extends Plugin
|
||||
{
|
||||
eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventBus.subscribe(BoostedLevelChanged.class, this, this::onBoostedLevelChanged);
|
||||
eventBus.subscribe(StatChanged.class, this, this::onStatChanged);
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
}
|
||||
|
||||
@@ -211,9 +211,9 @@ public class BoostsPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private void onBoostedLevelChanged(BoostedLevelChanged boostedLevelChanged)
|
||||
private void onStatChanged(StatChanged statChanged)
|
||||
{
|
||||
Skill skill = boostedLevelChanged.getSkill();
|
||||
Skill skill = statChanged.getSkill();
|
||||
|
||||
if (!BOOSTABLE_COMBAT_SKILLS.contains(skill) && !BOOSTABLE_NON_COMBAT_SKILLS.contains(skill))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2019, winterdaze
|
||||
* 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.bosstimetracker;
|
||||
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBox;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.Color;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class BossTimeTracker extends InfoBox
|
||||
{
|
||||
private final Instant startTime;
|
||||
private LocalTime time;
|
||||
private Instant lastTime;
|
||||
|
||||
public BossTimeTracker(BufferedImage image, BossTimeTrackerPlugin plugin, Instant startTime, Instant lastTime)
|
||||
{
|
||||
super(image, plugin);
|
||||
this.startTime = startTime;
|
||||
this.lastTime = lastTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText()
|
||||
{
|
||||
if (startTime == null)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
if (lastTime == null)
|
||||
{
|
||||
Duration elapsed = Duration.between(startTime, Instant.now());
|
||||
time = LocalTime.ofSecondOfDay(elapsed.getSeconds());
|
||||
}
|
||||
else
|
||||
{
|
||||
Duration elapsed = Duration.between(startTime, lastTime);
|
||||
time = LocalTime.ofSecondOfDay(elapsed.getSeconds());
|
||||
}
|
||||
|
||||
if (time.getHour() > 0)
|
||||
{
|
||||
return time.format(DateTimeFormatter.ofPattern("HH:mm"));
|
||||
}
|
||||
return time.format(DateTimeFormatter.ofPattern("mm:ss"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getTextColor()
|
||||
{
|
||||
return Color.WHITE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTooltip()
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("Elapsed time: ");
|
||||
builder.append(time.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2019, winterdaze
|
||||
* 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.bosstimetracker;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static net.runelite.api.ItemID.FIRE_CAPE;
|
||||
import static net.runelite.api.ItemID.INFERNAL_CAPE;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Boss Time Tracker",
|
||||
description = "Display elapsed time in the Fight Caves and Inferno",
|
||||
tags = {"inferno", "fight", "caves", "cape", "timer", "tzhaar", "pvm"},
|
||||
type = PluginType.PVM,
|
||||
enabledByDefault = false
|
||||
)
|
||||
public class BossTimeTrackerPlugin extends Plugin
|
||||
{
|
||||
private static final Pattern WAVE_MESSAGE = Pattern.compile("Wave: (\\d+)");
|
||||
private static final String DEFEATED_MESSAGE = "You have been defeated!";
|
||||
private static final Pattern COMPLETE_MESSAGE = Pattern.compile("Your (TzTok-Jad|TzKal-Zuk) kill count is:");
|
||||
private static final Pattern PAUSED_MESSAGE = Pattern.compile("The (Inferno|Fight Cave) has been paused. You may now log out.");
|
||||
private static final String CONFIG_GROUP = "Boss Time Tracker";
|
||||
private static final String CONFIG_TIME = "time";
|
||||
private static final String CONFIG_STARTED = "started";
|
||||
private static final String CONFIG_LASTTIME = "lasttime";
|
||||
|
||||
@Inject
|
||||
private InfoBoxManager infoBoxManager;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@Getter
|
||||
private BossTimeTracker timer;
|
||||
|
||||
private Instant startTime;
|
||||
private Instant lastTime;
|
||||
private Boolean started = false;
|
||||
private boolean loggingIn;
|
||||
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
addSubscriptions();
|
||||
}
|
||||
|
||||
public void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
switch (event.getGameState())
|
||||
{
|
||||
case LOGGED_IN:
|
||||
if (loggingIn)
|
||||
{
|
||||
loggingIn = false;
|
||||
loadConfig();
|
||||
resetConfig();
|
||||
}
|
||||
break;
|
||||
case LOGGING_IN:
|
||||
loggingIn = true;
|
||||
break;
|
||||
case LOADING:
|
||||
if (!loggingIn)
|
||||
{
|
||||
updateInfoBoxState();
|
||||
}
|
||||
break;
|
||||
case HOPPING:
|
||||
loggingIn = true;
|
||||
case LOGIN_SCREEN:
|
||||
removeTimer();
|
||||
saveConfig();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (event.getType() != ChatMessageType.GAMEMESSAGE && event.getType() != ChatMessageType.SPAM)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String message = Text.removeTags(event.getMessage());
|
||||
Matcher matcher = COMPLETE_MESSAGE.matcher(message);
|
||||
|
||||
if (message.contains(DEFEATED_MESSAGE) || matcher.matches())
|
||||
{
|
||||
removeTimer();
|
||||
resetConfig();
|
||||
resetVars();
|
||||
return;
|
||||
}
|
||||
|
||||
Instant now = Instant.now();
|
||||
matcher = PAUSED_MESSAGE.matcher(message);
|
||||
if (matcher.matches())
|
||||
{
|
||||
lastTime = now;
|
||||
createTimer(startTime, now);
|
||||
return;
|
||||
}
|
||||
|
||||
matcher = WAVE_MESSAGE.matcher(message);
|
||||
if (!matcher.matches())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!started)
|
||||
{
|
||||
int wave = Integer.parseInt(matcher.group(1));
|
||||
if (wave != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
started = true;
|
||||
startTime = now;
|
||||
}
|
||||
else if (lastTime != null)
|
||||
{
|
||||
startTime = startTime.plus(Duration.between(startTime, now)).minus(Duration.between(startTime, lastTime));
|
||||
lastTime = null;
|
||||
}
|
||||
|
||||
createTimer(startTime, lastTime);
|
||||
}
|
||||
|
||||
private void updateInfoBoxState()
|
||||
{
|
||||
if (timer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkInFightCaves() && !checkInInferno())
|
||||
{
|
||||
removeTimer();
|
||||
resetConfig();
|
||||
resetVars();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkInFightCaves()
|
||||
{
|
||||
return client.getMapRegions() != null && Arrays.stream(client.getMapRegions())
|
||||
.filter(x -> x == 9551)
|
||||
.toArray().length > 0;
|
||||
}
|
||||
|
||||
private boolean checkInInferno()
|
||||
{
|
||||
return client.getMapRegions() != null && Arrays.stream(client.getMapRegions())
|
||||
.filter(x -> x == 9043)
|
||||
.toArray().length > 0;
|
||||
}
|
||||
|
||||
private void resetVars()
|
||||
{
|
||||
startTime = null;
|
||||
lastTime = null;
|
||||
started = false;
|
||||
}
|
||||
|
||||
private void removeTimer()
|
||||
{
|
||||
infoBoxManager.removeInfoBox(timer);
|
||||
timer = null;
|
||||
}
|
||||
|
||||
private void createTimer(Instant startTime, Instant lastTime)
|
||||
{
|
||||
if (timer != null)
|
||||
{
|
||||
infoBoxManager.removeInfoBox(timer);
|
||||
}
|
||||
|
||||
if (checkInFightCaves())
|
||||
{
|
||||
timer = new BossTimeTracker(itemManager.getImage(FIRE_CAPE), this, startTime, lastTime);
|
||||
infoBoxManager.addInfoBox(timer);
|
||||
}
|
||||
else if (checkInInferno())
|
||||
{
|
||||
timer = new BossTimeTracker(itemManager.getImage(INFERNAL_CAPE), this, startTime, lastTime);
|
||||
infoBoxManager.addInfoBox(timer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown() throws Exception
|
||||
{
|
||||
eventBus.unregister(this);
|
||||
removeTimer();
|
||||
resetConfig();
|
||||
resetVars();
|
||||
}
|
||||
|
||||
private void addSubscriptions()
|
||||
{
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventBus.subscribe(ChatMessage.class, this, this::onChatMessage);
|
||||
}
|
||||
|
||||
private void loadConfig()
|
||||
{
|
||||
startTime = configManager.getConfiguration(CONFIG_GROUP, CONFIG_TIME, Instant.class);
|
||||
started = configManager.getConfiguration(CONFIG_GROUP, CONFIG_STARTED, Boolean.class);
|
||||
lastTime = configManager.getConfiguration(CONFIG_GROUP, CONFIG_LASTTIME, Instant.class);
|
||||
if (started == null)
|
||||
{
|
||||
started = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void resetConfig()
|
||||
{
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, CONFIG_TIME);
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, CONFIG_STARTED);
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, CONFIG_LASTTIME);
|
||||
}
|
||||
|
||||
private void saveConfig()
|
||||
{
|
||||
if (startTime == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastTime == null)
|
||||
{
|
||||
lastTime = Instant.now();
|
||||
}
|
||||
|
||||
configManager.setConfiguration(CONFIG_GROUP, CONFIG_TIME, startTime);
|
||||
configManager.setConfiguration(CONFIG_GROUP, CONFIG_STARTED, started);
|
||||
configManager.setConfiguration(CONFIG_GROUP, CONFIG_LASTTIME, lastTime);
|
||||
resetVars();
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ import static net.runelite.api.ProjectileID.CANNONBALL;
|
||||
import static net.runelite.api.ProjectileID.GRANITE_CANNONBALL;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ItemContainerChanged;
|
||||
|
||||
@@ -37,7 +37,7 @@ public enum CannonSpots
|
||||
FIRE_GIANTS(new WorldPoint(2393, 9782, 0), new WorldPoint(2412, 9776, 0), new WorldPoint(2401, 9780, 0)),
|
||||
ABERRANT_SPECTRES(new WorldPoint(2456, 9791, 0)),
|
||||
HELLHOUNDS(new WorldPoint(2431, 9776, 0), new WorldPoint(2413, 9786, 0), new WorldPoint(2783, 9686, 0), new WorldPoint(3198, 10071, 0)),
|
||||
BLACK_DEMONS(new WorldPoint(2859, 9778, 0), new WorldPoint(2841, 9791, 0)),
|
||||
BLACK_DEMONS(new WorldPoint(2859, 9778, 0), new WorldPoint(2841, 9791, 0), new WorldPoint(1421, 10089, 1)),
|
||||
ELVES(new WorldPoint(2044, 4635, 0), new WorldPoint(3278, 6098, 0)),
|
||||
SUQAHS(new WorldPoint(2114, 3943, 0)),
|
||||
TROLLS(new WorldPoint(2401, 3856, 0)),
|
||||
|
||||
@@ -24,14 +24,12 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.chatboxperformance;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
@@ -41,6 +39,7 @@ import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
|
||||
@@ -28,9 +28,9 @@ package net.runelite.client.plugins.chatfilter;
|
||||
import com.google.common.base.CharMatcher;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.inject.Provides;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
@@ -42,14 +42,14 @@ import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MessageNode;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.OverheadTextChanged;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.api.util.Text;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@PluginDescriptor(
|
||||
@@ -68,7 +68,7 @@ public class ChatFilterPlugin extends Plugin
|
||||
private static final String CENSOR_MESSAGE = "Hey, everyone, I just tried to say something very silly!";
|
||||
|
||||
private final CharMatcher jagexPrintableCharMatcher = Text.JAGEX_PRINTABLE_CHAR_MATCHER;
|
||||
private final List<Pattern> filteredPatterns = new ArrayList<>();
|
||||
private final List<Pattern> filteredPatterns = new CopyOnWriteArrayList<>();
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@@ -39,19 +39,19 @@ import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.VarClientInt;
|
||||
import net.runelite.api.VarClientStr;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.vars.InputType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.input.KeyListener;
|
||||
import net.runelite.client.input.KeyManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.api.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Chat History",
|
||||
|
||||
@@ -41,7 +41,7 @@ import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MessageNode;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
|
||||
@@ -17,22 +17,22 @@ import net.runelite.api.MessageNode;
|
||||
import static net.runelite.api.ScriptID.CHATBOX_INPUT;
|
||||
import net.runelite.api.VarClientStr;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.MenuOpened;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.util.Text;
|
||||
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.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
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.api.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Chat Translator",
|
||||
|
||||
@@ -57,13 +57,14 @@ import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ClanChanged;
|
||||
import net.runelite.api.events.ClanMemberJoined;
|
||||
import net.runelite.api.events.ClanMemberLeft;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.PlayerDespawned;
|
||||
import net.runelite.api.events.PlayerSpawned;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.events.VarClientStrChanged;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
@@ -80,7 +81,6 @@ import static net.runelite.client.ui.JagexColors.CHAT_CLAN_NAME_TRANSPARENT_BACK
|
||||
import static net.runelite.client.ui.JagexColors.CHAT_CLAN_TEXT_OPAQUE_BACKGROUND;
|
||||
import static net.runelite.client.ui.JagexColors.CHAT_CLAN_TEXT_TRANSPARENT_BACKGROUND;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
import net.runelite.api.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Clan Chat",
|
||||
@@ -411,7 +411,8 @@ public class ClanChatPlugin extends Plugin
|
||||
|
||||
ChatMessageBuilder message = new ChatMessageBuilder()
|
||||
.append("[")
|
||||
.append(channelColor, client.getClanChatName());
|
||||
.append(channelColor, client.getClanChatName() == null ? "" : client.getClanChatName());
|
||||
|
||||
if (rankIcon > -1)
|
||||
{
|
||||
message
|
||||
|
||||
@@ -14,11 +14,11 @@ import net.runelite.api.GameState;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
|
||||
@@ -60,7 +60,7 @@ import net.runelite.api.TileObject;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ItemContainerChanged;
|
||||
@@ -389,6 +389,11 @@ public class ClueScrollPlugin extends Plugin
|
||||
|
||||
for (WorldPoint location : locations)
|
||||
{
|
||||
if (location == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only set the location hint arrow if we do not already have more accurate location
|
||||
if (location.isInScene(client)
|
||||
&& this.displayHintArrows
|
||||
@@ -512,17 +517,6 @@ public class ClueScrollPlugin extends Plugin
|
||||
return clue;
|
||||
}
|
||||
|
||||
// (This|The) anagram reveals who to speak to next:
|
||||
if (text.contains("anagram reveals who to speak to next:"))
|
||||
{
|
||||
return AnagramClue.forText(text);
|
||||
}
|
||||
|
||||
if (text.startsWith("the cipher reveals who to speak to next:"))
|
||||
{
|
||||
return CipherClue.forText(text);
|
||||
}
|
||||
|
||||
if (text.startsWith("i'd like to hear some music."))
|
||||
{
|
||||
return MusicClue.forText(clueScrollText.getText());
|
||||
@@ -533,6 +527,18 @@ public class ClueScrollPlugin extends Plugin
|
||||
return coordinatesToWorldPoint(text);
|
||||
}
|
||||
|
||||
final AnagramClue anagramClue = AnagramClue.forText(text);
|
||||
if (anagramClue != null)
|
||||
{
|
||||
return anagramClue;
|
||||
}
|
||||
|
||||
final CipherClue cipherClue = CipherClue.forText(text);
|
||||
if (cipherClue != null)
|
||||
{
|
||||
return cipherClue;
|
||||
}
|
||||
|
||||
final CrypticClue crypticClue = CrypticClue.forText(text);
|
||||
|
||||
if (crypticClue != null)
|
||||
@@ -680,6 +686,11 @@ public class ClueScrollPlugin extends Plugin
|
||||
final Tile tile = tiles[client.getPlane()][localLocation.getSceneX()][localLocation.getSceneY()];
|
||||
objectsToMark.clear();
|
||||
|
||||
if (tile == null || tile.getGameObjects() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (GameObject object : tile.getGameObjects())
|
||||
{
|
||||
if (object == null)
|
||||
|
||||
@@ -51,109 +51,109 @@ public class AnagramClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
private static final String ANAGRAM_TEXT_BEGINNER = "The anagram reveals who to speak to next: ";
|
||||
|
||||
private static final Set<AnagramClue> CLUES = ImmutableSet.of(
|
||||
new AnagramClue("A BAKER", "Baraek", new WorldPoint(3217, 3434, 0), "Varrock square", "5"),
|
||||
new AnagramClue("A BASIC ANTI POT", "Captain Tobias", new WorldPoint(3026, 3216, 0), "Port Sarim", "6"),
|
||||
new AnagramClue("A BAKER", "Baraek", new WorldPoint(3217, 3434, 0), "Varrock square", "How many stalls are there in Varrock Square?", "5"),
|
||||
new AnagramClue("A BASIC ANTI POT", "Captain Tobias", new WorldPoint(3026, 3216, 0), "Port Sarim", "How many ships are there docked at Port Sarim currently?", "6"),
|
||||
new AnagramClue("A ELF KNOWS", "Snowflake", new WorldPoint(2872, 3934, 0), "Weiss"),
|
||||
new AnagramClue("A HEART", "Aretha", new WorldPoint(1814, 3851, 0), "Soul altar", "2"),
|
||||
new AnagramClue("A HEART", "Aretha", new WorldPoint(1814, 3851, 0), "Soul altar", "32 - 5x = 22, what is x?", "2"),
|
||||
new AnagramClue("A ZEN SHE", "Zenesha", new WorldPoint(2652, 3295, 0), "Platebody Southern Ardougne centre square"),
|
||||
new AnagramClue("ACE MATCH ELM", "Cam The Camel", new WorldPoint(3300, 3231, 0), "North of the glider in Al Kharid"),
|
||||
new AnagramClue("AHA JAR", "Jaraah", new WorldPoint(3359, 3276, 0), "Duel Arena hospital"),
|
||||
new AnagramClue("AN PAINT TONIC", "Captain Ninto", new WorldPoint(2865, 9877, 0), "Bar under White Wolf Mountain"),
|
||||
new AnagramClue("ARC O LINE", "Caroline", new WorldPoint(2715, 3302, 0), "North Witchaven next to the row boat", "11"),
|
||||
new AnagramClue("ARE COL", "Oracle", new WorldPoint(3013, 3501, 0), "Ice Mountain West of Edgeville", "48"),
|
||||
new AnagramClue("ARMCHAIR THE PELT", "Charlie the Tramp", new WorldPoint(3209, 3392, 0), "South entrance of Varrock", "0"),
|
||||
new AnagramClue("ARC O LINE", "Caroline", new WorldPoint(2715, 3302, 0), "North Witchaven next to the row boat", "How many fishermen are there on the fishing platform?", "11"),
|
||||
new AnagramClue("ARE COL", "Oracle", new WorldPoint(3013, 3501, 0), "Ice Mountain West of Edgeville", "If x is 15 and y is 3 what is 3x + y?", "48"),
|
||||
new AnagramClue("ARMCHAIR THE PELT", "Charlie the Tramp", new WorldPoint(3209, 3392, 0), "South entrance of Varrock", "How many coins would I have if I had 0 coins and attempted to buy 3 loaves of bread?", "0"),
|
||||
new AnagramClue("ARR! SO I AM A CRUST, AND?", "Ramara du Croissant", new WorldPoint(2339, 3677, 0), "Piscatoris Fishing Colony"),
|
||||
new AnagramClue("AT HERG", "Regath", new WorldPoint(1719, 3723, 0), "General Store, Arceuus, Zeah", "25"),
|
||||
new AnagramClue("AT HERG", "Regath", new WorldPoint(1719, 3723, 0), "General Store, Arceuus, Zeah", "What is -5 to the power of 2?", "25"),
|
||||
new AnagramClue("A BAS", "Saba", new WorldPoint(2858, 3577, 0), "Death Plateau"),
|
||||
new AnagramClue("AREA CHEF TREK", "Father Aereck", new WorldPoint(3243, 3208, 0), "Lumbridge Church", "19 or 20"),
|
||||
new AnagramClue("AREA CHEF TREK", "Father Aereck", new WorldPoint(3243, 3208, 0), "Lumbridge Church", "How many gravestones are in the church graveyard?", "19 or 20"),
|
||||
new AnagramClue("BAIL TRIMS", "Brimstail", new WorldPoint(2402, 3419, 0), "West of Stronghold Slayer Cave"),
|
||||
new AnagramClue("BAKER CLIMB", "Brambickle", new WorldPoint(2783, 3861, 0), "Trollweiss mountain"),
|
||||
new AnagramClue("BLUE GRIM GUIDED", "Lumbridge Guide", new WorldPoint(3232, 3232, 0), "Lumbridge"),
|
||||
new AnagramClue("BY LOOK", "Bolkoy", new WorldPoint(2529, 3162, 0), "Tree Gnome Village general store", "13"),
|
||||
new AnagramClue("CALAMARI MADE MUD", "Madame Caldarium", new WorldPoint(2553, 2868, 0), "Corsair Cove", "6"),
|
||||
new AnagramClue("BY LOOK", "Bolkoy", new WorldPoint(2529, 3162, 0), "Tree Gnome Village general store", "How many flowers are there in the clearing below this platform?", "13"),
|
||||
new AnagramClue("CALAMARI MADE MUD", "Madame Caldarium", new WorldPoint(2553, 2868, 0), "Corsair Cove", "What is 3(5-3)?", "6"),
|
||||
new AnagramClue("CAR IF ICES", "Sacrifice", new WorldPoint(2209, 3056, 0), "Zul-Andra"),
|
||||
new AnagramClue("CAREER IN MOON", "Oneiromancer", new WorldPoint(2150, 3866, 0), "Astral altar", "25"),
|
||||
new AnagramClue("CLASH ION", "Nicholas", new WorldPoint(1841, 3803, 0), "North of Port Piscarilius fishing shop", "4"),
|
||||
new AnagramClue("C ON GAME HOC", "Gnome Coach", new WorldPoint(2395, 3486, 0), "Gnome Ball course", "6"),
|
||||
new AnagramClue("COOL NERD", "Old crone", new WorldPoint(3462, 3557, 0), "East of the Slayer Tower", "619"),
|
||||
new AnagramClue("COPPER ORE CRYPTS", "Prospector Percy", new WorldPoint(3061, 3377, 0), "Motherlode Mine", "12"),
|
||||
new AnagramClue("CAREER IN MOON", "Oneiromancer", new WorldPoint(2150, 3866, 0), "Astral altar", "How many Suqah inhabit Lunar isle?", "25"),
|
||||
new AnagramClue("CLASH ION", "Nicholas", new WorldPoint(1841, 3803, 0), "North of Port Piscarilius fishing shop", "How many windows are in Tynan's shop?", "4"),
|
||||
new AnagramClue("C ON GAME HOC", "Gnome Coach", new WorldPoint(2395, 3486, 0), "Gnome Ball course", "How many gnomes on the Gnome ball field have red patches on their uniforms?", "6"),
|
||||
new AnagramClue("COOL NERD", "Old crone", new WorldPoint(3462, 3557, 0), "East of the Slayer Tower", "What is the combined combat level of each species that live in Slayer tower?", "619"),
|
||||
new AnagramClue("COPPER ORE CRYPTS", "Prospector Percy", new WorldPoint(3061, 3377, 0), "Motherlode Mine", "During a party, everyone shook hands with everyone else. There were 66 handshakes. How many people were at the party?", "12"),
|
||||
new AnagramClue("DED WAR", "Edward", new WorldPoint(3284, 3943, 0), "Inside Rogue's Castle"),
|
||||
new AnagramClue("DEKAGRAM", "Dark mage", new WorldPoint(3039, 4835, 0), "Centre of the Abyss", "13"),
|
||||
new AnagramClue("DO SAY MORE", "Doomsayer", new WorldPoint(3230, 3230, 0), "East of Lumbridge Castle", "95"),
|
||||
new AnagramClue("DIM THARN", "Mandrith", new WorldPoint(3182, 3946, 0), "Wilderness Resource Area", "28 or Puzzle box"),
|
||||
new AnagramClue("DR HITMAN", "Mandrith", new WorldPoint(3182, 3946, 0), "Wilderness Resource Area", "28, Light box or Puzzle box"),
|
||||
new AnagramClue("DR WARDEN FUNK", "Drunken Dwarf", new WorldPoint(2913, 10221, 0), "East Side of Keldagrim", "Puzzle box"),
|
||||
new AnagramClue("DRAGONS LAMENT", "Strange Old Man", new WorldPoint(3564, 3288, 0), "Barrows", "40"),
|
||||
new AnagramClue("DT RUN B", "Brundt the Chieftain", new WorldPoint(2658, 3670, 0), "Rellekka, main hall", "4"),
|
||||
new AnagramClue("DEKAGRAM", "Dark mage", new WorldPoint(3039, 4835, 0), "Centre of the Abyss", "How many rifts are found here in the abyss?", "13"),
|
||||
new AnagramClue("DO SAY MORE", "Doomsayer", new WorldPoint(3230, 3230, 0), "East of Lumbridge Castle", "What is 40 divided by 1/2 plus 15?", "95"),
|
||||
new AnagramClue("DIM THARN", "Mandrith", new WorldPoint(3182, 3946, 0), "Wilderness Resource Area"),
|
||||
new AnagramClue("DR HITMAN", "Mandrith", new WorldPoint(3182, 3946, 0), "Wilderness Resource Area", "How many scorpions live under the pit?", "28"),
|
||||
new AnagramClue("DR WARDEN FUNK", "Drunken Dwarf", new WorldPoint(2913, 10221, 0), "East Side of Keldagrim"),
|
||||
new AnagramClue("DRAGONS LAMENT", "Strange Old Man", new WorldPoint(3564, 3288, 0), "Barrows", "One pipe fills a barrel in 1 hour while another pipe can fill the same barrel in 2 hours. How many minutes will it take to fill the take if both pipes are used?", "40"),
|
||||
new AnagramClue("DT RUN B", "Brundt the Chieftain", new WorldPoint(2658, 3670, 0), "Rellekka, main hall", "How many people are waiting for the next bard to perform?", "4"),
|
||||
new AnagramClue("DUO PLUG", "Dugopul", new WorldPoint(2803, 2744, 0), "Graveyard on Ape Atoll"),
|
||||
new AnagramClue("EEK ZERO OP", "Zoo keeper", new WorldPoint(2613, 3269, 0), "Ardougne Zoo", "40"),
|
||||
new AnagramClue("EEK ZERO OP", "Zoo keeper", new WorldPoint(2613, 3269, 0), "Ardougne Zoo", "How many animals are in the Ardougne Zoo?", "40"),
|
||||
new AnagramClue("EL OW", "Lowe", new WorldPoint(3233, 3423, 0), "Varrock archery store"),
|
||||
new AnagramClue("ERR CURE IT", "Recruiter", new WorldPoint(2541, 3305, 0), "West Ardougne centre square", "20"),
|
||||
new AnagramClue("ERR CURE IT", "Recruiter", new WorldPoint(2541, 3305, 0), "West Ardougne centre square", "How many houses have a cross on the door?", "20"),
|
||||
new AnagramClue("FORLUN", "Runolf", new WorldPoint(2512, 10256, 0), "Miscellania & Etceteria Dungeon"),
|
||||
new AnagramClue("GOBLIN KERN", "King Bolren", new WorldPoint(2541, 3170, 0), "Tree Gnome Village"),
|
||||
new AnagramClue("GOT A BOY", "Gabooty", new WorldPoint(2790, 3066, 0), "Centre of Tai Bwo Wannai", "11"),
|
||||
new AnagramClue("GOT A BOY", "Gabooty", new WorldPoint(2790, 3066, 0), "Centre of Tai Bwo Wannai", "How many buildings in the village?", "11"),
|
||||
new AnagramClue("GULAG RUN", "Uglug Nar", new WorldPoint(2442, 3051, 0), "West of Jiggig"),
|
||||
new AnagramClue("GOBLETS ODD TOES", "Otto Godblessed", new WorldPoint(2501, 3487, 0), "Otto's Grotto", "2"),
|
||||
new AnagramClue("HALT US", "Luthas", new WorldPoint(2938, 3152, 0), "Banana plantation, Karamja", "33 (or none)"),
|
||||
new AnagramClue("GOBLETS ODD TOES", "Otto Godblessed", new WorldPoint(2501, 3487, 0), "Otto's Grotto", "How many types of dragon are there beneath the whirlpool's cavern?", "2"),
|
||||
new AnagramClue("HALT US", "Luthas", new WorldPoint(2938, 3152, 0), "Banana plantation, Karamja"),
|
||||
new AnagramClue("HE DO POSE. IT IS CULTRRL, MK?", "Riki the sculptor's model", new WorldPoint(2904, 10206, 0), "East Keldagrim, south of kebab seller."),
|
||||
new AnagramClue("HEORIC", "Eohric", new WorldPoint(2900, 3565, 0), "Top floor of Burthorpe Castle", "36"),
|
||||
new AnagramClue("HIS PHOR", "Horphis", new WorldPoint(1639, 3812, 0), "Arceuus Library, Zeah", "1"),
|
||||
new AnagramClue("I AM SIR", "Marisi", new WorldPoint(1737, 3557, 0), "Allotment patch, South of Hosidius chapel", "5"),
|
||||
new AnagramClue("HEORIC", "Eohric", new WorldPoint(2900, 3565, 0), "Top floor of Burthorpe Castle", "King Arthur and Merlin sit down at the Round Table with 8 knights. How many degrees does each get?", "36"),
|
||||
new AnagramClue("HIS PHOR", "Horphis", new WorldPoint(1639, 3812, 0), "Arceuus Library, Zeah", "On a scale of 1-10, how helpful is Logosia?", "1"),
|
||||
new AnagramClue("I AM SIR", "Marisi", new WorldPoint(1737, 3557, 0), "Allotment patch, South of Hosidius chapel", "How many cities form the Kingdom of Great Kourend?", "5"),
|
||||
new AnagramClue("ICY FE", "Fycie", new WorldPoint(2630, 2997, 0), "East Feldip Hills"),
|
||||
new AnagramClue("I DOOM ICON INN", "Dominic Onion", new WorldPoint(2609, 3116, 0), "Nightmare Zone", "9,500"),
|
||||
new AnagramClue("I DOOM ICON INN", "Dominic Onion", new WorldPoint(2609, 3116, 0), "Nightmare Zone", "How many reward points does a herb box cost?", "9,500"),
|
||||
new AnagramClue("I EAT ITS CHART HINTS DO U", "Shiratti the Custodian", new WorldPoint(3427, 2927, 0), "North of fountain, Nardah"),
|
||||
new AnagramClue("I EVEN", "Nieve", new WorldPoint(2432, 3422, 0), "The slayer master in Gnome Stronghold", "2"),
|
||||
new AnagramClue("I EVEN", "Nieve", new WorldPoint(2432, 3422, 0), "The slayer master in Gnome Stronghold", "How many farming patches are there in Gnome stronghold?", "2"),
|
||||
new AnagramClue("I FAFFY RUN", "Fairy Nuff", new WorldPoint(3201, 3169, 0), "North of the bank in Zanaris"),
|
||||
new AnagramClue("IM N ZEZIM", "Impling", new WorldPoint(2592, 4324, 0), "The Imp inside Puro-Puro"),
|
||||
new AnagramClue("KAY SIR", "Sir Kay", new WorldPoint(2760, 3496, 0), "The courtyard in Camelot Castle", "6"),
|
||||
new AnagramClue("LEAKEY", "Kaylee", new WorldPoint(2957, 3370, 0), "Rising Sun Inn in Falador", "18"),
|
||||
new AnagramClue("KAY SIR", "Sir Kay", new WorldPoint(2760, 3496, 0), "The courtyard in Camelot Castle", "How many fountains are there within the grounds of Camelot castle.", "6"),
|
||||
new AnagramClue("LEAKEY", "Kaylee", new WorldPoint(2957, 3370, 0), "Rising Sun Inn in Falador", "How many chairs are there in the Rising Sun?", "18"),
|
||||
new AnagramClue("LAND DOOMD", "Odd Old Man", new WorldPoint(3359, 3506, 0), "Limestone mine northeast of Varrock"),
|
||||
new AnagramClue("LARK IN DOG", "King Roald", new WorldPoint(3220, 3476, 0), "Ground floor of Varrock castle", "24"),
|
||||
new AnagramClue("LOW LAG", "Gallow", new WorldPoint(1805, 3566, 0), "Vinery in the Great Kourend", "12"),
|
||||
new AnagramClue("LADDER MEMO GUV", "Guard Vemmeldo", new WorldPoint(2447, 3418, 1), "Gnome Stronghold Bank", "3"),
|
||||
new AnagramClue("LARK IN DOG", "King Roald", new WorldPoint(3220, 3476, 0), "Ground floor of Varrock castle", "How many bookcases are there in the Varrock palace library?", "24"),
|
||||
new AnagramClue("LOW LAG", "Gallow", new WorldPoint(1805, 3566, 0), "Vinery in the Great Kourend", "How many vine patches can you find in this vinery?", "12"),
|
||||
new AnagramClue("LADDER MEMO GUV", "Guard Vemmeldo", new WorldPoint(2447, 3418, 1), "Gnome Stronghold Bank", "How many magic trees can you find inside the Gnome Stronghold?", "3"),
|
||||
new AnagramClue("MAL IN TAU", "Luminata", new WorldPoint(3508, 3237, 0), "Near Burgh de Rott entrance"),
|
||||
new AnagramClue("ME AM THE CALC", "Cam the Camel", new WorldPoint(3300, 3231, 0), "Outside Duel Arena"),
|
||||
new AnagramClue("MACHETE CLAM", "Cam the Camel", new WorldPoint(3300, 3231, 0), "Outside Duel Arena", "6"),
|
||||
new AnagramClue("MACHETE CLAM", "Cam the Camel", new WorldPoint(3300, 3231, 0), "Outside Duel Arena", "How many items can carry water in RuneScape?", "6"),
|
||||
new AnagramClue("ME IF", "Femi", new WorldPoint(2461, 3382, 0), "Gates of Tree Gnome Stronghold"),
|
||||
new AnagramClue("MOLD LA RAN", "Old Man Ral", new WorldPoint(3602, 3209, 0), "Meiyerditch"),
|
||||
new AnagramClue("MOTHERBOARD", "Brother Omad", new WorldPoint(2606, 3211, 0), "Monastery south of Ardougne", "129"),
|
||||
new AnagramClue("MOTHERBOARD", "Brother Omad", new WorldPoint(2606, 3211, 0), "Monastery south of Ardougne", "What is the next number? 12, 13, 15, 17, 111, 113, 117, 119, 123....?", "129"),
|
||||
new AnagramClue("MUS KIL READER", "Radimus Erkle", new WorldPoint(2726, 3368, 0), "Legends' Guild"),
|
||||
new AnagramClue("MY MANGLE LAL", "Lammy Langle", new WorldPoint(1688, 3540, 0), "Hosidius spirit tree patch"),
|
||||
new AnagramClue("NO OWNER", "Oronwen", new WorldPoint(1162, 3178, 0), "Lletya Seamstress shop in Lletya", "20"),
|
||||
new AnagramClue("NOD MED", "Edmond", new WorldPoint(2566, 3332, 0), "Behind the most NW house in East Ardougne", "3"),
|
||||
new AnagramClue("O BIRDZ A ZANY EN PC", "Cap'n Izzy No-Beard", new WorldPoint(2807, 3191, 0), "Brimhaven Agility Arena", "33"),
|
||||
new AnagramClue("OK CO", "Cook", new WorldPoint(3207, 3214, 0), "Ground floor of Lumbridge Castle", "9"),
|
||||
new AnagramClue("NO OWNER", "Oronwen", new WorldPoint(1162, 3178, 0), "Lletya Seamstress shop in Lletya", "What is the minimum amount of quest points required to reach Lletya?", "20"),
|
||||
new AnagramClue("NOD MED", "Edmond", new WorldPoint(2566, 3332, 0), "Behind the most NW house in East Ardougne", "How many pigeon cages are there around the back of Jerico's house?", "3"),
|
||||
new AnagramClue("O BIRDZ A ZANY EN PC", "Cap'n Izzy No-Beard", new WorldPoint(2807, 3191, 0), "Brimhaven Agility Arena", "How many Banana Trees are there in the plantation?", "33"),
|
||||
new AnagramClue("OK CO", "Cook", new WorldPoint(3207, 3214, 0), "Ground floor of Lumbridge Castle", "How many cannons does Lumbridge Castle have?", "9"),
|
||||
new AnagramClue("OR ZINC FUMES WARD", "Wizard Frumscone", new WorldPoint(2594, 3086, 0), "Downstairs in the Wizards' Guild"),
|
||||
new AnagramClue("OUR OWN NEEDS", "Nurse Wooned", new WorldPoint(1575, 3590, 0), "Shayzien Infirmary", "19"),
|
||||
new AnagramClue("PACINNG A TAIE", "Captain Ginea", new WorldPoint(1561, 3602, 0), "Building east of Shayzien combat ring", "113"),
|
||||
new AnagramClue("PEAK REFLEX", "Flax keeper", new WorldPoint(2744, 3444, 0), "Flax field south of Seers Village", "676"),
|
||||
new AnagramClue("OUR OWN NEEDS", "Nurse Wooned", new WorldPoint(1575, 3590, 0), "Shayzien Infirmary", "How many injured soldiers are in this tent?", "19"),
|
||||
new AnagramClue("PACINNG A TAIE", "Captain Ginea", new WorldPoint(1561, 3602, 0), "Building east of Shayzien combat ring", "1 soldier can deal with 6 lizardmen. How many soldiers do we need for an army of 678 lizardmen?", "113"),
|
||||
new AnagramClue("PEAK REFLEX", "Flax keeper", new WorldPoint(2744, 3444, 0), "Flax field south of Seers Village", "If I have 1014 flax, and I spin a third of them into bowstring, how many flax do I have left?", "676"),
|
||||
new AnagramClue("PEATY PERT", "Party Pete", new WorldPoint(3047, 3376, 0), "Falador Party Room"),
|
||||
new AnagramClue("PROFS LOSE WRONG PIE", "Professor Onglewip", new WorldPoint(3113, 3162, 0), "Ground floor of Wizards Tower"),
|
||||
new AnagramClue("QUIT HORRIBLE TYRANT", "Brother Tranquility", new WorldPoint(3681, 2963, 0), "Mos Le'Harmless or Harmony Island", "7"),
|
||||
new AnagramClue("QUE SIR", "Squire", new WorldPoint(2975, 3343, 0), "Falador Castle Courtyard", "654"),
|
||||
new AnagramClue("R AK MI", "Karim", new WorldPoint(3273, 3181, 0), "Al Kharid Kebab shop", "5"),
|
||||
new AnagramClue("RAT MAT WITHIN", "Martin Thwait", new WorldPoint(2906, 3537, 0), "Rogues' Den", "2"),
|
||||
new AnagramClue("QUIT HORRIBLE TYRANT", "Brother Tranquility", new WorldPoint(3681, 2963, 0), "Mos Le'Harmless or Harmony Island", "If I have 49 bottles of rum to share between 7 pirates, how many would each pirate get?", "7"),
|
||||
new AnagramClue("QUE SIR", "Squire", new WorldPoint(2975, 3343, 0), "Falador Castle Courtyard", "White knights are superior to black knights. 2 white knights can handle 3 black knights. How many knights do we need for an army of 981 black knights?", "654"),
|
||||
new AnagramClue("R AK MI", "Karim", new WorldPoint(3273, 3181, 0), "Al Kharid Kebab shop", "I have 16 kebabs, I eat one myself and share the rest equally between 3 friends. How many do they have each?", "5"),
|
||||
new AnagramClue("RAT MAT WITHIN", "Martin Thwait", new WorldPoint(2906, 3537, 0), "Rogues' Den", "How many natural fires burn in Rogue's Den?", "2"),
|
||||
new AnagramClue("RED ART TANS", "Trader Stan", new WorldPoint(3041, 3193, 0), "Port Sarim Charter ship"),
|
||||
new AnagramClue("RATAI", "Taria", new WorldPoint(2940, 3223, 0), "Rimmington bush patch", "7"),
|
||||
new AnagramClue("R SLICER", "Clerris", new WorldPoint(1761, 3850, 0), "Arceuus mine, Zeah", "738"),
|
||||
new AnagramClue("RATAI", "Taria", new WorldPoint(2940, 3223, 0), "Rimmington bush patch", "How many buildings are there in Rimmington?", "7"),
|
||||
new AnagramClue("R SLICER", "Clerris", new WorldPoint(1761, 3850, 0), "Arceuus mine, Zeah", "If I have 1,000 blood runes, and cast 131 ice barrage spells, how many blood runes do I have left?", "738"),
|
||||
new AnagramClue("RIP MAUL", "Primula", new WorldPoint(2454, 2853, 1), "Myth's Guild, first floor"),
|
||||
new AnagramClue("SAND NUT", "Dunstan", new WorldPoint(2919, 3574, 0), "Anvil in north east Burthorpe", "8"),
|
||||
new AnagramClue("SAND NUT", "Dunstan", new WorldPoint(2919, 3574, 0), "Anvil in north east Burthorpe", "How much smithing experience does one receive for smelting a blurite bar?", "8"),
|
||||
new AnagramClue("SEQUIN DIRGE", "Queen Sigrid", new WorldPoint(2612, 3867, 0), "Throne room of Etceteria Castle."),
|
||||
new AnagramClue("SLAM DUSTER GRAIL", "Guildmaster Lars", new WorldPoint(1649, 3498, 0), "Woodcutting guild, Zeah"),
|
||||
new AnagramClue("SLIDE WOMAN", "Wise Old Man", new WorldPoint(3088, 3253, 0), "Draynor Village", "28"),
|
||||
new AnagramClue("SLIDE WOMAN", "Wise Old Man", new WorldPoint(3088, 3253, 0), "Draynor Village", "How many bookcases are in the Wise Old Man's house?", "28"),
|
||||
new AnagramClue("SNAH", "Hans", new WorldPoint(3218, 3219, 0), "Lumbridge Castle courtyard"),
|
||||
new AnagramClue("SNAKES SO I SAIL", "Lisse Isaakson", new WorldPoint(2351, 3801, 0), "Neitiznot", "2"),
|
||||
new AnagramClue("TAMED ROCKS", "Dockmaster", new WorldPoint(1822, 3739, 0), "Port Piscarilius, NE of General store", "5"),
|
||||
new AnagramClue("SNAKES SO I SAIL", "Lisse Isaakson", new WorldPoint(2351, 3801, 0), "Neitiznot", "How many arctic logs are required to make a large fremennik round shield?", "2"),
|
||||
new AnagramClue("TAMED ROCKS", "Dockmaster", new WorldPoint(1822, 3739, 0), "Port Piscarilius, NE of General store", "What is the cube root of 125?", "5"),
|
||||
new AnagramClue("TEN WIGS ON", "Wingstone", new WorldPoint(3389, 2877, 0), "Between Nardah & Agility Pyramid"),
|
||||
new AnagramClue("THEM CAL CAME", "Cam the Camel", new WorldPoint(3300, 3231, 0), "Just outside of the Duel Arena"),
|
||||
new AnagramClue("THICKNO", "Hickton", new WorldPoint(2822, 3442, 0), "Catherby fletching shop", "2"),
|
||||
new AnagramClue("THICKNO", "Hickton", new WorldPoint(2822, 3442, 0), "Catherby fletching shop", "How many ranges are there in Catherby?", "2"),
|
||||
new AnagramClue("TWENTY CURE IRON", "New recruit Tony", new WorldPoint(1498, 3544, 0), "Shayzien Graveyard"),
|
||||
new AnagramClue("UNLEASH NIGHT MIST", "Sigli the Huntsman", new WorldPoint(2660, 3654, 0), "Rellekka", "302"),
|
||||
new AnagramClue("VESTE", "Steve", new WorldPoint(2432, 3423, 0), "Upstairs Wyvern Area or Stronghold Slayer Cave", "2"),
|
||||
new AnagramClue("VEIL VEDA", "Evil Dave", new WorldPoint(3079, 9892, 0), "Doris' basement, Edgeville", "666"),
|
||||
new AnagramClue("WOO AN EGG KIWI", "Awowogei", ObjectID.AWOWOGEI, new WorldPoint(2802, 2765, 0), "Ape Atoll", "24"),
|
||||
new AnagramClue("UNLEASH NIGHT MIST", "Sigli the Huntsman", new WorldPoint(2660, 3654, 0), "Rellekka", "What is the combined slayer requirement of every monster in the slayer cave?", "302"),
|
||||
new AnagramClue("VESTE", "Steve", new WorldPoint(2432, 3423, 0), "Upstairs Wyvern Area or Stronghold Slayer Cave", "How many farming patches are there in Gnome stronghold?", "2"),
|
||||
new AnagramClue("VEIL VEDA", "Evil Dave", new WorldPoint(3079, 9892, 0), "Doris' basement, Edgeville", "What is 333 multiplied by 2?", "666"),
|
||||
new AnagramClue("WOO AN EGG KIWI", "Awowogei", ObjectID.AWOWOGEI, new WorldPoint(2802, 2765, 0), "Ape Atoll", "If I have 303 bananas, and share them between 31 friends evenly, only handing out full bananas. How many will I have left over?", "24"),
|
||||
new AnagramClue("YAWNS GY", "Ysgawyn", new WorldPoint(2340, 3167, 0), "Lletya"),
|
||||
new AnagramClue("MAJORS LAVA BADS AIR", "Ambassador Alvijar", new WorldPoint(2736, 5351, 1), "Dorgesh-Kaan, NE Middle Level", "2505"),
|
||||
new AnagramClue("MAJORS LAVA BADS AIR", "Ambassador Alvijar", new WorldPoint(2736, 5351, 1), "Dorgesh-Kaan, NE Middle Level", "Double the miles before the initial Dorgeshuun veteran.", "2505"),
|
||||
new AnagramClue("AN EARL", "Ranael", new WorldPoint(3315, 3163, 0), "Al Kharid skirt shop"),
|
||||
new AnagramClue("CARPET AHOY", "Apothecary", new WorldPoint(3195, 3404, 0), "Southwest Varrock"),
|
||||
new AnagramClue("DISORDER", "Sedridor", new WorldPoint(3102, 9570, 0), "Wizards' Tower basement"),
|
||||
@@ -163,7 +163,7 @@ public class AnagramClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new AnagramClue("RUG DETER", "Gertrude", new WorldPoint(3151, 3412, 0), "West of Varrock, south of the Cooks' Guild"),
|
||||
new AnagramClue("SIR SHARE RED", "Hairdresser", new WorldPoint(2944, 3381, 0), "Western Falador"),
|
||||
new AnagramClue("TAUNT ROOF", "Fortunato", new WorldPoint(3080, 3250, 0), "Draynor Village Market"),
|
||||
new AnagramClue("HICK JET", "Jethick", new WorldPoint(2541, 3305, 0), "West Ardougne", "38"),
|
||||
new AnagramClue("HICK JET", "Jethick", new WorldPoint(2541, 3305, 0), "West Ardougne", "How many graves are there in the city graveyard?", "38"),
|
||||
new AnagramClue("RUE GO", "Goreu", new WorldPoint(2335, 3162, 0), "Lletya")
|
||||
);
|
||||
|
||||
@@ -171,27 +171,29 @@ public class AnagramClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
private final String npc;
|
||||
private final WorldPoint location;
|
||||
private final String area;
|
||||
private final String question;
|
||||
private final String answer;
|
||||
private int objectId;
|
||||
|
||||
private AnagramClue(String text, String npc, WorldPoint location, String area)
|
||||
{
|
||||
this(text, npc, location, area, null);
|
||||
this(text, npc, location, area, "", null);
|
||||
}
|
||||
|
||||
private AnagramClue(String text, String npc, WorldPoint location, String area, String answer)
|
||||
private AnagramClue(String text, String npc, WorldPoint location, String area, String question, String answer)
|
||||
{
|
||||
this.text = text;
|
||||
this.npc = npc;
|
||||
this.location = location;
|
||||
this.area = area;
|
||||
this.question = question;
|
||||
this.answer = answer;
|
||||
this.objectId = -1;
|
||||
}
|
||||
|
||||
private AnagramClue(String text, String npc, int objectId, WorldPoint location, String area, String answer)
|
||||
private AnagramClue(String text, String npc, int objectId, WorldPoint location, String area, String question, String answer)
|
||||
{
|
||||
this(text, npc, location, area, answer);
|
||||
this(text, npc, location, area, question, answer);
|
||||
this.objectId = objectId;
|
||||
}
|
||||
|
||||
@@ -257,7 +259,9 @@ public class AnagramClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
{
|
||||
for (AnagramClue clue : CLUES)
|
||||
{
|
||||
if (text.equalsIgnoreCase(ANAGRAM_TEXT + clue.text) || text.equalsIgnoreCase(ANAGRAM_TEXT_BEGINNER + clue.text))
|
||||
if (text.equalsIgnoreCase(ANAGRAM_TEXT + clue.text)
|
||||
|| text.equalsIgnoreCase(ANAGRAM_TEXT_BEGINNER + clue.text)
|
||||
|| text.equalsIgnoreCase(clue.question))
|
||||
{
|
||||
return clue;
|
||||
}
|
||||
|
||||
@@ -43,35 +43,42 @@ import net.runelite.client.ui.overlay.components.TitleComponent;
|
||||
public class CipherClue extends ClueScroll implements TextClueScroll, NpcClueScroll, LocationClueScroll
|
||||
{
|
||||
private static final Set<CipherClue> CLUES = ImmutableSet.of(
|
||||
new CipherClue("BMJ UIF LFCBC TFMMFS", "Ali the Kebab seller", new WorldPoint(3354, 2974, 0), "Pollnivneach", "399"),
|
||||
new CipherClue("GUHCHO", "Drezel", new WorldPoint(3440, 9895, 0), "Paterdomus", "7"),
|
||||
new CipherClue("ZCZL", "Adam", new WorldPoint(3227, 3227, 0), "Outside Lumbridge castle", "666"),
|
||||
new CipherClue("ZHLUG ROG PDQ", "Weird Old Man", new WorldPoint(3224, 3112, 0), "Kalphite Lair entrance. Fairy ring BIQ", "150"),
|
||||
new CipherClue("ECRVCKP MJCNGF", "Captain Khaled", new WorldPoint(1845, 3754, 0), "Large eastern building in Port Piscarilius", "5"),
|
||||
new CipherClue("OVEXON", "Eluned", new WorldPoint(2289, 3144, 0), "Outside Lletya", "53,000"),
|
||||
new CipherClue("VTYR APCNTGLW", "King Percival", new WorldPoint(2634, 4682, 1), "Fisher Realm, first floor. Fairy ring BJR", "5"),
|
||||
new CipherClue("UZZU MUJHRKYYKJ", "Otto Godblessed", new WorldPoint(2501, 3487, 0), "Otto's Grotto", "3"),
|
||||
new CipherClue("USBJCPSO", "Traiborn", new WorldPoint(3112, 3162, 0), "First floor of Wizards Tower", "3150"),
|
||||
new CipherClue("HCKTA IQFHCVJGT", "Fairy Godfather", new WorldPoint(2446, 4428, 0), "Zanaris throne room", "64"),
|
||||
new CipherClue("ZSBKDO ZODO", "Pirate Pete", new WorldPoint(3680, 3537, 0), "Dock northeast of the Ectofunctus", "Puzzle"),
|
||||
new CipherClue("GBJSZ RVFFO", "Fairy Queen", new WorldPoint(2347, 4435, 0), "Fairy Resistance Hideout", "Puzzle"),
|
||||
new CipherClue("QSPGFTTPS HSBDLMFCPOF", "Professor Gracklebone", new WorldPoint(1625, 3802, 0), "Ground floor of Arceuus Library", "9"),
|
||||
new CipherClue("IWPPLQTP", "Gunnjorn", new WorldPoint(2541, 3548, 0), "Barbarian Outpost Agility course", "Puzzle"),
|
||||
new CipherClue("BSOPME MZETQPS", "Arnold Lydspor", new WorldPoint(2329, 3689, 0), "Piscatoris Fishing Colony general store/bank", "Puzzle")
|
||||
new CipherClue("BMJ UIF LFCBC TFMMFS", "Ali the Kebab seller", new WorldPoint(3354, 2974, 0), "Pollnivneach", "How many coins would you need to purchase 133 kebabs from me?", "399"),
|
||||
new CipherClue("GUHCHO", "Drezel", new WorldPoint(3440, 9895, 0), "Paterdomus", "Please solve this for x: 7x - 28=21", "7"),
|
||||
new CipherClue("ZCZL", "Adam", new WorldPoint(3227, 3227, 0), "Outside Lumbridge castle", "How many snakeskins are needed in order to craft 44 boots, 29 vambraces and 34 bandanas?", "666"),
|
||||
new CipherClue("ZHLUG ROG PDQ", "Weird Old Man", new WorldPoint(3224, 3112, 0), "Kalphite Lair entrance. Fairy ring BIQ", "SIX LEGS! All of them have 6! There are 25 of them! How many legs?", "150"),
|
||||
new CipherClue("ECRVCKP MJCNGF", "Captain Khaled", new WorldPoint(1845, 3754, 0), "Large eastern building in Port Piscarilius", "How many fishing cranes can you find around here?", "5"),
|
||||
new CipherClue("OVEXON", "Eluned", new WorldPoint(2289, 3144, 0), "Outside Lletya", "A question on elven crystal math. I have 5 and 3 crystals, large and small respectively. A large crystal is worth 10,000 coins and a small is worth but 1,000. How much are all my crystals worth?", "53,000"),
|
||||
new CipherClue("VTYR APCNTGLW", "King Percival", new WorldPoint(2634, 4682, 1), "Fisher Realm, first floor. Fairy ring BJR", "How many cannons are on this here castle?", "5"),
|
||||
new CipherClue("UZZU MUJHRKYYKJ", "Otto Godblessed", new WorldPoint(2501, 3487, 0), "Otto's Grotto", "How many pyre sites are found around this lake?", "3"),
|
||||
new CipherClue("USBJCPSO", "Traiborn", new WorldPoint(3112, 3162, 0), "First floor of Wizards Tower", "How many air runes would I need to cast 630 wind waves?", "3150"),
|
||||
new CipherClue("HCKTA IQFHCVJGT", "Fairy Godfather", new WorldPoint(2446, 4428, 0), "Zanaris throne room", "There are 3 inputs and 4 letters on each ring How many total individual fairy ring codes are possible?", "64"),
|
||||
new CipherClue("ZSBKDO ZODO", "Pirate Pete", new WorldPoint(3680, 3537, 0), "Dock northeast of the Ectofunctus"),
|
||||
new CipherClue("GBJSZ RVFFO", "Fairy Queen", new WorldPoint(2347, 4435, 0), "Fairy Resistance Hideout"),
|
||||
new CipherClue("QSPGFTTPS HSBDLMFCPOF", "Professor Gracklebone", new WorldPoint(1625, 3802, 0), "Ground floor of Arceuus Library", "How many round tables can be found on this floor of the library?", "9"),
|
||||
new CipherClue("IWPPLQTP", "Gunnjorn", new WorldPoint(2541, 3548, 0), "Barbarian Outpost Agility course"),
|
||||
new CipherClue("BSOPME MZETQPS", "Arnold Lydspor", new WorldPoint(2329, 3689, 0), "Piscatoris Fishing Colony general store/bank")
|
||||
);
|
||||
|
||||
private String text;
|
||||
private String npc;
|
||||
private WorldPoint location;
|
||||
private String area;
|
||||
private String question;
|
||||
private String answer;
|
||||
|
||||
private CipherClue(String text, String npc, WorldPoint location, String area, String answer)
|
||||
private CipherClue(String text, String npc, WorldPoint location, String area)
|
||||
{
|
||||
this(text, npc, location, area, "", null);
|
||||
}
|
||||
|
||||
private CipherClue(String text, String npc, WorldPoint location, String area, String question, String answer)
|
||||
{
|
||||
this.text = "The cipher reveals who to speak to next: " + text;
|
||||
this.npc = npc;
|
||||
this.location = location;
|
||||
this.area = area;
|
||||
this.question = question;
|
||||
this.answer = answer;
|
||||
}
|
||||
|
||||
@@ -122,7 +129,7 @@ public class CipherClue extends ClueScroll implements TextClueScroll, NpcClueScr
|
||||
{
|
||||
for (CipherClue clue : CLUES)
|
||||
{
|
||||
if (clue.text.equalsIgnoreCase(text))
|
||||
if (clue.text.equalsIgnoreCase(text) || clue.question.equalsIgnoreCase(text))
|
||||
{
|
||||
return clue;
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
|
||||
.put(new WorldPoint(2383, 3370, 0), "West of the outpost")
|
||||
.put(new WorldPoint(3312, 3375, 0), "North-west of Exam Centre, on the hill.")
|
||||
.put(new WorldPoint(3121, 3384, 0), "North-east of Draynor Manor, near River Lum.")
|
||||
.put(new WorldPoint(3430, 3388, 0), "West of Mort Myre Swamp.")
|
||||
.put(new WorldPoint(3430, 3388, 0), "West of Mort Myre Swamp (BKR).")
|
||||
.put(new WorldPoint(2920, 3403, 0), "South-east of Taverley, near Lady of the Lake.")
|
||||
.put(new WorldPoint(2594, 2899, 0), "South-east of Feldip Hills, by the crimson swifts (AKS).")
|
||||
.put(new WorldPoint(2387, 3435, 0), "West of Tree Gnome Stronghold, near the pen containing terrorbirds.")
|
||||
@@ -71,21 +71,21 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
|
||||
.put(new WorldPoint(2381, 3468, 0), "West of Tree Gnome Stronghold, north of the pen with terrorbirds.")
|
||||
.put(new WorldPoint(3005, 3475, 0), "Ice Mountain, west of Edgeville.")
|
||||
.put(new WorldPoint(2585, 3505, 0), "By the shore line north of the Coal Trucks.")
|
||||
.put(new WorldPoint(3443, 3515, 0), "South of Slayer Tower.")
|
||||
.put(new WorldPoint(3443, 3515, 0), "South of Slayer Tower (CKS).")
|
||||
.put(new WorldPoint(2416, 3516, 0), "Tree Gnome Stronghold, west of Grand Tree, near swamp.")
|
||||
.put(new WorldPoint(3429, 3523, 0), "South of Slayer Tower.")
|
||||
.put(new WorldPoint(2363, 3531, 0), "North-east of Eagles' Peak.")
|
||||
.put(new WorldPoint(3429, 3523, 0), "South of Slayer Tower (CKS).")
|
||||
.put(new WorldPoint(2363, 3531, 0), "North-east of Eagles' Peak (AKQ).")
|
||||
.put(new WorldPoint(2919, 3535, 0), "East of Burthorpe pub.")
|
||||
.put(new WorldPoint(3548, 3560, 0), "Inside Fenkenstrain's Castle.")
|
||||
.put(new WorldPoint(1456, 3620, 0), "Graveyard west of Shayzien (DJR).")
|
||||
.put(new WorldPoint(2735, 3638, 0), "East of Rellekka, north-west of Golden Apple Tree (AJR).")
|
||||
.put(new WorldPoint(2681, 3653, 0), "Rellekka, in the garden of the south-east house.")
|
||||
.put(new WorldPoint(2537, 3881, 0), "Miscellania.")
|
||||
.put(new WorldPoint(2537, 3881, 0), "Miscellania (CIP).")
|
||||
.put(new WorldPoint(2828, 3234, 0), "Southern coast of Crandor.")
|
||||
.put(new WorldPoint(1247, 3726, 0), "Just inside the Farming Guild")
|
||||
.put(new WorldPoint(3770, 3898, 0), "On the small island north-east of Fossil Island's mushroom forest.")
|
||||
// Hard
|
||||
.put(new WorldPoint(2209, 3161, 0), "North-east of Tyras Camp.")
|
||||
.put(new WorldPoint(2209, 3161, 0), "North-east of Tyras Camp (BJS).")
|
||||
.put(new WorldPoint(2181, 3206, 0), "South of Elf Camp.")
|
||||
.put(new WorldPoint(3081, 3209, 0), "Small Island (CLP).")
|
||||
.put(new WorldPoint(3374, 3250, 0), "Duel Arena combat area.")
|
||||
@@ -98,12 +98,12 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
|
||||
.put(new WorldPoint(2581, 3030, 0), "Gu'Tanoth island, enter cave north-west of Feldip Hills (AKS).")
|
||||
.put(new WorldPoint(2961, 3024, 0), "Ship yard (DKP).")
|
||||
.put(new WorldPoint(2339, 3311, 0), "East of Prifddinas on Arandar mountain pass.")
|
||||
.put(new WorldPoint(3440, 3341, 0), "Nature Spirit's grotto.")
|
||||
.put(new WorldPoint(2763, 2974, 0), "Cairn Isle, west of Shilo Village.")
|
||||
.put(new WorldPoint(3440, 3341, 0), "Nature Spirit's grotto (BIP).")
|
||||
.put(new WorldPoint(2763, 2974, 0), "Cairn Isle, west of Shilo Village (CKR).")
|
||||
.put(new WorldPoint(3138, 2969, 0), "West of Bandit Camp in Kharidian Desert.")
|
||||
.put(new WorldPoint(2924, 2963, 0), "On the southern part of eastern Karamja.")
|
||||
.put(new WorldPoint(2838, 2914, 0), "Kharazi Jungle, near water pool.")
|
||||
.put(new WorldPoint(3441, 3419, 0), "Mort Myre Swamp.")
|
||||
.put(new WorldPoint(2838, 2914, 0), "Kharazi Jungle, near water pool (CKR).")
|
||||
.put(new WorldPoint(3441, 3419, 0), "Mort Myre Swamp (BKR).")
|
||||
.put(new WorldPoint(2950, 2902, 0), "South-east of Kharazi Jungle.")
|
||||
.put(new WorldPoint(2775, 2891, 0), "South-west of Kharazi Jungle.")
|
||||
.put(new WorldPoint(3113, 3602, 0), "Wilderness. North of Edgeville (level 11).")
|
||||
@@ -113,8 +113,8 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
|
||||
.put(new WorldPoint(3305, 3692, 0), "Wilderness. West of eastern green dragon.")
|
||||
.put(new WorldPoint(3055, 3696, 0), "Wilderness. Bandit Camp.")
|
||||
.put(new WorldPoint(3302, 3696, 0), "Wilderness. West of eastern green dragon.")
|
||||
.put(new WorldPoint(1479, 3696, 0), "Lizardman Canyon.")
|
||||
.put(new WorldPoint(2712, 3732, 0), "North-east of Rellekka.")
|
||||
.put(new WorldPoint(1479, 3696, 0), "Lizardman Canyon (DJR).")
|
||||
.put(new WorldPoint(2712, 3732, 0), "North-east of Rellekka (DKS).")
|
||||
.put(new WorldPoint(2970, 3749, 0), "Wilderness. Forgotten Cemetery.")
|
||||
.put(new WorldPoint(3094, 3764, 0), "Wilderness. Mining site north of Bandit Camp.")
|
||||
.put(new WorldPoint(3311, 3769, 0), "Wilderness. North of Venenatis.")
|
||||
@@ -168,6 +168,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
|
||||
.put(new WorldPoint(3051, 3736, 0), "East of the Wilderness Obelisk in 28 Wilderness.")
|
||||
.put(new WorldPoint(2316, 3814, 0), "West of Neitiznot, near the bridge.")
|
||||
.put(new WorldPoint(2872, 3937, 0), "Weiss.")
|
||||
.put(new WorldPoint(2484, 4016, 0), "Northeast corner of the Island of Stone.")
|
||||
// Master
|
||||
.put(new WorldPoint(2178, 3209, 0), "South of Elf Camp.")
|
||||
.put(new WorldPoint(2155, 3100, 0), "South of Port Tyras (BJS).")
|
||||
@@ -187,7 +188,7 @@ public class CoordinateClue extends ClueScroll implements TextClueScroll, Locati
|
||||
.put(new WorldPoint(1698, 3792, 0), "Arceuus church.")
|
||||
.put(new WorldPoint(2951, 3820, 0), "Wilderness. Chaos Temple (level 38).")
|
||||
.put(new WorldPoint(2202, 3825, 0), "Pirates' Cove, between Lunar Isle and Rellekka.")
|
||||
.put(new WorldPoint(1761, 3853, 0), "Arceuus essence mine.")
|
||||
.put(new WorldPoint(1761, 3853, 0), "Arceuus essence mine (CIS).")
|
||||
.put(new WorldPoint(2090, 3863, 0), "South of Lunar Isle, west of Astral altar.")
|
||||
.put(new WorldPoint(1442, 3878, 0), "Sulphur Mine.")
|
||||
.put(new WorldPoint(3380, 3929, 0), "Wilderness. Near Volcano.")
|
||||
|
||||
@@ -61,7 +61,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new CrypticClue("Search the crates in a bank in Varrock.", CRATE_5107, new WorldPoint(3187, 9825, 0), "Search in the basement of the West Varrock bank."),
|
||||
new CrypticClue("Falo the bard wants to see you.", "Falo the Bard", new WorldPoint(2689, 3550, 0), "Speak to Falo the Bard located between Seer's Village and Rellekka. Southwest of fairy ring CJR."),
|
||||
new CrypticClue("Search a bookcase in the Wizards tower.", BOOKCASE_12539, new WorldPoint(3113, 3159, 0), "The bookcase located on the ground floor."),
|
||||
new CrypticClue("Come have a cip with this great soot covered denizen.", "Miner Magnus", new WorldPoint(2527, 3891, 0), "Talk to Miner Magnus east of the fairy ring CIP. Answer: 8"),
|
||||
new CrypticClue("Come have a cip with this great soot covered denizen.", "Miner Magnus", new WorldPoint(2527, 3891, 0), "Talk to Miner Magnus east of the fairy ring CIP. Answer: 8", "How many coal rocks are around here?"),
|
||||
new CrypticClue("Citric cellar.", "Heckel Funch", new WorldPoint(2490, 3488, 0), "Speak to Heckel Funch on the first floor in the Grand Tree."),
|
||||
new CrypticClue("I burn between heroes and legends.", "Candle maker", new WorldPoint(2799, 3438, 0), "Speak to the Candle maker in Catherby."),
|
||||
new CrypticClue("Speak to Sarah at Falador farm.", "Sarah", new WorldPoint(3038, 3292, 0), "Talk to Sarah at Falador farm, north of Port Sarim."),
|
||||
@@ -110,7 +110,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new CrypticClue("Dig between some ominous stones in Falador.", new WorldPoint(3040, 3399, 0), "Three standing stones inside a walled area. East of the northern Falador gate."),
|
||||
new CrypticClue("Speak to Rusty north of Falador.", "Rusty", new WorldPoint(2979, 3435, 0), "Rusty can be found northeast of Falador on the way to the Mind altar."),
|
||||
new CrypticClue("Search a wardrobe in Draynor.", WARDROBE_5622, new WorldPoint(3087, 3261, 0), "Go to Aggie's house and search the wardrobe in northern wall."),
|
||||
new CrypticClue("I have many arms but legs, I have just one. I have little family but my seed you can grow on, I am not dead, yet I am but a spirit, and my power, on your quests, you will earn the right to free it.", NULL_1293, new WorldPoint(2544, 3170, 0), "Spirit Tree in Tree Gnome Village. Answer: 13112221"),
|
||||
new CrypticClue("I have many arms but legs, I have just one. I have little family but my seed you can grow on, I am not dead, yet I am but a spirit, and my power, on your quests, you will earn the right to free it.", NULL_1293, new WorldPoint(2544, 3170, 0), "Spirit Tree in Tree Gnome Village. Answer: 13112221", "What is the next number in the sequence? 1, 11, 21, 1211, 111221, 312211"),
|
||||
new CrypticClue("I am the one who watches the giants. The giants in turn watch me. I watch with two while they watch with one. Come seek where I may be.", "Kamfreena", new WorldPoint(2845, 3539, 0), "Speak to Kamfreena on the top floor of the Warriors' Guild."),
|
||||
new CrypticClue("In a town where wizards are known to gather, search upstairs in a large house to the north.", "Man", 375, new WorldPoint(2593, 3108, 1), "Search the chest upstairs in the house north of Yanille Wizard's Guild. Kill a man for the key."),
|
||||
new CrypticClue("Probably filled with wizards socks.", "Wizard", DRAWERS_350, new WorldPoint(3116, 9562, 0), "Search the drawers in the basement of the Wizard's Tower south of Draynor Village. Kill one of the Wizards for the key. Fairy ring DIS"),
|
||||
@@ -138,7 +138,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new CrypticClue("46 is my number. My body is the colour of burnt orange and crawls among those with eight. Three mouths I have, yet I cannot eat. My blinking blue eye hides my grave.", new WorldPoint(3170, 3885, 0), "Sapphire respawn in the Spider's Nest, lvl 46 Wilderness. Dig under the sapphire spawn."),
|
||||
new CrypticClue("Green is the colour of my death as the winter-guise, I swoop towards the ground.", new WorldPoint(2780, 3783, 0), "Players need to slide down to where Trollweiss grows on Trollweiss Mountain."),
|
||||
new CrypticClue("Talk to a party-goer in Falador.", "Lucy", new WorldPoint(3046, 3382, 0), "Lucy is the bartender on the first floor of the party room."),
|
||||
new CrypticClue("He knows just how easy it is to lose track of time.", "Brother Kojo", new WorldPoint(2570, 3250, 0), "Speak to Brother Kojo in the Clock Tower. Answer: 22"),
|
||||
new CrypticClue("He knows just how easy it is to lose track of time.", "Brother Kojo", new WorldPoint(2570, 3250, 0), "Speak to Brother Kojo in the Clock Tower. Answer: 22", "On a clock, how many times a day do the minute hand and the hour hand overlap?"),
|
||||
new CrypticClue("A great view - watch the rapidly drying hides get splashed. Check the box you are sitting on.", BOXES, new WorldPoint(2523, 3493, 1), "Almera's House north of Baxtorian Falls, search boxes on the first floor."),
|
||||
new CrypticClue("Search the Coffin in Edgeville.", COFFIN, new WorldPoint(3091, 3477, 0), "Search the coffin located by the Wilderness teleport lever."),
|
||||
new CrypticClue("When no weapons are at hand, then is the time to reflect. In Saradomin's name, redemption draws closer...", DRAWERS_350, new WorldPoint(2818, 3351, 0), "On Entrana, search the southern drawer in the house with the cooking range."),
|
||||
@@ -211,7 +211,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new CrypticClue("Great demons, dragons and spiders protect this blue rock, beneath which, you may find what you seek.", new WorldPoint(3045, 10265, 0), "Dig by the runite rock in the Lava Maze Dungeon"),
|
||||
new CrypticClue("My giant guardians below the market streets would be fans of rock and roll, if only they could grab hold of it. Dig near my green bubbles!", new WorldPoint(3161, 9904, 0), "Dig near the cauldron by Moss Giants under Varrock Sewers"),
|
||||
new CrypticClue("Varrock is where I reside, not the land of the dead, but I am so old, I should be there instead. Let's hope your reward is as good as it says, just 1 gold one and you can have it read.", "Gypsy Aris", new WorldPoint(3203, 3424, 0), "Talk to Gypsy Aris, West of varrock main square."),
|
||||
new CrypticClue("Speak to a referee.", "Gnome ball referee", new WorldPoint(2386, 3487, 0), "Talk to a Gnome ball referee found on the Gnome ball field in the Gnome Stronghold. Answer: 5096"),
|
||||
new CrypticClue("Speak to a referee.", "Gnome ball referee", new WorldPoint(2386, 3487, 0), "Talk to a Gnome ball referee found on the Gnome ball field in the Gnome Stronghold. Answer: 5096", "What is 57 x 89 + 23?"),
|
||||
new CrypticClue("This crate holds a better reward than a broken arrow.", CRATE_356, new WorldPoint(2671, 3437, 0), "Inside the Ranging Guild. Search the crate behind the northern most building."),
|
||||
new CrypticClue("Search the drawers in the house next to the Port Sarim mage shop.", DRAWERS, new WorldPoint(3024, 3259, 0), "House east of Betty's. Contains a cooking sink."),
|
||||
new CrypticClue("With a name like that, you'd expect a little more than just a few scimitars.", "Daga", new WorldPoint(2759, 2775, 0), "Speak to Daga on Ape Atoll."),
|
||||
@@ -300,7 +300,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new CrypticClue("Search the open crate found in the Hosidius kitchens.", CRATE_27533, new WorldPoint(1683, 3616, 0), "The kitchens are north-west of the town in Hosidius."),
|
||||
new CrypticClue("Dig under Ithoi's cabin.", new WorldPoint(2529, 2838, 0), "Dig under Ithoi's cabin in the Corsair Cove."),
|
||||
new CrypticClue("Search the drawers, upstairs in the bank to the East of Varrock.", DRAWERS_7194, new WorldPoint(3250, 3420, 1), "Search the drawers upstairs in Varrock east bank."),
|
||||
new CrypticClue("Speak to Hazelmere.", "Hazelmere", new WorldPoint(2677, 3088, 1), "Located upstairs in the house to the north of fairy ring CLS. Answer: 6859"),
|
||||
new CrypticClue("Speak to Hazelmere.", "Hazelmere", new WorldPoint(2677, 3088, 1), "Located upstairs in the house to the north of fairy ring CLS. Answer: 6859", "What is 19 to the power of 3?"),
|
||||
new CrypticClue("The effects of this fire are magnified.", new WorldPoint(1179, 3626, 0), "Dig by the fire beside Ket'sal K'uk in the westernmost part of the Kebos Swamp. "),
|
||||
new CrypticClue("Always walking around the castle grounds and somehow knows everyone's age.", "Hans", new WorldPoint(3221, 3218, 0), "Talk to Hans walking around Lumbridge Castle."),
|
||||
new CrypticClue("In the place Duke Horacio calls home, talk to a man with a hat dropped by goblins.", "Cook", new WorldPoint(3208, 3213, 0), "Talk to the Cook in Lumbridge Castle."),
|
||||
@@ -311,7 +311,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
new CrypticClue("Search the eastern bookcase in Father Urhney's house.", BOOKCASE_9523, new WorldPoint(3149, 3177, 0), "Father Urhney's house is found in the western end of the Lumbridge Swamp."),
|
||||
new CrypticClue("Talk to Morgan in his house at Draynor Village.", "Morgan", new WorldPoint(3098, 3268, 0), "Morgan can be found in the house with the quest start map icon."),
|
||||
new CrypticClue("Talk to Charles at Port Piscarilius.", "Charles", new WorldPoint(1821, 3690, 0), "Charles is found by Veos' ship in Port Piscarilius."),
|
||||
new CrypticClue("Search the crate in Rommiks crafting shop in Rimmington.", CRATE_9534, new WorldPoint(2947, 3208, 0), "The crates in Rommik's Crafty Supplies in Rimmington."),
|
||||
new CrypticClue("Search the crate in Rommiks crafting shop in Rimmington.", CRATE_9533, new WorldPoint(2946, 3207, 0), "The crates in Rommik's Crafty Supplies in Rimmington."),
|
||||
new CrypticClue("Talk to Ali the Leaflet Dropper north of the Al Kharid mine.", "Ali the Leaflet Dropper", new WorldPoint(3283, 3329, 0), "Ali the Leaflet Dropper can be found roaming north of the Al Kharid mine."),
|
||||
new CrypticClue("Talk to the cook in the Blue Moon Inn in Varrock.", "Cook", new WorldPoint(3230, 3401, 0), "The Blue Moon Inn can be found by the southern entrance to Varrock."),
|
||||
new CrypticClue("Search the single crate in Horvik's smithy in Varrock.", CRATE_5106, new WorldPoint(3228, 3433, 0), "Horvik's Smithy is found north-east of of Varrock Square."),
|
||||
@@ -331,6 +331,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
private final int objectId;
|
||||
private final WorldPoint location;
|
||||
private final String solution;
|
||||
private final String questionText;
|
||||
|
||||
private CrypticClue(String text, WorldPoint location, String solution)
|
||||
{
|
||||
@@ -339,21 +340,37 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
|
||||
private CrypticClue(String text, int objectId, WorldPoint location, String solution)
|
||||
{
|
||||
this(text, null, objectId, location, solution);
|
||||
this(text, null, objectId, location, solution, "");
|
||||
}
|
||||
|
||||
private CrypticClue(String text, String npc, WorldPoint location, String solution)
|
||||
{
|
||||
this(text, npc, -1, location, solution);
|
||||
this(text, npc, -1, location, solution, "");
|
||||
}
|
||||
|
||||
private CrypticClue(String text, int objectId, WorldPoint location, String solution, String questionText)
|
||||
{
|
||||
this(text, null, objectId, location, solution, questionText);
|
||||
}
|
||||
|
||||
private CrypticClue(String text, String npc, WorldPoint location, String solution, String questionText)
|
||||
{
|
||||
this(text, npc, -1, location, solution, questionText);
|
||||
}
|
||||
|
||||
private CrypticClue(String text, String npc, int objectId, WorldPoint location, String solution)
|
||||
{
|
||||
this(text, npc, objectId, location, solution, "");
|
||||
}
|
||||
|
||||
private CrypticClue(String text, String npc, int objectId, WorldPoint location, String solution, String questionText)
|
||||
{
|
||||
this.text = text;
|
||||
this.npc = npc;
|
||||
this.objectId = objectId;
|
||||
this.location = location;
|
||||
this.solution = solution;
|
||||
this.questionText = questionText;
|
||||
setRequiresSpade(getLocation() != null && getNpc() == null && objectId == -1);
|
||||
}
|
||||
|
||||
@@ -442,7 +459,7 @@ public class CrypticClue extends ClueScroll implements TextClueScroll, NpcClueSc
|
||||
{
|
||||
for (CrypticClue clue : CLUES)
|
||||
{
|
||||
if (clue.text.equalsIgnoreCase(text))
|
||||
if (clue.text.equalsIgnoreCase(text) || clue.questionText.equalsIgnoreCase(text))
|
||||
{
|
||||
return clue;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ public class EmoteClue extends ClueScroll implements TextClueScroll, LocationClu
|
||||
new EmoteClue("Laugh at the crossroads south of the Sinclair Mansion. Equip a cowl, a blue wizard robe top and an iron scimitar.", "Sinclair Mansion", ROAD_JUNCTION_SOUTH_OF_SINCLAIR_MANSION, new WorldPoint(2741, 3536, 0), LAUGH, item(LEATHER_COWL), item(BLUE_WIZARD_ROBE), item(IRON_SCIMITAR)),
|
||||
new EmoteClue("Laugh in front of the gem store in Ardougne market. Equip a Castlewars bracelet, a dragonstone amulet and a ring of forging.", "Ardougne", NEAR_THE_GEM_STALL_IN_ARDOUGNE_MARKET, new WorldPoint(2666, 3304, 0), LAUGH, any("Castle wars bracelet", range(CASTLE_WARS_BRACELET3, CASTLE_WARS_BRACELET1)), item(DRAGONSTONE_AMULET), item(RING_OF_FORGING)),
|
||||
new EmoteClue("Panic in the Limestone Mine. Equip bronze platelegs, a steel pickaxe and a steel medium helmet.", "Limestone Mine", LIMESTONE_MINE, new WorldPoint(3372, 3498, 0), PANIC, item(BRONZE_PLATELEGS), item(STEEL_PICKAXE), item(STEEL_MED_HELM)),
|
||||
new EmoteClue("Panic by the mausoleum in Morytania. Wave before you speak to me. Equip a mithril plate skirt, a maple longbow and no boots.", "Morytania", MAUSOLEUM_OFF_THE_MORYTANIA_COAST, new WorldPoint(3504, 3576, 0), PANIC, WAVE, item(MITHRIL_PLATESKIRT), item(MAPLE_LONGBOW), emptySlot("No boots", BOOTS)),
|
||||
new EmoteClue("Panic by the mausoleum in Morytania. Wave before you speak to me. Equip a mithril plate skirt, a maple longbow and no boots.", "Morytania mausoleum, access via the experiments cave", MAUSOLEUM_OFF_THE_MORYTANIA_COAST, new WorldPoint(3504, 3576, 0), PANIC, WAVE, item(MITHRIL_PLATESKIRT), item(MAPLE_LONGBOW), emptySlot("No boots", BOOTS)),
|
||||
new EmoteClue("Panic on the Wilderness volcano bridge. Beware of double agents! Equip any headband and crozier.", "Wilderness volcano", VOLCANO_IN_THE_NORTHEASTERN_WILDERNESS, new WorldPoint(3368, 3935, 0), PANIC, any("Any headband", range(RED_HEADBAND, BROWN_HEADBAND), range(WHITE_HEADBAND, GREEN_HEADBAND)), any("Any crozier", item(ANCIENT_CROZIER), item(ARMADYL_CROZIER), item(BANDOS_CROZIER), range(SARADOMIN_CROZIER, ZAMORAK_CROZIER))),
|
||||
new EmoteClue("Panic by the pilot on White Wolf Mountain. Beware of double agents! Equip mithril platelegs, a ring of life and a rune axe.", "White Wolf Mountain", GNOME_GLIDER_ON_WHITE_WOLF_MOUNTAIN, new WorldPoint(2847, 3499, 0), PANIC, item(MITHRIL_PLATELEGS), item(RING_OF_LIFE), item(RUNE_AXE)),
|
||||
new EmoteClue("Panic by the big egg where no one dare goes and the ground is burnt. Beware of double agents! Equip a dragon med helm, a TokTz-Ket-Xil, a brine sabre, rune platebody and an uncharged amulet of glory.", "Lava dragon isle", SOUTHEAST_CORNER_OF_LAVA_DRAGON_ISLE, new WorldPoint(3227, 3831, 0), PANIC, item(DRAGON_MED_HELM), item(TOKTZKETXIL), item(BRINE_SABRE), item(RUNE_PLATEBODY), item(AMULET_OF_GLORY)),
|
||||
|
||||
@@ -144,7 +144,7 @@ public class SkillChallengeClue extends ClueScroll implements NpcClueScroll
|
||||
new SkillChallengeClue("Craft multiple cosmic runes from a single essence.", item(ItemID.PURE_ESSENCE)),
|
||||
new SkillChallengeClue("Plant a watermelon seed.", item(ItemID.RAKE), item(ItemID.SEED_DIBBER), xOfItem(ItemID.WATERMELON_SEED, 3)),
|
||||
new SkillChallengeClue("Activate the Chivalry prayer."),
|
||||
new SkillChallengeClue("Hand in a Tier 2 or higher set of Shayzien supply armour", "hand in a boxed set of shayzien supply armour at tier 2 or above.", any("Shayzien Supply Set (Tier 2 or higher)", item(ItemID.SHAYZIEN_SUPPLY_SET_2), item(ItemID.SHAYZIEN_SUPPLY_SET_3), item(ItemID.SHAYZIEN_SUPPLY_SET_4), item(ItemID.SHAYZIEN_SUPPLY_SET_5))),
|
||||
new SkillChallengeClue("Hand in a Tier 2 or higher set of Shayzien supply armour", "take the lovakengj armourers a boxed set of shayzien supply armour at tier 2 or above.", any("Shayzien Supply Set (Tier 2 or higher)", item(ItemID.SHAYZIEN_SUPPLY_SET_2), item(ItemID.SHAYZIEN_SUPPLY_SET_3), item(ItemID.SHAYZIEN_SUPPLY_SET_4), item(ItemID.SHAYZIEN_SUPPLY_SET_5))),
|
||||
// Master Sherlock Tasks
|
||||
new SkillChallengeClue("Equip an abyssal whip in front of the abyssal demons of the Slayer Tower.", true, any("Abyssal Whip", item(ItemID.ABYSSAL_WHIP), item(ItemID.FROZEN_ABYSSAL_WHIP), item(ItemID.VOLCANIC_ABYSSAL_WHIP))),
|
||||
new SkillChallengeClue("Smith a runite med helm.", item(ItemID.HAMMER), item(ItemID.RUNITE_BAR)),
|
||||
|
||||
@@ -38,7 +38,7 @@ import net.runelite.api.coords.WorldPoint;
|
||||
* <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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
@@ -48,11 +48,16 @@ public class MultipleOfItemRequirement implements ItemRequirement
|
||||
@Override
|
||||
public boolean fulfilledBy(Item[] items)
|
||||
{
|
||||
int quantityFound = 0;
|
||||
for (Item item : items)
|
||||
{
|
||||
if (item.getId() == itemId && item.getQuantity() >= quantity)
|
||||
if (item.getId() == itemId)
|
||||
{
|
||||
return true;
|
||||
quantityFound += item.getQuantity();
|
||||
if (quantityFound >= quantity)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,12 +51,12 @@ import net.runelite.api.NPCDefinition;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.HitsplatApplied;
|
||||
import net.runelite.api.kit.KitType;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
|
||||
@@ -38,7 +38,7 @@ import net.runelite.api.Experience;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.WorldType;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
|
||||
@@ -26,6 +26,7 @@ package net.runelite.client.plugins.config;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
@@ -45,6 +46,7 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -105,6 +107,7 @@ import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginInstantiationException;
|
||||
import net.runelite.client.plugins.PluginManager;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.DynamicGridLayout;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
@@ -137,7 +140,7 @@ public class ConfigPanel extends PluginPanel
|
||||
private static final String RUNELITE_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value();
|
||||
private static final String PINNED_PLUGINS_CONFIG_KEY = "pinnedPlugins";
|
||||
private static final String RUNELITE_PLUGIN = "RuneLite";
|
||||
private static final String openosrs_PLUGIN = "OpenOSRS";
|
||||
private static final String OPENOSRS_PLUGIN = "OpenOSRS";
|
||||
private static final String CHAT_COLOR_PLUGIN = "Chat Color";
|
||||
private final PluginManager pluginManager;
|
||||
private final ConfigManager configManager;
|
||||
@@ -156,6 +159,9 @@ public class ConfigPanel extends PluginPanel
|
||||
private boolean showingPluginList = true;
|
||||
private int scrollBarPosition = 0;
|
||||
|
||||
private static final ImmutableList<PluginType> definedOrder = ImmutableList.of(PluginType.IMPORTANT, PluginType.EXTERNAL, PluginType.PVM, PluginType.SKILLING, PluginType.PVP, PluginType.UTILITY, PluginType.GENERAL_USE);
|
||||
private static final Comparator<PluginListItem> categoryComparator = Comparator.comparing(plugin -> definedOrder.indexOf(plugin.getPluginType()));
|
||||
|
||||
static
|
||||
{
|
||||
final BufferedImage backIcon = ImageUtil.getResourceStreamFromClass(ConfigPanel.class, "config_back_icon.png");
|
||||
@@ -282,15 +288,15 @@ public class ConfigPanel extends PluginPanel
|
||||
// set OpenOSRS config on top, as it should always have been
|
||||
final PluginListItem openosrs = new PluginListItem(this, configManager, OpenOSRSConfig,
|
||||
configManager.getConfigDescriptor(OpenOSRSConfig),
|
||||
openosrs_PLUGIN, "OpenOSRS client settings", "client");
|
||||
openosrs.setPinned(pinnedPlugins.contains(openosrs_PLUGIN));
|
||||
OPENOSRS_PLUGIN, "OpenOSRS client settings", PluginType.IMPORTANT, "client");
|
||||
openosrs.setPinned(pinnedPlugins.contains(OPENOSRS_PLUGIN));
|
||||
openosrs.nameLabel.setForeground(Color.WHITE);
|
||||
pluginList.add(openosrs);
|
||||
|
||||
// set RuneLite config on top, as it should always have been
|
||||
final PluginListItem runeLite = new PluginListItem(this, configManager, runeLiteConfig,
|
||||
configManager.getConfigDescriptor(runeLiteConfig),
|
||||
RUNELITE_PLUGIN, "RuneLite client settings", "client");
|
||||
RUNELITE_PLUGIN, "RuneLite client settings", PluginType.IMPORTANT, "client");
|
||||
runeLite.setPinned(pinnedPlugins.contains(RUNELITE_PLUGIN));
|
||||
runeLite.nameLabel.setForeground(Color.WHITE);
|
||||
pluginList.add(runeLite);
|
||||
@@ -307,18 +313,21 @@ public class ConfigPanel extends PluginPanel
|
||||
|
||||
final PluginListItem listItem = new PluginListItem(this, configManager, plugin, descriptor, config, configDescriptor);
|
||||
listItem.setPinned(pinnedPlugins.contains(listItem.getName()));
|
||||
listItem.setColor(getColorByCategory(OpenOSRSConfig, listItem.getPluginType()));
|
||||
listItem.setHidden(getHiddenByCategory(OpenOSRSConfig, listItem.getPluginType()));
|
||||
plugins.add(listItem);
|
||||
}
|
||||
);
|
||||
|
||||
final PluginListItem chatColor = new PluginListItem(this, configManager, chatColorConfig,
|
||||
configManager.getConfigDescriptor(chatColorConfig),
|
||||
CHAT_COLOR_PLUGIN, "Recolor chat text", "colour", "messages");
|
||||
CHAT_COLOR_PLUGIN, "Recolor chat text", PluginType.GENERAL_USE, "colour", "messages");
|
||||
chatColor.setPinned(pinnedPlugins.contains(CHAT_COLOR_PLUGIN));
|
||||
chatColor.nameLabel.setForeground(Color.WHITE);
|
||||
plugins.add(chatColor);
|
||||
|
||||
pluginList.addAll(plugins);
|
||||
|
||||
ConfigPanel.sortPluginList(OpenOSRSConfig, null);
|
||||
}
|
||||
|
||||
void refreshPluginList()
|
||||
@@ -466,10 +475,17 @@ public class ConfigPanel extends PluginPanel
|
||||
|
||||
String name = listItem.getName();
|
||||
JLabel title = new JLabel(name);
|
||||
title.setForeground(Color.WHITE);
|
||||
title.setForeground(listItem.getColor());
|
||||
title.setToolTipText("<html>" + name + ":<br>" + listItem.getDescription() + "</html>");
|
||||
topPanel.add(title);
|
||||
|
||||
IconButton toggleButton = new IconButton(PluginListItem.OFF_SWITCHER);
|
||||
toggleButton.setPreferredSize(new Dimension(25, 0));
|
||||
listItem.updateToggleButton(toggleButton);
|
||||
listItem.attachToggleButtonListener(toggleButton);
|
||||
|
||||
topPanel.add(toggleButton, BorderLayout.EAST);
|
||||
|
||||
final Map<String, JPanel> sectionWidgets = new HashMap<>();
|
||||
final Map<String, JPanel> titleSectionWidgets = new HashMap<>();
|
||||
|
||||
@@ -1379,4 +1395,70 @@ public class ConfigPanel extends PluginPanel
|
||||
{
|
||||
openGroupConfigPanel(listItem, config, cd, true);
|
||||
}
|
||||
|
||||
public static Color getColorByCategory(OpenOSRSConfig openOSRSConfig, PluginType pluginType)
|
||||
{
|
||||
switch (pluginType)
|
||||
{
|
||||
case EXTERNAL:
|
||||
return openOSRSConfig.externalColor();
|
||||
case PVM:
|
||||
return openOSRSConfig.pvmColor();
|
||||
case PVP:
|
||||
return openOSRSConfig.pvpColor();
|
||||
case SKILLING:
|
||||
return openOSRSConfig.skillingColor();
|
||||
case UTILITY:
|
||||
return openOSRSConfig.utilityColor();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean getHiddenByCategory(OpenOSRSConfig openOSRSConfig, PluginType pluginType)
|
||||
{
|
||||
if (pluginType == PluginType.IMPORTANT || pluginType == PluginType.GENERAL_USE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (openOSRSConfig.hidePlugins())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (pluginType)
|
||||
{
|
||||
case EXTERNAL:
|
||||
return openOSRSConfig.hideExternalPlugins();
|
||||
case PVM:
|
||||
return openOSRSConfig.hidePvmPlugins();
|
||||
case PVP:
|
||||
return openOSRSConfig.hidePvpPlugins();
|
||||
case SKILLING:
|
||||
return openOSRSConfig.hideSkillingPlugins();
|
||||
case UTILITY:
|
||||
return openOSRSConfig.hideUtilityPlugins();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void sortPluginList(OpenOSRSConfig openOSRSConfig, Comparator<PluginListItem> comparator)
|
||||
{
|
||||
if (comparator != null)
|
||||
{
|
||||
ConfigPanel.pluginList.sort(comparator.thenComparing(PluginListItem::getName));
|
||||
return;
|
||||
}
|
||||
|
||||
if (openOSRSConfig.pluginSortMode() == net.runelite.client.config.OpenOSRSConfig.SortStyle.CATEGORY)
|
||||
{
|
||||
ConfigPanel.pluginList.sort(categoryComparator.thenComparing(PluginListItem::getName));
|
||||
}
|
||||
else
|
||||
{
|
||||
ConfigPanel.pluginList.sort(Comparator.comparing(PluginListItem::getName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.runelite.client.plugins.config;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.image.BufferedImage;
|
||||
@@ -43,6 +44,7 @@ import net.runelite.client.config.ConfigDescriptor;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import net.runelite.client.ui.components.IconButton;
|
||||
@@ -58,7 +60,7 @@ public class PluginListItem extends JPanel
|
||||
private static final ImageIcon CONFIG_ICON;
|
||||
private static final ImageIcon CONFIG_ICON_HOVER;
|
||||
private static final ImageIcon ON_SWITCHER;
|
||||
private static final ImageIcon OFF_SWITCHER;
|
||||
public static final ImageIcon OFF_SWITCHER;
|
||||
private static final ImageIcon ON_STAR;
|
||||
private static final ImageIcon OFF_STAR;
|
||||
|
||||
@@ -82,12 +84,16 @@ public class PluginListItem extends JPanel
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private final String description;
|
||||
|
||||
@Getter(AccessLevel.PUBLIC)
|
||||
private final PluginType pluginType;
|
||||
|
||||
private final List<String> keywords = new ArrayList<>();
|
||||
|
||||
private final IconButton pinButton = new IconButton(OFF_STAR);
|
||||
private final IconButton configButton = new IconButton(CONFIG_ICON, CONFIG_ICON_HOVER);
|
||||
private final IconButton toggleButton = new IconButton(OFF_SWITCHER);
|
||||
|
||||
@Getter
|
||||
private boolean isPluginEnabled = false;
|
||||
|
||||
@Getter
|
||||
@@ -96,6 +102,8 @@ public class PluginListItem extends JPanel
|
||||
@Getter
|
||||
private boolean isHidden = false;
|
||||
|
||||
private Color color = null;
|
||||
|
||||
static
|
||||
{
|
||||
BufferedImage configIcon = ImageUtil.getResourceStreamFromClass(ConfigPanel.class, "config_edit_icon.png");
|
||||
@@ -131,20 +139,20 @@ public class PluginListItem extends JPanel
|
||||
@Nullable Config config, @Nullable ConfigDescriptor configDescriptor)
|
||||
{
|
||||
this(configPanel, configManager, plugin, config, configDescriptor,
|
||||
descriptor.name(), descriptor.description(), descriptor.tags());
|
||||
descriptor.name(), descriptor.description(), descriptor.type(), descriptor.tags());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code PluginListItem} for a core configuration.
|
||||
*/
|
||||
PluginListItem(ConfigPanel configPanel, ConfigManager configManager, Config config, ConfigDescriptor configDescriptor,
|
||||
String name, String description, String... tags)
|
||||
String name, String description, PluginType pluginType, String... tags)
|
||||
{
|
||||
this(configPanel, configManager, null, config, configDescriptor, name, description, tags);
|
||||
this(configPanel, configManager, null, config, configDescriptor, name, description, pluginType, tags);
|
||||
}
|
||||
|
||||
private PluginListItem(ConfigPanel configPanel, ConfigManager configManager, @Nullable Plugin plugin, @Nullable Config config,
|
||||
@Nullable ConfigDescriptor configDescriptor, String name, String description, String... tags)
|
||||
@Nullable ConfigDescriptor configDescriptor, String name, String description, PluginType pluginType, String... tags)
|
||||
{
|
||||
this.configPanel = configPanel;
|
||||
this.plugin = plugin;
|
||||
@@ -152,6 +160,7 @@ public class PluginListItem extends JPanel
|
||||
this.configDescriptor = configDescriptor;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.pluginType = pluginType;
|
||||
Collections.addAll(keywords, name.toLowerCase().split(" "));
|
||||
Collections.addAll(keywords, description.toLowerCase().split(" "));
|
||||
Collections.addAll(keywords, tags);
|
||||
@@ -206,7 +215,7 @@ public class PluginListItem extends JPanel
|
||||
buttonPanel.add(toggleButton);
|
||||
}
|
||||
|
||||
private void attachToggleButtonListener(IconButton button)
|
||||
void attachToggleButtonListener(IconButton button)
|
||||
{
|
||||
// no need for a listener if there is no plugin to enable / disable
|
||||
if (plugin == null)
|
||||
@@ -231,15 +240,6 @@ public class PluginListItem extends JPanel
|
||||
});
|
||||
}
|
||||
|
||||
IconButton createToggleButton()
|
||||
{
|
||||
IconButton button = new IconButton(OFF_SWITCHER);
|
||||
button.setPreferredSize(new Dimension(25, 0));
|
||||
updateToggleButton(button);
|
||||
attachToggleButtonListener(button);
|
||||
return button;
|
||||
}
|
||||
|
||||
void setPluginEnabled(boolean enabled)
|
||||
{
|
||||
isPluginEnabled = enabled;
|
||||
@@ -253,12 +253,28 @@ public class PluginListItem extends JPanel
|
||||
pinButton.setToolTipText(pinned ? "Unpin plugin" : "Pin plugin");
|
||||
}
|
||||
|
||||
Color getColor()
|
||||
{
|
||||
return this.color == null ? Color.WHITE : this.color;
|
||||
}
|
||||
|
||||
public void setColor(Color color)
|
||||
{
|
||||
if (color == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.color = color;
|
||||
this.nameLabel.setForeground(color);
|
||||
}
|
||||
|
||||
public void setHidden(boolean hidden)
|
||||
{
|
||||
isHidden = hidden;
|
||||
}
|
||||
|
||||
private void updateToggleButton(IconButton button)
|
||||
void updateToggleButton(IconButton button)
|
||||
{
|
||||
button.setIcon(isPluginEnabled ? ON_SWITCHER : OFF_SWITCHER);
|
||||
button.setToolTipText(isPluginEnabled ? "Disable plugin" : "Enable plugin");
|
||||
|
||||
@@ -36,6 +36,7 @@ import javax.inject.Singleton;
|
||||
import static net.runelite.api.AnimationID.COOKING_FIRE;
|
||||
import static net.runelite.api.AnimationID.COOKING_RANGE;
|
||||
import net.runelite.api.Client;
|
||||
import static net.runelite.api.MenuOpcode.RUNELITE_OVERLAY;
|
||||
import static net.runelite.api.MenuOpcode.RUNELITE_OVERLAY_CONFIG;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerService;
|
||||
@@ -53,6 +54,7 @@ class CookingOverlay extends Overlay
|
||||
{
|
||||
private static final int COOK_TIMEOUT = 3;
|
||||
private static final DecimalFormat FORMAT = new DecimalFormat("#.#");
|
||||
static final String COOKING_RESET = "Reset";
|
||||
|
||||
private final Client client;
|
||||
private final CookingPlugin plugin;
|
||||
@@ -68,6 +70,7 @@ class CookingOverlay extends Overlay
|
||||
this.plugin = plugin;
|
||||
this.xpTrackerService = xpTrackerService;
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Cooking overlay"));
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY, COOKING_RESET, "Cooking overlay"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,19 +38,22 @@ import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicID;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.SpotAnimationChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.events.OverlayMenuClicked;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDependency;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerPlugin;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
|
||||
@PluginDescriptor(
|
||||
@@ -122,6 +125,18 @@ public class CookingPlugin extends Plugin
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
eventBus.subscribe(SpotAnimationChanged.class, this, this::onSpotAnimationChanged);
|
||||
eventBus.subscribe(ChatMessage.class, this, this::onChatMessage);
|
||||
eventBus.subscribe(OverlayMenuClicked.class, this, this::onOverlayMenuClicked);
|
||||
}
|
||||
|
||||
private void onOverlayMenuClicked(OverlayMenuClicked overlayMenuClicked)
|
||||
{
|
||||
OverlayMenuEntry overlayMenuEntry = overlayMenuClicked.getEntry();
|
||||
if (overlayMenuEntry.getMenuOpcode() == MenuOpcode.RUNELITE_OVERLAY
|
||||
&& overlayMenuClicked.getEntry().getOption().equals(CookingOverlay.COOKING_RESET)
|
||||
&& overlayMenuClicked.getOverlay() == overlay)
|
||||
{
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void onGameTick(GameTick gameTick)
|
||||
|
||||
@@ -40,7 +40,6 @@ import static net.runelite.api.MenuOpcode.NPC_SECOND_OPTION;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.HitsplatApplied;
|
||||
import net.runelite.api.events.InteractingChanged;
|
||||
@@ -53,6 +52,7 @@ import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
|
||||
@@ -57,20 +57,20 @@ import net.runelite.api.ProjectileID;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.ProjectileSpawned;
|
||||
import net.runelite.api.events.SpotAnimationChanged;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.api.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "CoX Helper",
|
||||
@@ -223,7 +223,7 @@ public class CoxPlugin extends Plugin
|
||||
{
|
||||
final String fixedPlayerName = Text.sanitize(rawPlayerName);
|
||||
|
||||
if (fixedPlayerName.equals(tpMatcher.group(1)))
|
||||
if (fixedPlayerName.equals(Text.sanitize(tpMatcher.group(1))))
|
||||
{
|
||||
victims.add(new Victim(player, Victim.Type.TELEPORT));
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
package net.runelite.client.plugins.customcursor;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.io.IOException;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
@@ -33,17 +34,14 @@ import javax.sound.sampled.Clip;
|
||||
import javax.sound.sampled.FloatControl;
|
||||
import javax.sound.sampled.LineUnavailableException;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
name = "Custom Cursor",
|
||||
|
||||
@@ -26,11 +26,9 @@
|
||||
|
||||
package net.runelite.client.plugins.dailytaskindicators;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.vars.AccountType;
|
||||
import com.google.inject.Provides;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
@@ -39,12 +37,14 @@ import net.runelite.api.VarPlayer;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.vars.AccountType;
|
||||
import net.runelite.client.chat.ChatColorType;
|
||||
import net.runelite.client.chat.ChatMessageBuilder;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.runelite.client.plugins.deathindicator;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Scene;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import static net.runelite.client.plugins.deathindicator.DeathIndicatorPlugin.HIJACKED_ITEMID;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.client.util.MiscUtils;
|
||||
|
||||
@EqualsAndHashCode
|
||||
@Getter
|
||||
@Setter
|
||||
class Bone
|
||||
{
|
||||
private String name;
|
||||
private WorldPoint loc;
|
||||
private Instant time;
|
||||
|
||||
void addToScene(Scene scene)
|
||||
{
|
||||
scene.addItem(HIJACKED_ITEMID, 1, loc);
|
||||
}
|
||||
|
||||
void removeFromScene(Scene scene)
|
||||
{
|
||||
scene.removeItem(HIJACKED_ITEMID, 1, loc);
|
||||
}
|
||||
|
||||
String getName()
|
||||
{
|
||||
return ColorUtil.colorStartTag(0xff9040) + "Bones (" + name + ")";
|
||||
}
|
||||
|
||||
String getExamine()
|
||||
{
|
||||
return name + " died here " + MiscUtils.formatTimeAgo(Duration.between(time, Instant.now()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package net.runelite.client.plugins.deathindicator;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Scene;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import static net.runelite.http.api.RuneLiteAPI.GSON;
|
||||
|
||||
@Slf4j
|
||||
public class Bones
|
||||
{
|
||||
private static final String CONFIG_GROUP = "deathIndicator";
|
||||
private static final String BONES_PREFIX = "bones_";
|
||||
|
||||
private ImmutableMap<Integer, Map<WorldPoint, List<Bone>>> map;
|
||||
|
||||
void init(Client client, ConfigManager configManager)
|
||||
{
|
||||
// Clone is important here as the normal array changes
|
||||
int[] regions = client.getMapRegions().clone();
|
||||
Bone[][] bones = getBones(configManager, regions);
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.trace("Regions are now {}", Arrays.toString(regions));
|
||||
|
||||
int n = 0;
|
||||
for (Bone[] ar : bones)
|
||||
{
|
||||
n += ar.length;
|
||||
}
|
||||
log.debug("Loaded {} Bones", n);
|
||||
}
|
||||
|
||||
initMap(regions, bones);
|
||||
|
||||
showBones(client.getScene());
|
||||
}
|
||||
|
||||
private Bone[][] getBones(ConfigManager configManager, int[] regions)
|
||||
{
|
||||
Bone[][] bones = new Bone[regions.length][];
|
||||
|
||||
for (int i = 0; i < regions.length; i++)
|
||||
{
|
||||
int region = regions[i];
|
||||
bones[i] = getBones(configManager, region);
|
||||
}
|
||||
|
||||
return bones;
|
||||
}
|
||||
|
||||
private Bone[] getBones(ConfigManager configManager, int regionId)
|
||||
{
|
||||
String json = configManager.getConfiguration(CONFIG_GROUP, BONES_PREFIX + regionId);
|
||||
if (json == null)
|
||||
{
|
||||
return new Bone[0];
|
||||
}
|
||||
|
||||
return GSON.fromJson(json, Bone[].class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void initMap(int[] regions, Bone[][] bones)
|
||||
{
|
||||
ImmutableMap.Builder<Integer, Map<WorldPoint, List<Bone>>> builder = ImmutableMap.builder();
|
||||
|
||||
for (int i = 0; i < regions.length; i++)
|
||||
{
|
||||
int region = regions[i];
|
||||
Bone[] boneA = bones[i];
|
||||
if (boneA.length == 0)
|
||||
{
|
||||
builder.put(region, new HashMap<>());
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<WorldPoint, List<Bone>> map = new HashMap(boneA.length);
|
||||
for (Bone b : boneA)
|
||||
{
|
||||
List<Bone> list = map.computeIfAbsent(b.getLoc(), wp -> new ArrayList<>());
|
||||
list.add(b);
|
||||
}
|
||||
|
||||
builder.put(region, map);
|
||||
}
|
||||
|
||||
this.map = builder.build();
|
||||
}
|
||||
|
||||
private void showBones(Scene scene)
|
||||
{
|
||||
this.forEach(bone -> bone.addToScene(scene));
|
||||
}
|
||||
|
||||
void save(ConfigManager configManager, int region)
|
||||
{
|
||||
final Map<WorldPoint, List<Bone>> regionBones = this.map.get(region);
|
||||
if (regionBones == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final String key = BONES_PREFIX + region;
|
||||
|
||||
if (regionBones.size() == 0)
|
||||
{
|
||||
configManager.unsetConfiguration(CONFIG_GROUP, key);
|
||||
}
|
||||
|
||||
List<Bone> list = new ArrayList<>(regionBones.values().size());
|
||||
for (List<Bone> lb : regionBones.values())
|
||||
{
|
||||
list.addAll(lb);
|
||||
}
|
||||
|
||||
String val = GSON.toJson(list.toArray(new Bone[0]));
|
||||
configManager.setConfiguration(CONFIG_GROUP, key, val);
|
||||
}
|
||||
|
||||
public boolean add(Bone bone)
|
||||
{
|
||||
if (this.map == null || bone == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
final int region = bone.getLoc().getRegionID();
|
||||
final Map<WorldPoint, List<Bone>> map = this.map.get(region);
|
||||
final List<Bone> list = map.computeIfAbsent(bone.getLoc(), wp -> new ArrayList<>());
|
||||
list.add(bone);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void remove(Bone bone)
|
||||
{
|
||||
final int region = bone.getLoc().getRegionID();
|
||||
final Map<WorldPoint, List<Bone>> map = this.map.get(region);
|
||||
final List<Bone> list = map.get(bone.getLoc());
|
||||
list.remove(bone);
|
||||
}
|
||||
|
||||
public void clear(Scene scene)
|
||||
{
|
||||
if (map == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.forEach(bone -> bone.removeFromScene(scene));
|
||||
}
|
||||
|
||||
public Bone get(WorldPoint point, int i)
|
||||
{
|
||||
return get(point).get(i);
|
||||
}
|
||||
|
||||
public List<Bone> get(WorldPoint point)
|
||||
{
|
||||
final int reg = point.getRegionID();
|
||||
final Map<WorldPoint, List<Bone>> map = this.map.get(reg);
|
||||
if (map == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return map.get(point);
|
||||
}
|
||||
|
||||
private void forEach(Consumer<Bone> consumer)
|
||||
{
|
||||
for (Map<WorldPoint, List<Bone>> map : this.map.values())
|
||||
{
|
||||
for (Map.Entry<WorldPoint, List<Bone>> entry : map.entrySet())
|
||||
{
|
||||
for (Bone bone : entry.getValue())
|
||||
{
|
||||
consumer.accept(bone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,4 +152,14 @@ public interface DeathIndicatorConfig extends Config
|
||||
description = ""
|
||||
)
|
||||
void timeOfDeath(Instant timeOfDeath);
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "permaBones",
|
||||
name = "Permanent bones",
|
||||
description = "Show right clickable bones with the name of who died permanently, after seeing someone die"
|
||||
)
|
||||
default boolean permaBones()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,18 +30,32 @@ import java.awt.image.BufferedImage;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ItemDespawned;
|
||||
import net.runelite.api.events.LocalPlayerDeath;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOpened;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.PlayerDeath;
|
||||
import net.runelite.api.events.PostItemDefinition;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
@@ -61,6 +75,10 @@ import net.runelite.client.util.ImageUtil;
|
||||
@Slf4j
|
||||
public class DeathIndicatorPlugin extends Plugin
|
||||
{
|
||||
private static final Object BONES = new Object();
|
||||
// A random number, that jagex probably won't actually use in the near future
|
||||
static final int HIJACKED_ITEMID = 0x69696969;
|
||||
|
||||
private static final Set<Integer> RESPAWN_REGIONS = ImmutableSet.of(
|
||||
12850, // Lumbridge
|
||||
11828, // Falador
|
||||
@@ -88,6 +106,14 @@ public class DeathIndicatorPlugin extends Plugin
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@Inject
|
||||
private ConfigManager configManager;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
private final Bones bones = new Bones();
|
||||
|
||||
private BufferedImage mapArrow;
|
||||
|
||||
private Timer deathTimer;
|
||||
@@ -95,7 +121,7 @@ public class DeathIndicatorPlugin extends Plugin
|
||||
private WorldPoint lastDeath;
|
||||
private Instant lastDeathTime;
|
||||
private int lastDeathWorld;
|
||||
|
||||
private int despawnIdx = 0;
|
||||
@Provides
|
||||
DeathIndicatorConfig deathIndicatorConfig(ConfigManager configManager)
|
||||
{
|
||||
@@ -129,12 +155,18 @@ public class DeathIndicatorPlugin extends Plugin
|
||||
worldMapPointManager.removeIf(DeathWorldMapPoint.class::isInstance);
|
||||
worldMapPointManager.add(new DeathWorldMapPoint(new WorldPoint(config.deathLocationX(), config.deathLocationY(), config.deathLocationPlane()), this));
|
||||
}
|
||||
|
||||
if (config.permaBones() && client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
clientThread.invokeLater(this::initBones);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
eventBus.unregister(this);
|
||||
eventBus.unregister(BONES);
|
||||
|
||||
if (client.hasHintArrow())
|
||||
{
|
||||
@@ -148,6 +180,18 @@ public class DeathIndicatorPlugin extends Plugin
|
||||
}
|
||||
|
||||
worldMapPointManager.removeIf(DeathWorldMapPoint.class::isInstance);
|
||||
|
||||
clientThread.invokeLater(this::clearBones);
|
||||
}
|
||||
|
||||
private void initBones()
|
||||
{
|
||||
bones.init(client, configManager);
|
||||
}
|
||||
|
||||
private void clearBones()
|
||||
{
|
||||
bones.clear(client.getScene());
|
||||
}
|
||||
|
||||
private void addSubscriptions()
|
||||
@@ -156,6 +200,105 @@ public class DeathIndicatorPlugin extends Plugin
|
||||
eventBus.subscribe(LocalPlayerDeath.class, this, this::onLocalPlayerDeath);
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
if (config.permaBones())
|
||||
{
|
||||
addBoneSubs();
|
||||
}
|
||||
}
|
||||
|
||||
private void addBoneSubs()
|
||||
{
|
||||
eventBus.subscribe(ItemDespawned.class, BONES, this::onItemDespawn);
|
||||
eventBus.subscribe(PlayerDeath.class, BONES, this::onPlayerDeath);
|
||||
eventBus.subscribe(MenuEntryAdded.class, BONES, this::onMenuEntryAdded);
|
||||
eventBus.subscribe(MenuOptionClicked.class, BONES, this::onMenuOptionClicked);
|
||||
eventBus.subscribe(MenuOpened.class, BONES, this::onMenuOpened);
|
||||
eventBus.subscribe(PostItemDefinition.class, BONES, this::onPostItemDefinition);
|
||||
}
|
||||
|
||||
private void onPostItemDefinition(PostItemDefinition def)
|
||||
{
|
||||
ItemDefinition itemDef = def.getItemDefinition();
|
||||
if (itemDef.getId() == HIJACKED_ITEMID)
|
||||
{
|
||||
itemDef.setModelOverride(ItemID.BONES);
|
||||
itemDef.setName("Bones");
|
||||
// This is so never hide untradeables doesn't not hide it
|
||||
itemDef.setTradeable(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void onPlayerDeath(PlayerDeath death)
|
||||
{
|
||||
newBoneFor(death.getPlayer());
|
||||
}
|
||||
|
||||
private void newBoneFor(Player player)
|
||||
{
|
||||
Bone b = new Bone();
|
||||
|
||||
b.setName(Text.sanitize(player.getName()));
|
||||
b.setTime(Instant.now());
|
||||
b.setLoc(player.getWorldLocation());
|
||||
|
||||
while (!bones.add(b))
|
||||
{
|
||||
initBones();
|
||||
}
|
||||
|
||||
b.addToScene(client.getScene());
|
||||
bones.save(configManager, b.getLoc().getRegionID());
|
||||
}
|
||||
|
||||
private void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
if (event.getIdentifier() == HIJACKED_ITEMID)
|
||||
{
|
||||
if (event.getOpcode() == MenuOpcode.GROUND_ITEM_THIRD_OPTION.getId())
|
||||
{
|
||||
client.setMenuOptionCount(client.getMenuOptionCount() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onMenuOpened(MenuOpened event)
|
||||
{
|
||||
int idx = 0;
|
||||
|
||||
for (MenuEntry entry : event)
|
||||
{
|
||||
if (entry.getIdentifier() != HIJACKED_ITEMID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only entries with appropriate identifier here will be examine so that's easy
|
||||
// Add idx to id field, so we can find that back from clicked event
|
||||
entry.setIdentifier(HIJACKED_ITEMID + idx);
|
||||
|
||||
Bone bone = bones.get(
|
||||
WorldPoint.fromScene(client, entry.getParam0(), entry.getParam1(), client.getPlane()),
|
||||
idx++
|
||||
);
|
||||
|
||||
entry.setTarget(bone.getName());
|
||||
event.setModified();
|
||||
}
|
||||
}
|
||||
|
||||
private void onMenuOptionClicked(MenuOptionClicked event)
|
||||
{
|
||||
if (event.getIdentifier() >= HIJACKED_ITEMID
|
||||
&& event.getOpcode() == MenuOpcode.EXAMINE_ITEM_GROUND.getId())
|
||||
{
|
||||
Bone b = bones.get(
|
||||
WorldPoint.fromScene(client, event.getParam0(), event.getParam1(), client.getPlane()),
|
||||
event.getIdentifier() - HIJACKED_ITEMID
|
||||
);
|
||||
|
||||
client.addChatMessage(ChatMessageType.ITEM_EXAMINE, "", b.getExamine(), "");
|
||||
event.consume();
|
||||
}
|
||||
}
|
||||
|
||||
private void onLocalPlayerDeath(LocalPlayerDeath death)
|
||||
@@ -165,7 +308,13 @@ public class DeathIndicatorPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
lastDeath = client.getLocalPlayer().getWorldLocation();
|
||||
Player lp = client.getLocalPlayer();
|
||||
if (config.permaBones())
|
||||
{
|
||||
newBoneFor(lp);
|
||||
}
|
||||
|
||||
lastDeath = lp.getWorldLocation();
|
||||
lastDeathWorld = client.getWorld();
|
||||
lastDeathTime = Instant.now();
|
||||
}
|
||||
@@ -238,6 +387,28 @@ public class DeathIndicatorPlugin extends Plugin
|
||||
{
|
||||
if (event.getGroup().equals("deathIndicator"))
|
||||
{
|
||||
if ("permaBones".equals(event.getKey()))
|
||||
{
|
||||
if (config.permaBones())
|
||||
{
|
||||
addBoneSubs();
|
||||
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
clientThread.invokeLater(this::initBones);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
eventBus.unregister(BONES);
|
||||
|
||||
if (client.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
clientThread.invokeLater(this::clearBones);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!config.showDeathHintArrow() && hasDied())
|
||||
{
|
||||
client.clearHintArrow();
|
||||
@@ -267,32 +438,61 @@ public class DeathIndicatorPlugin extends Plugin
|
||||
|
||||
private void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
if (!hasDied())
|
||||
switch (event.getGameState())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getGameState() == GameState.LOGGED_IN)
|
||||
{
|
||||
if (client.getWorld() == config.deathWorld())
|
||||
{
|
||||
WorldPoint deathPoint = new WorldPoint(config.deathLocationX(), config.deathLocationY(), config.deathLocationPlane());
|
||||
|
||||
if (config.showDeathHintArrow())
|
||||
case LOADING:
|
||||
clearBones();
|
||||
break;
|
||||
case LOGGED_IN:
|
||||
if (config.permaBones())
|
||||
{
|
||||
client.setHintArrow(deathPoint);
|
||||
initBones();
|
||||
}
|
||||
|
||||
if (config.showDeathOnWorldMap())
|
||||
if (!hasDied())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.getWorld() == config.deathWorld())
|
||||
{
|
||||
WorldPoint deathPoint = new WorldPoint(config.deathLocationX(), config.deathLocationY(), config.deathLocationPlane());
|
||||
|
||||
if (config.showDeathHintArrow())
|
||||
{
|
||||
client.setHintArrow(deathPoint);
|
||||
}
|
||||
|
||||
if (config.showDeathOnWorldMap())
|
||||
{
|
||||
worldMapPointManager.removeIf(DeathWorldMapPoint.class::isInstance);
|
||||
worldMapPointManager.add(new DeathWorldMapPoint(deathPoint, this));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
worldMapPointManager.removeIf(DeathWorldMapPoint.class::isInstance);
|
||||
worldMapPointManager.add(new DeathWorldMapPoint(deathPoint, this));
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void onItemDespawn(ItemDespawned event)
|
||||
{
|
||||
if (event.getItem().getId() == HIJACKED_ITEMID)
|
||||
{
|
||||
List<Bone> list = bones.get(event.getTile().getWorldLocation());
|
||||
if (list == null)
|
||||
{
|
||||
worldMapPointManager.removeIf(DeathWorldMapPoint.class::isInstance);
|
||||
return;
|
||||
}
|
||||
if (list.size() <= despawnIdx)
|
||||
{
|
||||
despawnIdx = 0;
|
||||
}
|
||||
Bone bone = list.get(despawnIdx++);
|
||||
bone.addToScene(client.getScene());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,6 @@ import java.awt.geom.Rectangle2D;
|
||||
import java.util.List;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Constants;
|
||||
@@ -76,9 +74,6 @@ import net.runelite.client.ui.overlay.tooltip.TooltipManager;
|
||||
@Singleton
|
||||
class DevToolsOverlay extends Overlay
|
||||
{
|
||||
private static final int ITEM_EMPTY = 6512;
|
||||
private static final int ITEM_FILLED = 20594;
|
||||
|
||||
private static final Font FONT = FontManager.getRunescapeFont().deriveFont(Font.BOLD, 16);
|
||||
private static final Color RED = new Color(221, 44, 0);
|
||||
private static final Color GREEN = new Color(0, 200, 83);
|
||||
@@ -97,13 +92,6 @@ class DevToolsOverlay extends Overlay
|
||||
private final DevToolsPlugin plugin;
|
||||
private final TooltipManager toolTipManager;
|
||||
|
||||
@Setter
|
||||
@Getter
|
||||
private Widget widget;
|
||||
|
||||
@Setter
|
||||
private int itemIndex = -1;
|
||||
|
||||
@Inject
|
||||
private DevToolsOverlay(Client client, DevToolsPlugin plugin, TooltipManager toolTipManager)
|
||||
{
|
||||
@@ -155,8 +143,6 @@ class DevToolsOverlay extends Overlay
|
||||
renderCursorTooltip(graphics);
|
||||
}
|
||||
|
||||
renderWidgets(graphics);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -490,70 +476,6 @@ class DevToolsOverlay extends Overlay
|
||||
}
|
||||
}
|
||||
|
||||
private void renderWidgets(Graphics2D graphics)
|
||||
{
|
||||
if (widget == null || widget.isHidden())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Rectangle childBounds = widget.getBounds();
|
||||
graphics.setColor(CYAN);
|
||||
graphics.draw(childBounds);
|
||||
|
||||
if (itemIndex == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (widget.getItemId() != ITEM_EMPTY
|
||||
&& widget.getItemId() != ITEM_FILLED)
|
||||
{
|
||||
Rectangle componentBounds = widget.getBounds();
|
||||
|
||||
graphics.setColor(ORANGE);
|
||||
graphics.draw(componentBounds);
|
||||
|
||||
renderWidgetText(graphics, componentBounds, widget.getItemId(), YELLOW);
|
||||
}
|
||||
|
||||
WidgetItem widgetItem = widget.getWidgetItem(itemIndex);
|
||||
if (widgetItem == null
|
||||
|| widgetItem.getId() < 0
|
||||
|| widgetItem.getId() == ITEM_EMPTY
|
||||
|| widgetItem.getId() == ITEM_FILLED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Rectangle itemBounds = widgetItem.getCanvasBounds();
|
||||
|
||||
graphics.setColor(ORANGE);
|
||||
graphics.draw(itemBounds);
|
||||
|
||||
renderWidgetText(graphics, itemBounds, widgetItem.getId(), YELLOW);
|
||||
}
|
||||
|
||||
private void renderWidgetText(Graphics2D graphics, Rectangle bounds, int itemId, Color color)
|
||||
{
|
||||
if (itemId == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String text = itemId + "";
|
||||
FontMetrics fm = graphics.getFontMetrics();
|
||||
Rectangle2D textBounds = fm.getStringBounds(text, graphics);
|
||||
|
||||
int textX = (int) (bounds.getX() + (bounds.getWidth() / 2) - (textBounds.getWidth() / 2));
|
||||
int textY = (int) (bounds.getY() + (bounds.getHeight() / 2) + (textBounds.getHeight() / 2));
|
||||
|
||||
graphics.setColor(Color.BLACK);
|
||||
graphics.drawString(text, textX + 1, textY + 1);
|
||||
graphics.setColor(color);
|
||||
graphics.drawString(text, textX, textY);
|
||||
}
|
||||
|
||||
private void renderPlayerWireframe(Graphics2D graphics, Player player, Color color)
|
||||
{
|
||||
Polygon[] polys = player.getPolygons();
|
||||
|
||||
@@ -42,11 +42,10 @@ import net.runelite.api.Player;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.AreaSoundEffectPlayed;
|
||||
import net.runelite.api.events.BoostedLevelChanged;
|
||||
import net.runelite.api.events.CommandExecuted;
|
||||
import net.runelite.api.events.ExperienceChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.SoundEffectPlayed;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.kit.KitType;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
@@ -301,9 +300,13 @@ public class DevToolsPlugin extends Plugin
|
||||
|
||||
client.queueChangedSkill(skill);
|
||||
|
||||
ExperienceChanged experienceChanged = new ExperienceChanged();
|
||||
experienceChanged.setSkill(skill);
|
||||
eventBus.post(ExperienceChanged.class, experienceChanged);
|
||||
StatChanged statChanged = new StatChanged(
|
||||
skill,
|
||||
totalXp,
|
||||
level,
|
||||
level
|
||||
);
|
||||
eventBus.post(StatChanged.class, statChanged);
|
||||
break;
|
||||
}
|
||||
case "setstat":
|
||||
@@ -320,13 +323,13 @@ public class DevToolsPlugin extends Plugin
|
||||
|
||||
client.queueChangedSkill(skill);
|
||||
|
||||
ExperienceChanged experienceChanged = new ExperienceChanged();
|
||||
experienceChanged.setSkill(skill);
|
||||
eventBus.post(ExperienceChanged.class, experienceChanged);
|
||||
|
||||
BoostedLevelChanged boostedLevelChanged = new BoostedLevelChanged();
|
||||
boostedLevelChanged.setSkill(skill);
|
||||
eventBus.post(BoostedLevelChanged.class, boostedLevelChanged);
|
||||
StatChanged statChanged = new StatChanged(
|
||||
skill,
|
||||
xp,
|
||||
level,
|
||||
level
|
||||
);
|
||||
eventBus.post(StatChanged.class, statChanged);
|
||||
break;
|
||||
}
|
||||
case "anim":
|
||||
|
||||
@@ -110,6 +110,7 @@ class SoundEffectOverlay extends Overlay
|
||||
|
||||
String text =
|
||||
"Id: " + event.getSoundId() +
|
||||
" - S: " + (event.getSource() != null ? event.getSource().getName() : "<none>") +
|
||||
" - L: " + event.getSceneX() + "," + event.getSceneY() +
|
||||
" - R: " + event.getRange() +
|
||||
" - D: " + event.getDelay();
|
||||
|
||||
@@ -27,13 +27,20 @@
|
||||
package net.runelite.client.plugins.devtools;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.stream.Stream;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFrame;
|
||||
@@ -45,29 +52,67 @@ import javax.swing.JTree;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetConfig;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
class WidgetInspector extends JFrame
|
||||
{
|
||||
private static final Map<Integer, WidgetInfo> widgetIdMap = new HashMap<>();
|
||||
|
||||
static final Color SELECTED_WIDGET_COLOR = Color.CYAN;
|
||||
private static final float SELECTED_WIDGET_HUE;
|
||||
|
||||
static
|
||||
{
|
||||
float[] hsb = new float[3];
|
||||
Color.RGBtoHSB(SELECTED_WIDGET_COLOR.getRed(), SELECTED_WIDGET_COLOR.getGreen(), SELECTED_WIDGET_COLOR.getBlue(), hsb);
|
||||
SELECTED_WIDGET_HUE = hsb[0];
|
||||
}
|
||||
|
||||
private final Client client;
|
||||
private final ClientThread clientThread;
|
||||
private final DevToolsConfig config;
|
||||
private final DevToolsOverlay overlay;
|
||||
private final Provider<WidgetInspectorOverlay> overlay;
|
||||
private final OverlayManager overlayManager;
|
||||
|
||||
private final JTree widgetTree;
|
||||
private final WidgetInfoTableModel infoTableModel;
|
||||
private final JCheckBox alwaysOnTop;
|
||||
private final JCheckBox hideHidden;
|
||||
|
||||
private static final Map<Integer, WidgetInfo> widgetIdMap = new HashMap<>();
|
||||
private DefaultMutableTreeNode root;
|
||||
|
||||
@Getter
|
||||
private Widget selectedWidget;
|
||||
|
||||
@Getter
|
||||
private int selectedItem;
|
||||
|
||||
private Widget picker = null;
|
||||
|
||||
@Getter
|
||||
private boolean pickerSelected = false;
|
||||
|
||||
@Inject
|
||||
private WidgetInspector(
|
||||
@@ -75,17 +120,21 @@ class WidgetInspector extends JFrame
|
||||
ClientThread clientThread,
|
||||
WidgetInfoTableModel infoTableModel,
|
||||
DevToolsConfig config,
|
||||
DevToolsPlugin plugin,
|
||||
EventBus eventBus,
|
||||
DevToolsOverlay overlay,
|
||||
DevToolsPlugin plugin)
|
||||
Provider<WidgetInspectorOverlay> overlay,
|
||||
OverlayManager overlayManager)
|
||||
{
|
||||
this.client = client;
|
||||
this.clientThread = clientThread;
|
||||
this.infoTableModel = infoTableModel;
|
||||
this.config = config;
|
||||
this.overlay = overlay;
|
||||
this.overlayManager = overlayManager;
|
||||
|
||||
eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
|
||||
eventBus.subscribe(MenuOptionClicked.class, this, this::onMenuOptionClicked);
|
||||
eventBus.subscribe(MenuEntryAdded.class, this, this::onMenuEntryAdded);
|
||||
|
||||
setTitle("RuneLite Widget Inspector");
|
||||
setIconImage(ClientUI.ICON);
|
||||
@@ -96,7 +145,6 @@ class WidgetInspector extends JFrame
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
eventBus.unregister(this);
|
||||
close();
|
||||
plugin.getWidgetInspector().setActive(false);
|
||||
}
|
||||
@@ -114,16 +162,12 @@ class WidgetInspector extends JFrame
|
||||
{
|
||||
WidgetTreeNode node = (WidgetTreeNode) selected;
|
||||
Widget widget = node.getWidget();
|
||||
overlay.setWidget(widget);
|
||||
overlay.setItemIndex(widget.getItemId());
|
||||
refreshInfo();
|
||||
log.debug("Set widget to {} and item index to {}", widget, widget.getItemId());
|
||||
setSelectedWidget(widget, -1, false);
|
||||
}
|
||||
else if (selected instanceof WidgetItemNode)
|
||||
{
|
||||
WidgetItemNode node = (WidgetItemNode) selected;
|
||||
overlay.setItemIndex(node.getWidgetItem().getIndex());
|
||||
log.debug("Set item index to {}", node.getWidgetItem().getIndex());
|
||||
setSelectedWidget(node.getWidgetItem().getWidget(), node.getWidgetItem().getIndex(), false);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -149,15 +193,20 @@ class WidgetInspector extends JFrame
|
||||
onConfigChanged(null);
|
||||
bottomPanel.add(alwaysOnTop);
|
||||
|
||||
hideHidden = new JCheckBox("Hide hidden");
|
||||
hideHidden.setSelected(true);
|
||||
hideHidden.addItemListener(ev -> refreshWidgets());
|
||||
bottomPanel.add(hideHidden);
|
||||
|
||||
final JButton revalidateWidget = new JButton("Revalidate");
|
||||
revalidateWidget.addActionListener(ev -> clientThread.invokeLater(() ->
|
||||
{
|
||||
if (overlay.getWidget() == null)
|
||||
if (selectedWidget == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
overlay.getWidget().revalidate();
|
||||
selectedWidget.revalidate();
|
||||
}));
|
||||
bottomPanel.add(revalidateWidget);
|
||||
|
||||
@@ -165,7 +214,6 @@ class WidgetInspector extends JFrame
|
||||
add(split, BorderLayout.CENTER);
|
||||
|
||||
pack();
|
||||
|
||||
}
|
||||
|
||||
private void onConfigChanged(ConfigChanged ev)
|
||||
@@ -180,10 +228,13 @@ class WidgetInspector extends JFrame
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
Widget[] rootWidgets = client.getWidgetRoots();
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
root = new DefaultMutableTreeNode();
|
||||
|
||||
overlay.setWidget(null);
|
||||
overlay.setItemIndex(-1);
|
||||
Widget wasSelectedWidget = selectedWidget;
|
||||
int wasSelectedItem = selectedItem;
|
||||
|
||||
selectedWidget = null;
|
||||
selectedItem = -1;
|
||||
|
||||
for (Widget widget : rootWidgets)
|
||||
{
|
||||
@@ -196,17 +247,15 @@ class WidgetInspector extends JFrame
|
||||
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
overlay.setWidget(null);
|
||||
overlay.setItemIndex(-1);
|
||||
refreshInfo();
|
||||
widgetTree.setModel(new DefaultTreeModel(root));
|
||||
setSelectedWidget(wasSelectedWidget, wasSelectedItem, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private DefaultMutableTreeNode addWidget(String type, Widget widget)
|
||||
{
|
||||
if (widget == null || widget.isHidden())
|
||||
if (widget == null || (hideHidden.isSelected() && widget.isHidden()))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -269,9 +318,70 @@ class WidgetInspector extends JFrame
|
||||
return node;
|
||||
}
|
||||
|
||||
private void refreshInfo()
|
||||
private void setSelectedWidget(Widget widget, int item, boolean updateTree)
|
||||
{
|
||||
infoTableModel.setWidget(overlay.getWidget());
|
||||
infoTableModel.setWidget(widget);
|
||||
|
||||
if (this.selectedWidget == widget && this.selectedItem == item)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedWidget = widget;
|
||||
this.selectedItem = item;
|
||||
|
||||
if (root == null || !updateTree)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
Stack<Widget> treePath = new Stack<>();
|
||||
for (Widget w = widget; w != null; w = w.getParent())
|
||||
{
|
||||
treePath.push(w);
|
||||
}
|
||||
|
||||
DefaultMutableTreeNode node = root;
|
||||
deeper:
|
||||
for (; !treePath.empty(); )
|
||||
{
|
||||
Widget w = treePath.pop();
|
||||
for (Enumeration<?> it = node.children(); it.hasMoreElements(); )
|
||||
{
|
||||
WidgetTreeNode inner = (WidgetTreeNode) it.nextElement();
|
||||
if (inner.getWidget().getId() == w.getId() && inner.getWidget().getIndex() == w.getIndex())
|
||||
{
|
||||
node = inner;
|
||||
continue deeper;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selectedItem != -1)
|
||||
{
|
||||
for (Enumeration<?> it = node.children(); it.hasMoreElements(); )
|
||||
{
|
||||
Object wiw = it.nextElement();
|
||||
if (wiw instanceof WidgetItemNode)
|
||||
{
|
||||
WidgetItemNode inner = (WidgetItemNode) wiw;
|
||||
if (inner.getWidgetItem().getIndex() == selectedItem)
|
||||
{
|
||||
node = inner;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final DefaultMutableTreeNode fnode = node;
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
widgetTree.getSelectionModel().clearSelection();
|
||||
widgetTree.getSelectionModel().addSelectionPath(new TreePath(fnode.getPath()));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static WidgetInfo getWidgetInfo(int packedId)
|
||||
@@ -295,12 +405,176 @@ class WidgetInspector extends JFrame
|
||||
setVisible(true);
|
||||
toFront();
|
||||
repaint();
|
||||
overlayManager.add(this.overlay.get());
|
||||
clientThread.invokeLater(this::addPickerWidget);
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
overlay.setWidget(null);
|
||||
overlay.setItemIndex(-1);
|
||||
overlayManager.remove(this.overlay.get());
|
||||
clientThread.invokeLater(this::removePickerWidget);
|
||||
setSelectedWidget(null, -1, false);
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void removePickerWidget()
|
||||
{
|
||||
if (picker == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widget parent = picker.getParent();
|
||||
if (parent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Widget[] children = parent.getChildren();
|
||||
if (children == null || children.length <= picker.getIndex() || children[picker.getIndex()] != picker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
children[picker.getIndex()] = null;
|
||||
}
|
||||
|
||||
private void addPickerWidget()
|
||||
{
|
||||
removePickerWidget();
|
||||
|
||||
int x = 10, y = 2;
|
||||
Widget parent = client.getWidget(WidgetInfo.MINIMAP_ORBS);
|
||||
if (parent == null)
|
||||
{
|
||||
Widget[] roots = client.getWidgetRoots();
|
||||
|
||||
parent = Stream.of(roots)
|
||||
.filter(w -> w.getType() == WidgetType.LAYER && w.getContentType() == 0 && !w.isSelfHidden())
|
||||
.sorted(Comparator.comparing((Widget w) -> w.getRelativeX() + w.getRelativeY())
|
||||
.reversed()
|
||||
.thenComparing(Widget::getId)
|
||||
.reversed())
|
||||
.findFirst().get();
|
||||
x = 4;
|
||||
y = 4;
|
||||
}
|
||||
|
||||
picker = parent.createChild(-1, WidgetType.GRAPHIC);
|
||||
|
||||
log.info("Picker is {}.{} [{}]", WidgetInfo.TO_GROUP(picker.getId()), WidgetInfo.TO_CHILD(picker.getId()), picker.getIndex());
|
||||
|
||||
picker.setSpriteId(SpriteID.MOBILE_FINGER_ON_INTERFACE);
|
||||
picker.setOriginalWidth(15);
|
||||
picker.setOriginalHeight(17);
|
||||
picker.setOriginalX(x);
|
||||
picker.setOriginalY(y);
|
||||
picker.revalidate();
|
||||
picker.setTargetVerb("Select");
|
||||
picker.setName("Pick");
|
||||
picker.setClickMask(WidgetConfig.USE_WIDGET | WidgetConfig.USE_ITEM);
|
||||
picker.setNoClickThrough(true);
|
||||
picker.setOnTargetEnterListener((JavaScriptCallback) ev ->
|
||||
{
|
||||
pickerSelected = true;
|
||||
picker.setOpacity(30);
|
||||
client.setAllWidgetsAreOpTargetable(true);
|
||||
});
|
||||
picker.setOnTargetLeaveListener((JavaScriptCallback) ev -> onPickerDeselect());
|
||||
}
|
||||
|
||||
private void onPickerDeselect()
|
||||
{
|
||||
client.setAllWidgetsAreOpTargetable(false);
|
||||
picker.setOpacity(0);
|
||||
pickerSelected = false;
|
||||
}
|
||||
|
||||
private void onMenuOptionClicked(MenuOptionClicked ev)
|
||||
{
|
||||
if (!pickerSelected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
onPickerDeselect();
|
||||
client.setSpellSelected(false);
|
||||
ev.consume();
|
||||
|
||||
Object target = getWidgetOrWidgetItemForMenuOption(ev.getMenuOpcode().getId(), ev.getParam0(), ev.getParam1());
|
||||
if (target == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (target instanceof WidgetItem)
|
||||
{
|
||||
WidgetItem iw = (WidgetItem) target;
|
||||
setSelectedWidget(iw.getWidget(), iw.getIndex(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
setSelectedWidget((Widget) target, -1, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void onMenuEntryAdded(MenuEntryAdded event)
|
||||
{
|
||||
if (!pickerSelected)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MenuEntry[] menuEntries = client.getMenuEntries();
|
||||
|
||||
for (int i = 0; i < menuEntries.length; i++)
|
||||
{
|
||||
MenuEntry entry = menuEntries[i];
|
||||
if (entry.getOpcode() != MenuOpcode.ITEM_USE_ON_WIDGET.getId()
|
||||
&& entry.getOpcode() != MenuOpcode.SPELL_CAST_ON_WIDGET.getId())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String name = WidgetInfo.TO_GROUP(entry.getParam1()) + "." + WidgetInfo.TO_CHILD(entry.getParam1());
|
||||
|
||||
if (entry.getParam0() != -1)
|
||||
{
|
||||
name += " [" + entry.getParam0() + "]";
|
||||
}
|
||||
|
||||
Color color = colorForWidget(i, menuEntries.length);
|
||||
|
||||
entry.setTarget(ColorUtil.wrapWithColorTag(name, color));
|
||||
}
|
||||
|
||||
client.setMenuEntries(menuEntries);
|
||||
}
|
||||
|
||||
Color colorForWidget(int index, int length)
|
||||
{
|
||||
float h = SELECTED_WIDGET_HUE + .1f + (.8f / length) * index;
|
||||
|
||||
return Color.getHSBColor(h, 1, 1);
|
||||
}
|
||||
|
||||
Object getWidgetOrWidgetItemForMenuOption(int type, int param0, int param1)
|
||||
{
|
||||
if (type == MenuOpcode.SPELL_CAST_ON_WIDGET.getId())
|
||||
{
|
||||
Widget w = client.getWidget(WidgetInfo.TO_GROUP(param1), WidgetInfo.TO_CHILD(param1));
|
||||
if (param0 != -1)
|
||||
{
|
||||
w = w.getChild(param0);
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
else if (type == MenuOpcode.ITEM_USE_ON_WIDGET.getId())
|
||||
{
|
||||
Widget w = client.getWidget(WidgetInfo.TO_GROUP(param1), WidgetInfo.TO_CHILD(param1));
|
||||
return w.getWidgetItem(param0);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Abex
|
||||
* Copyright (c) 2017, Kronos <https://github.com/KronosDesign>
|
||||
* Copyright (c) 2017, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.devtools;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.MenuEntry;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
import net.runelite.client.ui.overlay.OverlayPosition;
|
||||
import net.runelite.client.ui.overlay.OverlayPriority;
|
||||
|
||||
@Singleton
|
||||
public class WidgetInspectorOverlay extends Overlay
|
||||
{
|
||||
private final Client client;
|
||||
private final WidgetInspector inspector;
|
||||
|
||||
@Inject
|
||||
public WidgetInspectorOverlay(
|
||||
Client client,
|
||||
WidgetInspector inspector
|
||||
)
|
||||
{
|
||||
this.client = client;
|
||||
this.inspector = inspector;
|
||||
|
||||
setPosition(OverlayPosition.DYNAMIC);
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
setPriority(OverlayPriority.HIGHEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D g)
|
||||
{
|
||||
Widget w = inspector.getSelectedWidget();
|
||||
if (w != null)
|
||||
{
|
||||
Object wiw = w;
|
||||
if (inspector.getSelectedItem() != -1)
|
||||
{
|
||||
wiw = w.getWidgetItem(inspector.getSelectedItem());
|
||||
}
|
||||
|
||||
renderWiw(g, wiw, WidgetInspector.SELECTED_WIDGET_COLOR);
|
||||
}
|
||||
|
||||
if (inspector.isPickerSelected())
|
||||
{
|
||||
boolean menuOpen = client.isMenuOpen();
|
||||
|
||||
MenuEntry[] entries = client.getMenuEntries();
|
||||
for (int i = menuOpen ? 0 : entries.length - 1; i < entries.length; i++)
|
||||
{
|
||||
MenuEntry e = entries[i];
|
||||
|
||||
Object wiw = inspector.getWidgetOrWidgetItemForMenuOption(e.getOpcode(), e.getParam0(), e.getParam1());
|
||||
if (wiw == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Color color = inspector.colorForWidget(i, entries.length);
|
||||
renderWiw(g, wiw, color);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void renderWiw(Graphics2D g, Object wiw, Color color)
|
||||
{
|
||||
g.setColor(color);
|
||||
|
||||
if (wiw instanceof WidgetItem)
|
||||
{
|
||||
WidgetItem wi = (WidgetItem) wiw;
|
||||
Rectangle bounds = wi.getCanvasBounds();
|
||||
g.draw(bounds);
|
||||
|
||||
String text = wi.getId() + "";
|
||||
FontMetrics fm = g.getFontMetrics();
|
||||
Rectangle2D textBounds = fm.getStringBounds(text, g);
|
||||
|
||||
int textX = (int) (bounds.getX() + (bounds.getWidth() / 2) - (textBounds.getWidth() / 2));
|
||||
int textY = (int) (bounds.getY() + (bounds.getHeight() / 2) + (textBounds.getHeight() / 2));
|
||||
|
||||
g.setColor(Color.BLACK);
|
||||
g.drawString(text, textX + 1, textY + 1);
|
||||
g.setColor(Color.ORANGE);
|
||||
g.drawString(text, textX, textY);
|
||||
}
|
||||
else
|
||||
{
|
||||
Widget w = (Widget) wiw;
|
||||
g.draw(w.getBounds());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,9 +46,9 @@ import net.runelite.api.GameState;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.WorldType;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.ExperienceChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.client.RuneLiteProperties;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
@@ -175,7 +175,7 @@ public class DiscordPlugin extends Plugin
|
||||
{
|
||||
eventBus.subscribe(ConfigChanged.class, this, this::onConfigChanged);
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventBus.subscribe(ExperienceChanged.class, this, this::onExperienceChanged);
|
||||
eventBus.subscribe(StatChanged.class, this, this::onStatChanged);
|
||||
eventBus.subscribe(VarbitChanged.class, this, this::onVarbitChanged);
|
||||
eventBus.subscribe(DiscordReady.class, this, this::onDiscordReady);
|
||||
eventBus.subscribe(DiscordJoinRequest.class, this, this::onDiscordJoinRequest);
|
||||
@@ -222,17 +222,18 @@ public class DiscordPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private void onExperienceChanged(ExperienceChanged event)
|
||||
private void onStatChanged(StatChanged statChanged)
|
||||
{
|
||||
final int exp = client.getSkillExperience(event.getSkill());
|
||||
final Integer previous = skillExp.put(event.getSkill(), exp);
|
||||
final Skill skill = statChanged.getSkill();
|
||||
final int exp = statChanged.getXp();
|
||||
final Integer previous = skillExp.put(skill, exp);
|
||||
|
||||
if (previous == null || previous >= exp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
final DiscordGameEventType discordGameEventType = DiscordGameEventType.fromSkill(event.getSkill());
|
||||
final DiscordGameEventType discordGameEventType = DiscordGameEventType.fromSkill(skill);
|
||||
|
||||
if (discordGameEventType != null && this.showSkillingActivity)
|
||||
{
|
||||
@@ -398,7 +399,8 @@ public class DiscordPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
final int playerRegionID = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID();
|
||||
final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation());
|
||||
final int playerRegionID = worldPoint == null ? 0 : worldPoint.getRegionID();
|
||||
|
||||
if (playerRegionID == 0)
|
||||
{
|
||||
|
||||
@@ -38,12 +38,12 @@ import lombok.Getter;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
|
||||
@@ -45,7 +45,6 @@ import net.runelite.api.ItemID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.PlayerDespawned;
|
||||
@@ -56,6 +55,7 @@ import net.runelite.api.kit.KitType;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
|
||||
@@ -27,13 +27,16 @@
|
||||
package net.runelite.client.plugins.entityhider;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
@@ -41,10 +44,6 @@ import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Entity Hider",
|
||||
description = "Hide players, NPCs, and/or projectiles",
|
||||
@@ -91,13 +90,18 @@ public class EntityHiderPlugin extends Plugin
|
||||
{
|
||||
updateConfig();
|
||||
|
||||
if (event.getOldValue() == null || event.getNewValue() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getKey().equals("hideNPCsNames"))
|
||||
{
|
||||
List<String> oldList = Text.fromCSV(event.getOldValue());
|
||||
List<String> newList = Text.fromCSV(event.getNewValue());
|
||||
|
||||
ArrayList<String> removed = oldList.stream().filter(s -> !newList.contains(s)).collect(Collectors.toCollection(ArrayList::new));
|
||||
ArrayList<String> added = newList.stream().filter(s -> !oldList.contains(s)).collect(Collectors.toCollection(ArrayList::new));
|
||||
List<String> removed = oldList.stream().filter(s -> !newList.contains(s)).collect(Collectors.toCollection(ArrayList::new));
|
||||
List<String> added = newList.stream().filter(s -> !oldList.contains(s)).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
removed.forEach(client::removeHiddenNpcName);
|
||||
added.forEach(client::addHiddenNpcName);
|
||||
@@ -189,7 +193,8 @@ public class EntityHiderPlugin extends Plugin
|
||||
return true;
|
||||
}
|
||||
|
||||
final int playerRegionID = WorldPoint.fromLocalInstance(client, localPlayer.getLocalLocation()).getRegionID();
|
||||
final WorldPoint worldPoint = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation());
|
||||
final int playerRegionID = worldPoint == null ? 0 : worldPoint.getRegionID();
|
||||
|
||||
// 9520 = Castle Wars
|
||||
return playerRegionID != 9520;
|
||||
|
||||
@@ -44,15 +44,16 @@ import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.ItemDefinition;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.PlayerMenuOptionClicked;
|
||||
import net.runelite.api.kit.KitType;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.client.chat.ChatColorType;
|
||||
import net.runelite.client.chat.ChatMessageBuilder;
|
||||
import net.runelite.client.chat.ChatMessageManager;
|
||||
import net.runelite.client.chat.QueuedMessage;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.menus.MenuManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
@@ -61,7 +62,6 @@ import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.ui.ClientToolbar;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.api.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Equipment Inspector",
|
||||
|
||||
@@ -153,6 +153,10 @@ public class ExaminePlugin extends Plugin
|
||||
quantity = widgetItem != null && widgetItem.getId() >= 0 ? widgetItem.getQuantity() : 1;
|
||||
break;
|
||||
}
|
||||
case EXAMINE_ITEM_GROUND:
|
||||
type = ExamineType.ITEM;
|
||||
id = event.getIdentifier();
|
||||
break;
|
||||
case EXAMINE_ITEM_BANK_EQ:
|
||||
{
|
||||
type = ExamineType.ITEM_BANK_EQ;
|
||||
@@ -312,7 +316,9 @@ public class ExaminePlugin extends Plugin
|
||||
|| WidgetInfo.CLUE_SCROLL_REWARD_ITEM_CONTAINER.getGroupId() == widgetGroup
|
||||
|| WidgetInfo.LOOTING_BAG_CONTAINER.getGroupId() == widgetGroup
|
||||
|| WidgetID.SEED_VAULT_INVENTORY_GROUP_ID == widgetGroup
|
||||
|| WidgetID.SEED_BOX_GROUP_ID == widgetGroup)
|
||||
|| WidgetID.SEED_BOX_GROUP_ID == widgetGroup
|
||||
|| WidgetID.PLAYER_TRADE_SCREEN_GROUP_ID == widgetGroup
|
||||
|| WidgetID.PLAYER_TRADE_INVENTORY_GROUP_ID == widgetGroup)
|
||||
{
|
||||
Widget[] children = widget.getDynamicChildren();
|
||||
if (actionParam < children.length)
|
||||
|
||||
@@ -29,8 +29,6 @@ package net.runelite.client.plugins.experiencedrop;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.IntStream;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@@ -45,8 +43,6 @@ import net.runelite.api.Skill;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.WorldType;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.ExperienceChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.ScriptCallbackEvent;
|
||||
@@ -56,7 +52,9 @@ import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.NPCManager;
|
||||
import net.runelite.client.game.XpDropEvent;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
@@ -65,30 +63,23 @@ import net.runelite.client.util.ColorUtil;
|
||||
@PluginDescriptor(
|
||||
name = "XP Drop",
|
||||
description = "Enable customization of the way XP drops are displayed",
|
||||
tags = {"experience", "levels", "tick"}
|
||||
)
|
||||
tags = {"experience", "levels", "tick"})
|
||||
@Singleton
|
||||
public class XpDropPlugin extends Plugin
|
||||
{
|
||||
private static final int XPDROP_PADDING = 2; // space between xp drop icons
|
||||
private static final double HITPOINT_RATIO = 1.33; // Base rate of hp xp per point damage
|
||||
private static final double DMM_MULTIPLIER_RATIO = 10;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
private XpDropConfig config;
|
||||
|
||||
@Inject
|
||||
private NPCManager npcManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Inject
|
||||
private XpDropOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private EventBus eventBus;
|
||||
|
||||
@@ -106,16 +97,15 @@ public class XpDropPlugin extends Plugin
|
||||
private boolean hasDropped = false;
|
||||
private boolean correctPrayer;
|
||||
private Skill lastSkill = null;
|
||||
private final Map<Skill, Integer> previousSkillExpTable = new EnumMap<>(Skill.class);
|
||||
private PrayerType currentTickPrayer;
|
||||
private XpDropConfig.DamageMode damageMode;
|
||||
|
||||
private boolean hideSkillIcons;
|
||||
private Color getMeleePrayerColor;
|
||||
private Color getRangePrayerColor;
|
||||
private Color getMagePrayerColor;
|
||||
private int fakeXpDropDelay;
|
||||
private XpDropConfig.DamageMode showdamagedrops;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Color damageColor;
|
||||
|
||||
@@ -153,10 +143,17 @@ public class XpDropPlugin extends Plugin
|
||||
eventBus.subscribe(GameStateChanged.class, this, this::onGameStateChanged);
|
||||
eventBus.subscribe(WidgetHiddenChanged.class, this, this::onWidgetHiddenChanged);
|
||||
eventBus.subscribe(GameTick.class, this, this::onGameTick);
|
||||
eventBus.subscribe(ExperienceChanged.class, this, this::onExperienceChanged);
|
||||
eventBus.subscribe(XpDropEvent.class, this, this::onXpDropEvent);
|
||||
eventBus.subscribe(ScriptCallbackEvent.class, this, this::onScriptCallbackEvent);
|
||||
}
|
||||
|
||||
private void onXpDropEvent(XpDropEvent event)
|
||||
{
|
||||
previousExpGained = event.getExp();
|
||||
lastSkill = event.getSkill();
|
||||
hasDropped = true;
|
||||
}
|
||||
|
||||
private void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (!event.getGroup().equals("xpdrop"))
|
||||
@@ -188,8 +185,8 @@ public class XpDropPlugin extends Plugin
|
||||
|
||||
private void onGameStateChanged(GameStateChanged event)
|
||||
{
|
||||
damage = 0;
|
||||
tickShow = 0;
|
||||
damage = 0;
|
||||
}
|
||||
|
||||
private void onWidgetHiddenChanged(WidgetHiddenChanged event)
|
||||
@@ -269,9 +266,12 @@ public class XpDropPlugin extends Plugin
|
||||
switch (prayer)
|
||||
{
|
||||
case MELEE:
|
||||
if (spriteIDs.anyMatch(id ->
|
||||
id == SpriteID.SKILL_ATTACK || id == SpriteID.SKILL_STRENGTH || id == SpriteID.SKILL_DEFENCE
|
||||
|| correctPrayer))
|
||||
if (spriteIDs.anyMatch(
|
||||
id ->
|
||||
id == SpriteID.SKILL_ATTACK
|
||||
|| id == SpriteID.SKILL_STRENGTH
|
||||
|| id == SpriteID.SKILL_DEFENCE
|
||||
|| correctPrayer))
|
||||
{
|
||||
color = this.getMeleePrayerColor.getRGB();
|
||||
correctPrayer = true;
|
||||
@@ -351,21 +351,6 @@ public class XpDropPlugin extends Plugin
|
||||
client.runScript(XPDROP_DISABLED, lastSkill.ordinal(), previousExpGained);
|
||||
}
|
||||
|
||||
private void onExperienceChanged(ExperienceChanged event)
|
||||
{
|
||||
final Skill skill = event.getSkill();
|
||||
final int xp = client.getSkillExperience(skill);
|
||||
|
||||
lastSkill = skill;
|
||||
|
||||
Integer previous = previousSkillExpTable.put(skill, xp);
|
||||
if (previous != null)
|
||||
{
|
||||
previousExpGained = xp - previous;
|
||||
hasDropped = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void onScriptCallbackEvent(ScriptCallbackEvent e)
|
||||
{
|
||||
if (this.showdamagedrops == XpDropConfig.DamageMode.NONE)
|
||||
@@ -393,8 +378,6 @@ public class XpDropPlugin extends Plugin
|
||||
final int exp = intStack[intStackSize - 1];
|
||||
calculateDamageDealt(exp);
|
||||
}
|
||||
|
||||
client.setIntStackSize(intStackSize - 2);
|
||||
}
|
||||
else if (eventName.equals("hpXpGained"))
|
||||
{
|
||||
@@ -404,16 +387,19 @@ public class XpDropPlugin extends Plugin
|
||||
final int exp = intStack[intStackSize - 1];
|
||||
calculateDamageDealt(exp);
|
||||
}
|
||||
else if (eventName.equals("xpDropAddDamage") &&
|
||||
damageMode == XpDropConfig.DamageMode.IN_XP_DROP &&
|
||||
damage > 0)
|
||||
else if (eventName.equals("xpDropAddDamage")
|
||||
&& damageMode == XpDropConfig.DamageMode.IN_XP_DROP
|
||||
&& damage > 0)
|
||||
{
|
||||
final String[] stringStack = client.getStringStack();
|
||||
final int stringStackSize = client.getStringStackSize();
|
||||
|
||||
String builder = stringStack[stringStackSize - 1] +
|
||||
ColorUtil.colorTag(this.damageColor) +
|
||||
" (" + damage + ")";
|
||||
String builder =
|
||||
stringStack[stringStackSize - 1]
|
||||
+ ColorUtil.colorTag(this.damageColor)
|
||||
+ " ("
|
||||
+ damage
|
||||
+ ")";
|
||||
stringStack[stringStackSize - 1] = builder;
|
||||
}
|
||||
}
|
||||
@@ -431,7 +417,8 @@ public class XpDropPlugin extends Plugin
|
||||
Actor a = client.getLocalPlayer().getInteracting();
|
||||
if (!(a instanceof NPC) && !(a instanceof Player))
|
||||
{
|
||||
// If we are interacting with nothing we may have clicked away at the perfect time fall back to last tick
|
||||
// If we are interacting with nothing we may have clicked away at the perfect time fall back
|
||||
// to last tick
|
||||
if (!(lastOpponent instanceof NPC) && !(lastOpponent instanceof Player))
|
||||
{
|
||||
damage = (int) Math.rint(damageDealt);
|
||||
|
||||
@@ -44,10 +44,10 @@ import net.runelite.api.ScriptID;
|
||||
import net.runelite.api.SoundEffectID;
|
||||
import net.runelite.api.SpriteID;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.widgets.JavaScriptCallback;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
@@ -56,11 +56,11 @@ import net.runelite.api.widgets.WidgetType;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.chatbox.ChatboxPanelManager;
|
||||
import net.runelite.client.game.chatbox.ChatboxTextInput;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.api.util.Text;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
|
||||
@@ -35,7 +35,7 @@ import java.util.function.Supplier;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
|
||||
@@ -46,13 +46,13 @@ import net.runelite.api.GameState;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
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;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.game.NPCManager;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.fishing;
|
||||
|
||||
import java.awt.Color;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
@@ -76,7 +77,40 @@ public interface FishingConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 4,
|
||||
keyName = "overlayColor",
|
||||
name = "Overlay Color",
|
||||
description = "Color of overlays",
|
||||
position = 4
|
||||
)
|
||||
default Color getOverlayColor()
|
||||
{
|
||||
return Color.CYAN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "minnowsOverlayColor",
|
||||
name = "Minnows Overlay Color",
|
||||
description = "Color of overlays for Minnows",
|
||||
position = 5
|
||||
)
|
||||
default Color getMinnowsOverlayColor()
|
||||
{
|
||||
return Color.RED;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "aerialOverlayColor",
|
||||
name = "Aerial Overlay Color",
|
||||
description = "Color of overlays when 1-tick aerial fishing",
|
||||
position = 6
|
||||
)
|
||||
default Color getAerialOverlayColor()
|
||||
{
|
||||
return Color.GREEN;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 7,
|
||||
keyName = "statTimeout",
|
||||
name = "Reset stats (minutes)",
|
||||
description = "The time until fishing session data is reset in minutes."
|
||||
@@ -87,7 +121,7 @@ public interface FishingConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 5,
|
||||
position = 8,
|
||||
keyName = "showFishingStats",
|
||||
name = "Show Fishing session stats",
|
||||
description = "Display the fishing session stats."
|
||||
@@ -98,7 +132,7 @@ public interface FishingConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 6,
|
||||
position = 9,
|
||||
keyName = "showMinnowOverlay",
|
||||
name = "Show Minnow Movement overlay",
|
||||
description = "Display the minnow progress pie overlay."
|
||||
@@ -109,7 +143,7 @@ public interface FishingConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 7,
|
||||
position = 10,
|
||||
keyName = "trawlerNotification",
|
||||
name = "Trawler activity notification",
|
||||
description = "Send a notification when fishing trawler activity drops below 15%."
|
||||
@@ -120,7 +154,7 @@ public interface FishingConfig extends Config
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 8,
|
||||
position = 11,
|
||||
keyName = "trawlerTimer",
|
||||
name = "Trawler timer in MM:SS",
|
||||
description = "Trawler Timer will display a more accurate timer in MM:SS format."
|
||||
|
||||
@@ -31,6 +31,7 @@ import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GraphicID;
|
||||
import static net.runelite.api.MenuOpcode.RUNELITE_OVERLAY;
|
||||
import static net.runelite.api.MenuOpcode.RUNELITE_OVERLAY_CONFIG;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerService;
|
||||
@@ -47,6 +48,7 @@ import net.runelite.client.ui.overlay.components.table.TableComponent;
|
||||
class FishingOverlay extends Overlay
|
||||
{
|
||||
private static final String FISHING_SPOT = "Fishing spot";
|
||||
static final String FISHING_RESET = "Reset";
|
||||
|
||||
private final Client client;
|
||||
private final FishingPlugin plugin;
|
||||
@@ -63,6 +65,7 @@ class FishingOverlay extends Overlay
|
||||
this.plugin = plugin;
|
||||
this.xpTrackerService = xpTrackerService;
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Fishing overlay"));
|
||||
getMenuEntries().add(new OverlayMenuEntry(RUNELITE_OVERLAY, FISHING_RESET, "Fishing overlay"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,6 +27,7 @@ package net.runelite.client.plugins.fishing;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
@@ -46,11 +47,11 @@ import net.runelite.api.GameState;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.coords.LocalPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.InteractingChanged;
|
||||
@@ -65,11 +66,14 @@ import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.Notifier;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.events.OverlayMenuClicked;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDependency;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.xptracker.XpTrackerPlugin;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.OverlayMenuEntry;
|
||||
import net.runelite.client.util.ItemUtil;
|
||||
|
||||
@PluginDescriptor(
|
||||
@@ -157,6 +161,12 @@ public class FishingPlugin extends Plugin
|
||||
private boolean showMinnowOverlay;
|
||||
private boolean trawlerNotification;
|
||||
private boolean trawlerTimer;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Color overlayColor;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Color minnowsOverlayColor;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private Color aerialOverlayColor;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
@@ -198,6 +208,18 @@ public class FishingPlugin extends Plugin
|
||||
eventBus.subscribe(NpcDespawned.class, this, this::onNpcDespawned);
|
||||
eventBus.subscribe(VarbitChanged.class, this, this::onVarbitChanged);
|
||||
eventBus.subscribe(WidgetLoaded.class, this, this::onWidgetLoaded);
|
||||
eventBus.subscribe(OverlayMenuClicked.class, this, this::onOverlayMenuClicked);
|
||||
}
|
||||
|
||||
private void onOverlayMenuClicked(OverlayMenuClicked overlayMenuClicked)
|
||||
{
|
||||
OverlayMenuEntry overlayMenuEntry = overlayMenuClicked.getEntry();
|
||||
if (overlayMenuEntry.getMenuOpcode() == MenuOpcode.RUNELITE_OVERLAY
|
||||
&& overlayMenuClicked.getEntry().getOption().equals(FishingOverlay.FISHING_RESET)
|
||||
&& overlayMenuClicked.getOverlay() == overlay)
|
||||
{
|
||||
session.setLastFishCaught(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void onConfigChanged(ConfigChanged event)
|
||||
@@ -404,6 +426,7 @@ public class FishingPlugin extends Plugin
|
||||
if (regionID != TRAWLER_SHIP_REGION_NORMAL && regionID != TRAWLER_SHIP_REGION_SINKING)
|
||||
{
|
||||
log.debug("Trawler session ended");
|
||||
trawlerStartTime = null;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -477,5 +500,8 @@ public class FishingPlugin extends Plugin
|
||||
this.showMinnowOverlay = config.showMinnowOverlay();
|
||||
this.trawlerNotification = config.trawlerNotification();
|
||||
this.trawlerTimer = config.trawlerTimer();
|
||||
this.overlayColor = config.getOverlayColor();
|
||||
this.minnowsOverlayColor = config.getMinnowsOverlayColor();
|
||||
this.aerialOverlayColor = config.getAerialOverlayColor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,9 @@ class FishingSpotMinimapOverlay extends Overlay
|
||||
continue;
|
||||
}
|
||||
|
||||
Color color = npc.getSpotAnimation() == GraphicID.FLYING_FISH ? Color.RED : Color.CYAN;
|
||||
Color color = npc.getSpotAnimation() == GraphicID.FLYING_FISH
|
||||
? plugin.getMinnowsOverlayColor()
|
||||
: plugin.getOverlayColor();
|
||||
|
||||
net.runelite.api.Point minimapLocation = npc.getMinimapLocation();
|
||||
if (minimapLocation != null)
|
||||
|
||||
@@ -107,15 +107,15 @@ class FishingSpotOverlay extends Overlay
|
||||
Color color;
|
||||
if (npc.getSpotAnimation() == GraphicID.FLYING_FISH)
|
||||
{
|
||||
color = Color.RED;
|
||||
color = plugin.getMinnowsOverlayColor();
|
||||
}
|
||||
else if (spot == FishingSpot.COMMON_TENCH && npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING)
|
||||
{
|
||||
color = Color.GREEN;
|
||||
color = plugin.getAerialOverlayColor();
|
||||
}
|
||||
else
|
||||
{
|
||||
color = Color.CYAN;
|
||||
color = plugin.getOverlayColor();
|
||||
}
|
||||
|
||||
if (spot == FishingSpot.MINNOW && plugin.isShowMinnowOverlay())
|
||||
@@ -161,7 +161,7 @@ class FishingSpotOverlay extends Overlay
|
||||
if (spot == FishingSpot.COMMON_TENCH
|
||||
&& npc.getWorldLocation().distanceTo2D(client.getLocalPlayer().getWorldLocation()) <= ONE_TICK_AERIAL_FISHING)
|
||||
{
|
||||
fishImage = ImageUtil.outlineImage(itemManager.getImage(spot.getFishSpriteId()), Color.GREEN);
|
||||
fishImage = ImageUtil.outlineImage(itemManager.getImage(spot.getFishSpriteId()), color);
|
||||
}
|
||||
|
||||
if (fishImage != null)
|
||||
|
||||
@@ -29,10 +29,10 @@ import com.google.inject.Provides;
|
||||
import com.google.inject.Singleton;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.FocusChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.DrawManager;
|
||||
|
||||
@@ -39,13 +39,13 @@ import net.runelite.api.Player;
|
||||
import net.runelite.api.WorldType;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.LocalPlayerDeath;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.SpotAnimationChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
|
||||
@@ -38,10 +38,11 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.Friend;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.Nameable;
|
||||
import net.runelite.api.events.FriendRemoved;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NameableNameChanged;
|
||||
import net.runelite.api.events.FriendRemoved;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
@@ -50,7 +51,6 @@ import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.util.ColorUtil;
|
||||
import net.runelite.api.util.Text;
|
||||
|
||||
@Slf4j
|
||||
@PluginDescriptor(
|
||||
|
||||
@@ -25,11 +25,12 @@ import net.runelite.api.Friend;
|
||||
import net.runelite.api.Ignore;
|
||||
import net.runelite.api.MenuOpcode;
|
||||
import net.runelite.api.Nameable;
|
||||
import net.runelite.api.events.FriendRemoved;
|
||||
import net.runelite.api.events.MenuEntryAdded;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NameableNameChanged;
|
||||
import net.runelite.api.events.FriendRemoved;
|
||||
import net.runelite.api.events.WidgetMenuOptionClicked;
|
||||
import net.runelite.api.util.Text;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
@@ -40,7 +41,6 @@ import net.runelite.client.menus.WidgetMenuOption;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.api.util.Text;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
@Slf4j
|
||||
|
||||
@@ -321,4 +321,16 @@ public interface GauntletConfig extends Config
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 21,
|
||||
keyName = "displayResources",
|
||||
name = "Show raw resources gathered",
|
||||
description = "Displays how much of each resource you have gathered.",
|
||||
titleSection = "resources"
|
||||
)
|
||||
default boolean displayGatheredResources()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import net.runelite.api.Client;
|
||||
import net.runelite.api.GameObject;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.HeadIcon;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCDefinition;
|
||||
import net.runelite.api.NpcID;
|
||||
@@ -50,14 +51,15 @@ import net.runelite.api.ObjectID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.Projectile;
|
||||
import net.runelite.api.ProjectileID;
|
||||
import net.runelite.api.Skill;
|
||||
import net.runelite.api.SoundEffectID;
|
||||
import net.runelite.api.Varbits;
|
||||
import net.runelite.api.events.AnimationChanged;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameObjectDespawned;
|
||||
import net.runelite.api.events.GameObjectSpawned;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.MenuOptionClicked;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.ProjectileSpawned;
|
||||
@@ -65,7 +67,11 @@ import net.runelite.api.events.VarbitChanged;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.events.ConfigChanged;
|
||||
import net.runelite.client.events.NpcLootReceived;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.SkillIconManager;
|
||||
import net.runelite.client.game.XpDropEvent;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
@@ -74,6 +80,8 @@ import static net.runelite.client.plugins.gauntlet.Hunllef.BossAttack.MAGIC;
|
||||
import static net.runelite.client.plugins.gauntlet.Hunllef.BossAttack.PRAYER;
|
||||
import static net.runelite.client.plugins.gauntlet.Hunllef.BossAttack.RANGE;
|
||||
import net.runelite.client.ui.overlay.OverlayManager;
|
||||
import net.runelite.client.ui.overlay.infobox.Counter;
|
||||
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Gauntlet",
|
||||
@@ -104,7 +112,8 @@ public class GauntletPlugin extends Plugin
|
||||
ObjectID.PHREN_ROOTS_36066, ObjectID.FISHING_SPOT_36068, ObjectID.FISHING_SPOT_35971, ObjectID.GRYM_ROOT, ObjectID.GRYM_ROOT_36070,
|
||||
ObjectID.LINUM_TIRINUM, ObjectID.LINUM_TIRINUM_36072
|
||||
);
|
||||
|
||||
private static final int GATHERING_HERB = 0;
|
||||
private static final int GATHERING_CLOTH = 1;
|
||||
@Inject
|
||||
@Getter(AccessLevel.NONE)
|
||||
private Client client;
|
||||
@@ -138,6 +147,10 @@ public class GauntletPlugin extends Plugin
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
@Nullable
|
||||
private Hunllef hunllef;
|
||||
@Inject
|
||||
private InfoBoxManager infoBoxManager;
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
private boolean attackVisualOutline;
|
||||
private boolean completeStartup = false;
|
||||
private boolean displayTimerChat;
|
||||
@@ -160,11 +173,24 @@ public class GauntletPlugin extends Plugin
|
||||
private final Map<String, Integer> items = new HashMap<>();
|
||||
private final Set<Missiles> projectiles = new HashSet<>();
|
||||
private final Set<Resources> resources = new HashSet<>();
|
||||
|
||||
private GauntletConfig.CounterDisplay countAttacks;
|
||||
private int resourceIconSize;
|
||||
private Set<Tornado> tornadoes = new HashSet<>();
|
||||
private int projectileIconSize;
|
||||
|
||||
private boolean displayResources;
|
||||
private Counter oreCounter;
|
||||
private Counter woodCounter;
|
||||
private Counter clothCounter;
|
||||
private Counter fishCounter;
|
||||
private Counter herbCounter;
|
||||
private int oresGathered;
|
||||
private int woodGathered;
|
||||
private int clothGathered;
|
||||
private int fishGathered;
|
||||
private int herbGathered;
|
||||
private int currentFarmingAction = -1;
|
||||
private boolean countersVisible = false;
|
||||
|
||||
@Provides
|
||||
GauntletConfig getConfig(ConfigManager configManager)
|
||||
@@ -177,6 +203,7 @@ public class GauntletPlugin extends Plugin
|
||||
{
|
||||
addSubscriptions();
|
||||
updateConfig();
|
||||
initializeCounters();
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(infoboxoverlay);
|
||||
overlayManager.add(GauntletCounter);
|
||||
@@ -189,7 +216,8 @@ public class GauntletPlugin extends Plugin
|
||||
if (client.getGameState() != GameState.STARTING && client.getGameState() != GameState.UNKNOWN)
|
||||
{
|
||||
completeStartup = false;
|
||||
clientThread.invoke(() -> {
|
||||
clientThread.invoke(() ->
|
||||
{
|
||||
timer.initStates();
|
||||
completeStartup = true;
|
||||
});
|
||||
@@ -200,6 +228,47 @@ public class GauntletPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
private void addCounters()
|
||||
{
|
||||
if (!countersVisible)
|
||||
{
|
||||
infoBoxManager.addInfoBox(oreCounter);
|
||||
infoBoxManager.addInfoBox(woodCounter);
|
||||
infoBoxManager.addInfoBox(clothCounter);
|
||||
infoBoxManager.addInfoBox(fishCounter);
|
||||
infoBoxManager.addInfoBox(herbCounter);
|
||||
countersVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeCounters()
|
||||
{
|
||||
resetGatheringCounters();
|
||||
oreCounter = new Counter(itemManager.getImage(ItemID.CORRUPTED_ORE), this, 0);
|
||||
woodCounter = new Counter(itemManager.getImage(ItemID.PHREN_BARK_23878), this, 0);
|
||||
clothCounter = new Counter(itemManager.getImage(ItemID.LINUM_TIRINUM_23876), this, 0);
|
||||
fishCounter = new Counter(itemManager.getImage(ItemID.RAW_PADDLEFISH), this, 0);
|
||||
herbCounter = new Counter(itemManager.getImage(ItemID.GRYM_LEAF_23875), this, 0);
|
||||
}
|
||||
|
||||
private void resetGatheringCounters()
|
||||
{
|
||||
oresGathered = 0;
|
||||
fishGathered = 0;
|
||||
woodGathered = 0;
|
||||
clothGathered = 0;
|
||||
herbGathered = 0;
|
||||
}
|
||||
|
||||
private void updateCounters()
|
||||
{
|
||||
oreCounter.setCount(oresGathered);
|
||||
woodCounter.setCount(woodGathered);
|
||||
clothCounter.setCount(clothGathered);
|
||||
fishCounter.setCount(fishGathered);
|
||||
herbCounter.setCount(herbGathered);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
@@ -213,12 +282,24 @@ public class GauntletPlugin extends Plugin
|
||||
overlayManager.remove(overlay);
|
||||
overlayManager.remove(infoboxoverlay);
|
||||
overlayManager.remove(GauntletCounter);
|
||||
removeCounters();
|
||||
resetGatheringCounters();
|
||||
resources.clear();
|
||||
projectiles.clear();
|
||||
tornadoes.clear();
|
||||
setHunllef(null);
|
||||
}
|
||||
|
||||
private void removeCounters()
|
||||
{
|
||||
infoBoxManager.removeInfoBox(oreCounter);
|
||||
infoBoxManager.removeInfoBox(woodCounter);
|
||||
infoBoxManager.removeInfoBox(clothCounter);
|
||||
infoBoxManager.removeInfoBox(fishCounter);
|
||||
infoBoxManager.removeInfoBox(herbCounter);
|
||||
countersVisible = false;
|
||||
}
|
||||
|
||||
private void addSubscriptions()
|
||||
{
|
||||
eventBus.subscribe(AnimationChanged.class, this, this::onAnimationChanged);
|
||||
@@ -231,6 +312,56 @@ public class GauntletPlugin extends Plugin
|
||||
eventBus.subscribe(NpcSpawned.class, this, this::onNpcSpawned);
|
||||
eventBus.subscribe(ProjectileSpawned.class, this, this::onProjectileSpawned);
|
||||
eventBus.subscribe(VarbitChanged.class, this, this::onVarbitChanged);
|
||||
eventBus.subscribe(XpDropEvent.class, this, this::onXpDropEvent);
|
||||
eventBus.subscribe(NpcLootReceived.class, this, this::onNpcLootReceived);
|
||||
eventBus.subscribe(MenuOptionClicked.class, this, this::onMenuOptionClicked);
|
||||
}
|
||||
|
||||
private void onMenuOptionClicked(MenuOptionClicked menuOptionClicked)
|
||||
{
|
||||
if (menuOptionClicked.getTarget().toUpperCase().contains("LINUM"))
|
||||
{
|
||||
currentFarmingAction = GATHERING_CLOTH;
|
||||
}
|
||||
if (menuOptionClicked.getTarget().toUpperCase().contains("GRYM"))
|
||||
{
|
||||
currentFarmingAction = GATHERING_HERB;
|
||||
}
|
||||
}
|
||||
|
||||
private void onNpcLootReceived(NpcLootReceived npcLootReceived)
|
||||
{
|
||||
fishGathered += (int) npcLootReceived.getItems().stream().filter(item -> item.getId() == ItemID.RAW_PADDLEFISH).count();
|
||||
herbGathered += (int) npcLootReceived.getItems().stream().filter(item -> item.getId() == ItemID.GRYM_LEAF || item.getId() == ItemID.GRYM_LEAF_23875).count();
|
||||
updateCounters();
|
||||
}
|
||||
|
||||
private void onXpDropEvent(XpDropEvent experienceChanged)
|
||||
{
|
||||
if (experienceChanged.getSkill().compareTo(Skill.MINING) == 0)
|
||||
{
|
||||
oresGathered++;
|
||||
}
|
||||
if (experienceChanged.getSkill().compareTo(Skill.WOODCUTTING) == 0)
|
||||
{
|
||||
woodGathered++;
|
||||
}
|
||||
if (experienceChanged.getSkill().compareTo(Skill.FARMING) == 0)
|
||||
{
|
||||
if (currentFarmingAction == GATHERING_HERB)
|
||||
{
|
||||
herbGathered++;
|
||||
}
|
||||
else if (currentFarmingAction == GATHERING_CLOTH)
|
||||
{
|
||||
clothGathered++;
|
||||
}
|
||||
}
|
||||
if (experienceChanged.getSkill().compareTo(Skill.FISHING) == 0)
|
||||
{
|
||||
fishGathered++;
|
||||
}
|
||||
updateCounters();
|
||||
}
|
||||
|
||||
private void onAnimationChanged(AnimationChanged event)
|
||||
@@ -248,7 +379,7 @@ public class GauntletPlugin extends Plugin
|
||||
final Player player = (Player) actor;
|
||||
final int anim = player.getAnimation();
|
||||
|
||||
if (!player.getName().equals(client.getLocalPlayer().getName()) || anim == -1 || !PLAYER_ANIMATIONS.contains(anim))
|
||||
if (player.getName() == null || client.getLocalPlayer() == null || !player.getName().equals(client.getLocalPlayer().getName()) || anim == -1 || !PLAYER_ANIMATIONS.contains(anim))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -325,6 +456,18 @@ public class GauntletPlugin extends Plugin
|
||||
timerVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getKey().equals("displayResources"))
|
||||
{
|
||||
if (this.displayResources && this.startedGauntlet())
|
||||
{
|
||||
addCounters();
|
||||
}
|
||||
else
|
||||
{
|
||||
removeCounters();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onGameObjectDespawned(GameObjectDespawned event)
|
||||
@@ -379,6 +522,7 @@ public class GauntletPlugin extends Plugin
|
||||
if (HUNLLEF_NPC_IDS.contains(npc.getId()))
|
||||
{
|
||||
setHunllef(null);
|
||||
resetGatheringCounters();
|
||||
}
|
||||
else if (TORNADO_NPC_IDS.contains(npc.getId()))
|
||||
{
|
||||
@@ -436,6 +580,14 @@ public class GauntletPlugin extends Plugin
|
||||
{
|
||||
timer.checkStates(true);
|
||||
}
|
||||
if (startedGauntlet() && displayResources)
|
||||
{
|
||||
addCounters();
|
||||
}
|
||||
else
|
||||
{
|
||||
removeCounters();
|
||||
}
|
||||
}
|
||||
|
||||
boolean fightingBoss()
|
||||
@@ -468,5 +620,6 @@ public class GauntletPlugin extends Plugin
|
||||
this.displayTimerChat = config.displayTimerChat();
|
||||
this.attackVisualOutline = config.attackVisualOutline();
|
||||
this.highlightPrayerInfobox = config.highlightPrayerInfobox();
|
||||
this.displayResources = config.displayGatheredResources();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user