Overhaul (#349)
* Mini GPU overhaul * Alch value * Stoned Loot Tracker (persistent loot tracker) * Checkstyle * Added back max values to GPU plugin * Persistent loot tracker config options * Zulrah plugin type * Add inventory highlight plugin When dragging an item in the inventory, a highlight will show up to help the player place the item in the correct slot, instead of missing when they drag the item to the "gutter" * Fix inventory highlight plugin * Inventory highlight plugin type * Inventory highlight config options * Fix ess pouch swapping * Runecraftig config options * Add plugin type to persistient loot tracker * Fix panel repaint * Disable this for now * Revert "Fix ess pouch swapping" -> PR #351 This reverts commit c18f65069f5df3a1cafb983af5b3e162817a22fe. * I blame intellij for this * Fix test
This commit is contained in:
@@ -187,6 +187,9 @@ public class ItemManager
|
||||
private final Color outlineColor;
|
||||
}
|
||||
|
||||
// Used when getting High Alchemy value - multiplied by general store price.
|
||||
private static final float HIGH_ALCHEMY_CONSTANT = 0.6f;
|
||||
|
||||
private final Client client;
|
||||
private final ScheduledExecutorService scheduledExecutorService;
|
||||
private final ClientThread clientThread;
|
||||
@@ -411,6 +414,27 @@ public class ItemManager
|
||||
return price;
|
||||
}
|
||||
|
||||
public int getAlchValue(int itemID)
|
||||
{
|
||||
if (itemID == ItemID.COINS_995)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (itemID == ItemID.PLATINUM_TOKEN)
|
||||
{
|
||||
return 1000;
|
||||
}
|
||||
|
||||
float alchValue = getItemComposition(itemID).getPrice() * HIGH_ALCHEMY_CONSTANT;
|
||||
|
||||
/*
|
||||
* If the alch value is below 1, do not round up, return 0 instead.
|
||||
* For example bones have a base price of 1, multiplied by 0.6 will be 0.6,
|
||||
* if rounded up, the alch price will be 1, when it should be 0.
|
||||
*/
|
||||
return alchValue < 1 ? 0 : Math.round(alchValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up an item's stats
|
||||
*
|
||||
|
||||
@@ -36,7 +36,6 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.Item;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.ItemID;
|
||||
import static net.runelite.api.ItemID.COINS_995;
|
||||
@@ -47,7 +46,6 @@ import net.runelite.client.game.ItemManager;
|
||||
@Slf4j
|
||||
class BankCalculation
|
||||
{
|
||||
private static final float HIGH_ALCHEMY_CONSTANT = 0.6f;
|
||||
private static final ImmutableList<Varbits> TAB_VARBITS = ImmutableList.of(
|
||||
Varbits.BANK_TAB_ONE_COUNT,
|
||||
Varbits.BANK_TAB_TWO_COUNT,
|
||||
@@ -144,8 +142,6 @@ class BankCalculation
|
||||
continue;
|
||||
}
|
||||
|
||||
final ItemComposition itemComposition = itemManager.getItemComposition(item.getId());
|
||||
|
||||
if (config.showGE())
|
||||
{
|
||||
itemIds.add(item.getId());
|
||||
@@ -153,12 +149,11 @@ class BankCalculation
|
||||
|
||||
if (config.showHA())
|
||||
{
|
||||
int price = itemComposition.getPrice();
|
||||
long alchValue = itemManager.getAlchValue(item.getId());
|
||||
|
||||
if (price > 0)
|
||||
if (alchValue > 0)
|
||||
{
|
||||
haPrice += (long) Math.round(price * HIGH_ALCHEMY_CONSTANT) *
|
||||
(long) quantity;
|
||||
haPrice += alchValue * quantity;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,6 @@ import org.apache.commons.text.WordUtils;
|
||||
@Slf4j
|
||||
public class ChatCommandsPlugin extends Plugin
|
||||
{
|
||||
private static final float HIGH_ALCHEMY_CONSTANT = 0.6f;
|
||||
private static final Pattern KILLCOUNT_PATTERN = Pattern.compile("Your (.+) (?:kill|harvest) count is: <col=ff0000>(\\d+)</col>");
|
||||
private static final Pattern RAIDS_PATTERN = Pattern.compile("Your completed (.+) count is: <col=ff0000>(\\d+)</col>");
|
||||
private static final Pattern WINTERTODT_PATTERN = Pattern.compile("Your subdued Wintertodt count is: <col=ff0000>(\\d+)</col>");
|
||||
@@ -686,7 +685,7 @@ public class ChatCommandsPlugin extends Plugin
|
||||
}
|
||||
|
||||
int itemId = item.getId();
|
||||
int itemPrice = item.getPrice();
|
||||
int itemPrice = itemManager.getItemPrice(itemId);
|
||||
|
||||
final ChatMessageBuilder builder = new ChatMessageBuilder();
|
||||
builder.append(ChatColorType.NORMAL);
|
||||
@@ -704,7 +703,7 @@ public class ChatCommandsPlugin extends Plugin
|
||||
ItemComposition itemComposition = itemManager.getItemComposition(itemId);
|
||||
if (itemComposition != null)
|
||||
{
|
||||
int alchPrice = Math.round(itemComposition.getPrice() * HIGH_ALCHEMY_CONSTANT);
|
||||
int alchPrice = itemManager.getAlchValue(itemId);
|
||||
builder
|
||||
.append(ChatColorType.NORMAL)
|
||||
.append(" HA value ")
|
||||
|
||||
@@ -71,7 +71,6 @@ import net.runelite.http.api.osbuddy.OSBGrandExchangeResult;
|
||||
@Slf4j
|
||||
public class ExaminePlugin extends Plugin
|
||||
{
|
||||
private static final float HIGH_ALCHEMY_CONSTANT = 0.6f;
|
||||
private static final Pattern X_PATTERN = Pattern.compile("^\\d+ x ");
|
||||
|
||||
private final Deque<PendingExamine> pending = new ArrayDeque<>();
|
||||
@@ -323,7 +322,7 @@ public class ExaminePlugin extends Plugin
|
||||
quantity = Math.max(1, quantity);
|
||||
int itemCompositionPrice = itemComposition.getPrice();
|
||||
final int gePrice = itemManager.getItemPrice(id);
|
||||
final int alchPrice = itemCompositionPrice <= 0 ? 0 : Math.round(itemCompositionPrice * HIGH_ALCHEMY_CONSTANT);
|
||||
final int alchPrice = itemCompositionPrice <= 0 ? 0 : itemManager.getAlchValue(id);
|
||||
|
||||
if (gePrice > 0 || alchPrice > 0)
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ class GLUtil
|
||||
private static final int ERR_LEN = 1024;
|
||||
|
||||
private static final int[] buf = new int[1];
|
||||
private static final float[] fbuf = new float[1];
|
||||
|
||||
static int glGetInteger(GL4 gl, int pname)
|
||||
{
|
||||
@@ -42,6 +43,12 @@ class GLUtil
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
static float glGetFloat(GL4 gl, int pname)
|
||||
{
|
||||
gl.glGetFloatv(pname, fbuf, 0);
|
||||
return fbuf[0];
|
||||
}
|
||||
|
||||
static int glGetShader(GL4 gl, int shader, int pname)
|
||||
{
|
||||
gl.glGetShaderiv(shader, pname, buf, 0);
|
||||
@@ -201,4 +208,4 @@ class GLUtil
|
||||
Scanner scanner = new Scanner(in).useDelimiter("\\A");
|
||||
return scanner.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,18 +74,8 @@ 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 static net.runelite.client.plugins.gpu.GLUtil.glDeleteBuffer;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteFrameBuffer;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteRenderbuffers;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteTexture;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glDeleteVertexArrays;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glGenBuffers;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glGenFrameBuffer;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glGenRenderbuffer;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glGenTexture;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glGenVertexArrays;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.glGetInteger;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.inputStreamToString;
|
||||
import static net.runelite.client.plugins.gpu.GLUtil.*;
|
||||
import net.runelite.client.plugins.gpu.config.AnisotropicFilteringMode;
|
||||
import net.runelite.client.plugins.gpu.config.AntiAliasingMode;
|
||||
import net.runelite.client.plugins.gpu.template.Template;
|
||||
import net.runelite.client.ui.DrawManager;
|
||||
@@ -102,7 +92,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
{
|
||||
// This is the maximum number of triangles the compute shaders support
|
||||
private static final int MAX_TRIANGLE = 4096;
|
||||
private static final int SMALL_TRIANGLE_COUNT = 512;
|
||||
static final int SMALL_TRIANGLE_COUNT = 512;
|
||||
private static final int FLAG_SCENE_BUFFER = Integer.MIN_VALUE;
|
||||
static final int MAX_DISTANCE = 90;
|
||||
static final int MAX_FOG_DEPTH = 100;
|
||||
@@ -215,6 +205,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
private int lastStretchedCanvasWidth;
|
||||
private int lastStretchedCanvasHeight;
|
||||
private AntiAliasingMode lastAntiAliasingMode;
|
||||
private AnisotropicFilteringMode lastAnisotropicFilteringMode;
|
||||
|
||||
private int centerX;
|
||||
private int centerY;
|
||||
@@ -223,6 +214,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
private int uniUseFog;
|
||||
private int uniFogColor;
|
||||
private int uniFogDepth;
|
||||
private int uniFogCornerRadius;
|
||||
private int uniFogDensity;
|
||||
private int uniDrawDistance;
|
||||
private int uniProjectionMatrix;
|
||||
private int uniBrightness;
|
||||
@@ -499,6 +492,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
uniUseFog = gl.glGetUniformLocation(glProgram, "useFog");
|
||||
uniFogColor = gl.glGetUniformLocation(glProgram, "fogColor");
|
||||
uniFogDepth = gl.glGetUniformLocation(glProgram, "fogDepth");
|
||||
uniFogCornerRadius = gl.glGetUniformLocation(glProgram, "fogCornerRadius");
|
||||
uniFogDensity = gl.glGetUniformLocation(glProgram, "fogDensity");
|
||||
uniDrawDistance = gl.glGetUniformLocation(glProgram, "drawDistance");
|
||||
|
||||
uniTex = gl.glGetUniformLocation(glUiProgram, "tex");
|
||||
@@ -524,8 +519,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
gl.glDeleteProgram(glProgram);
|
||||
glProgram = -1;
|
||||
|
||||
///
|
||||
|
||||
gl.glDeleteShader(glComputeShader);
|
||||
glComputeShader = -1;
|
||||
|
||||
@@ -544,8 +537,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
gl.glDeleteProgram(glUnorderedComputeProgram);
|
||||
glUnorderedComputeProgram = -1;
|
||||
|
||||
///
|
||||
|
||||
gl.glDeleteShader(glUiVertexShader);
|
||||
glUiVertexShader = -1;
|
||||
|
||||
@@ -635,7 +626,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
}
|
||||
uniformBuffer.flip();
|
||||
|
||||
gl.glBufferData(gl.GL_UNIFORM_BUFFER, uniformBuffer.limit() * Integer.BYTES, uniformBuffer, gl.GL_STATIC_DRAW);
|
||||
gl.glBufferData(gl.GL_UNIFORM_BUFFER, uniformBuffer.limit() * Integer.BYTES, uniformBuffer, gl.GL_DYNAMIC_DRAW);
|
||||
gl.glBindBuffer(gl.GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
@@ -985,6 +976,40 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
int renderViewportHeight = viewportHeight;
|
||||
int renderViewportWidth = viewportWidth;
|
||||
|
||||
// Setup anisotropic filtering
|
||||
final AnisotropicFilteringMode anisotropicFilteringMode = config.anisotropicFilteringMode();
|
||||
final boolean afEnabled = anisotropicFilteringMode != anisotropicFilteringMode.DISABLED;
|
||||
|
||||
if (lastAnisotropicFilteringMode != anisotropicFilteringMode)
|
||||
{
|
||||
if (afEnabled)
|
||||
{
|
||||
switch (anisotropicFilteringMode)
|
||||
{
|
||||
case BILINEAR:
|
||||
gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_NEAREST);
|
||||
break;
|
||||
case TRILINEAR:
|
||||
gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_LINEAR);
|
||||
break;
|
||||
default:
|
||||
final float maxSamples = glGetFloat(gl, gl.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
|
||||
final float samples = Math.min(anisotropicFilteringMode.getSamples(), maxSamples);
|
||||
gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_LINEAR);
|
||||
gl.glTexParameterf(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MAX_ANISOTROPY_EXT, samples);
|
||||
break;
|
||||
}
|
||||
|
||||
gl.glGenerateMipmap(gl.GL_TEXTURE_2D_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
gl.glTexParameteri(gl.GL_TEXTURE_2D_ARRAY, gl.GL_TEXTURE_MIN_FILTER, gl.GL_NEAREST);
|
||||
}
|
||||
}
|
||||
|
||||
lastAnisotropicFilteringMode = anisotropicFilteringMode;
|
||||
|
||||
if (client.isStretchedEnabled())
|
||||
{
|
||||
Dimension dim = client.getStretchedDimensions();
|
||||
@@ -1011,9 +1036,12 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
|
||||
final int drawDistance = Math.max(0, Math.min(MAX_DISTANCE, config.drawDistance()));
|
||||
final int fogDepth = config.fogDepth();
|
||||
float effectiveDrawDistance = Perspective.LOCAL_TILE_SIZE * Math.min(Constants.SCENE_SIZE / 2, drawDistance);
|
||||
gl.glUniform1i(uniUseFog, fogDepth > 0 ? 1 : 0);
|
||||
gl.glUniform4f(uniFogColor, (sky >> 16 & 0xFF) / 255f, (sky >> 8 & 0xFF) / 255f, (sky & 0xFF) / 255f, 1f);
|
||||
gl.glUniform1i(uniFogDepth, fogDepth);
|
||||
gl.glUniform1f(uniFogDepth, config.fogDepth() * 0.01f * effectiveDrawDistance);
|
||||
gl.glUniform1f(uniFogCornerRadius, config.fogCircularity() * 0.01f * effectiveDrawDistance);
|
||||
gl.glUniform1f(uniFogDensity, config.fogDensity() * 0.1f);
|
||||
gl.glUniform1i(uniDrawDistance, drawDistance * Perspective.LOCAL_TILE_SIZE);
|
||||
|
||||
// Brightness happens to also be stored in the texture provider, so we use that
|
||||
@@ -1306,7 +1334,10 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
{
|
||||
int var21 = (pitchCos * modelHeight >> 16) + var19;
|
||||
int var22 = (var18 - var21) * zoom;
|
||||
return var22 / var14 < Rasterizer3D_clipMidY2;
|
||||
if (var22 / var14 < Rasterizer3D_clipMidY2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1348,6 +1379,35 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
|
||||
int tc = Math.min(MAX_TRIANGLE, model.getTrianglesCount());
|
||||
int uvOffset = model.getUvBufferOffset();
|
||||
boolean hasUv = model.getFaceTextures() != null;
|
||||
|
||||
// Speed hack: the scene uploader splits up large models with no priorities
|
||||
// based on face height, and then we sort each smaller set of faces
|
||||
if (tc > SMALL_TRIANGLE_COUNT && model.getFaceRenderPriorities() == null)
|
||||
{
|
||||
int left = tc;
|
||||
int off = 0;
|
||||
while (left > 0)
|
||||
{
|
||||
tc = Math.min(SMALL_TRIANGLE_COUNT, left);
|
||||
|
||||
GpuIntBuffer b = bufferForTriangles(tc);
|
||||
b.ensureCapacity(8);
|
||||
IntBuffer buffer = b.getBuffer();
|
||||
buffer.put(model.getBufferOffset() + off);
|
||||
buffer.put(hasUv ? uvOffset + off : -1);
|
||||
buffer.put(tc);
|
||||
buffer.put(targetBufferOffset);
|
||||
buffer.put(FLAG_SCENE_BUFFER | (model.getRadius() << 12) | orientation);
|
||||
buffer.put(x + client.getCameraX2()).put(y + client.getCameraY2()).put(z + client.getCameraZ2());
|
||||
|
||||
targetBufferOffset += tc * 3;
|
||||
|
||||
off += tc * 3;
|
||||
left -= tc;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
GpuIntBuffer b = bufferForTriangles(tc);
|
||||
|
||||
@@ -1422,7 +1482,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
|
||||
*/
|
||||
private GpuIntBuffer bufferForTriangles(int triangles)
|
||||
{
|
||||
if (triangles < SMALL_TRIANGLE_COUNT)
|
||||
if (triangles <= SMALL_TRIANGLE_COUNT)
|
||||
{
|
||||
++smallModels;
|
||||
return modelBufferSmall;
|
||||
|
||||
@@ -28,21 +28,36 @@ import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Range;
|
||||
import net.runelite.client.config.Stub;
|
||||
import static net.runelite.client.plugins.gpu.GpuPlugin.MAX_DISTANCE;
|
||||
import static net.runelite.client.plugins.gpu.GpuPlugin.MAX_FOG_DEPTH;
|
||||
import net.runelite.client.plugins.gpu.config.AnisotropicFilteringMode;
|
||||
import net.runelite.client.plugins.gpu.config.AntiAliasingMode;
|
||||
|
||||
@ConfigGroup("gpu")
|
||||
public interface GpuPluginConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "drawingStub",
|
||||
name = "Drawing",
|
||||
description = "",
|
||||
position = 1
|
||||
)
|
||||
default Stub drawingStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@Range(
|
||||
min = 20,
|
||||
max = MAX_DISTANCE
|
||||
)
|
||||
@ConfigItem(
|
||||
keyName = "drawDistance",
|
||||
name = "Draw Distance",
|
||||
description = "Draw distance",
|
||||
position = 1
|
||||
position = 2,
|
||||
parent = "drawingStub"
|
||||
)
|
||||
default int drawDistance()
|
||||
{
|
||||
@@ -53,35 +68,102 @@ public interface GpuPluginConfig extends Config
|
||||
keyName = "smoothBanding",
|
||||
name = "Remove Color Banding",
|
||||
description = "Smooths out the color banding that is present in the CPU renderer",
|
||||
position = 2
|
||||
position = 3,
|
||||
parent = "drawingStub"
|
||||
)
|
||||
default boolean smoothBanding()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "ppStub",
|
||||
name = "Post processing",
|
||||
description = "",
|
||||
position = 4
|
||||
)
|
||||
default Stub ppStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "antiAliasingMode",
|
||||
name = "Anti Aliasing",
|
||||
description = "Configures the anti-aliasing mode",
|
||||
position = 3
|
||||
position = 5,
|
||||
parent = "ppStub"
|
||||
)
|
||||
default AntiAliasingMode antiAliasingMode()
|
||||
{
|
||||
return AntiAliasingMode.DISABLED;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "anisotropicFilteringMode",
|
||||
name = "Anisotropic Filtering",
|
||||
description = "Configures the anisotropic filtering mode",
|
||||
position = 6,
|
||||
parent = "ppStub"
|
||||
)
|
||||
default AnisotropicFilteringMode anisotropicFilteringMode()
|
||||
{
|
||||
return AnisotropicFilteringMode.DISABLED;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "fogStub",
|
||||
name = "Fog",
|
||||
description = "",
|
||||
position = 7
|
||||
)
|
||||
default Stub fogStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@Range(
|
||||
max = MAX_FOG_DEPTH
|
||||
)
|
||||
@ConfigItem(
|
||||
keyName = "fogDepth",
|
||||
name = "Fog depth",
|
||||
name = "Depth",
|
||||
description = "Distance from the scene edge the fog starts",
|
||||
position = 4
|
||||
position = 8,
|
||||
parent = "fogStub"
|
||||
)
|
||||
default int fogDepth()
|
||||
{
|
||||
return 0;
|
||||
return 30;
|
||||
}
|
||||
}
|
||||
|
||||
@Range(
|
||||
max = MAX_FOG_DEPTH
|
||||
)
|
||||
@ConfigItem(
|
||||
keyName = "fogCircularity",
|
||||
name = "Roundness",
|
||||
description = "Fog circularity in %",
|
||||
position = 9,
|
||||
parent = "fogStub"
|
||||
)
|
||||
default int fogCircularity()
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
@Range(
|
||||
max = MAX_FOG_DEPTH
|
||||
)
|
||||
@ConfigItem(
|
||||
keyName = "fogDensity",
|
||||
name = "Density",
|
||||
description = "Relative fog thickness",
|
||||
position = 10,
|
||||
parent = "fogStub"
|
||||
)
|
||||
default int fogDensity()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
package net.runelite.client.plugins.gpu;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import net.runelite.api.Client;
|
||||
@@ -40,6 +41,7 @@ import net.runelite.api.SceneTileModel;
|
||||
import net.runelite.api.SceneTilePaint;
|
||||
import net.runelite.api.Tile;
|
||||
import net.runelite.api.WallObject;
|
||||
import static net.runelite.client.plugins.gpu.GpuPlugin.SMALL_TRIANGLE_COUNT;
|
||||
|
||||
@Singleton
|
||||
class SceneUploader
|
||||
@@ -90,7 +92,7 @@ class SceneUploader
|
||||
}
|
||||
}
|
||||
|
||||
private void reset(Tile tile)
|
||||
private static void reset(Tile tile)
|
||||
{
|
||||
Tile bridge = tile.getBridge();
|
||||
if (bridge != null)
|
||||
@@ -337,7 +339,7 @@ class SceneUploader
|
||||
return 6;
|
||||
}
|
||||
|
||||
private int upload(SceneTileModel sceneTileModel, int tileX, int tileY, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
|
||||
private static int upload(SceneTileModel sceneTileModel, int tileX, int tileY, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
|
||||
{
|
||||
final int[] faceX = sceneTileModel.getFaceX();
|
||||
final int[] faceY = sceneTileModel.getFaceY();
|
||||
@@ -413,6 +415,21 @@ class SceneUploader
|
||||
return cnt;
|
||||
}
|
||||
|
||||
private static int faceHeight(Model model, int face)
|
||||
{
|
||||
final int[] vertexY = model.getVerticesY();
|
||||
|
||||
final int[] trianglesX = model.getTrianglesX();
|
||||
final int[] trianglesY = model.getTrianglesY();
|
||||
final int[] trianglesZ = model.getTrianglesZ();
|
||||
|
||||
int triangleA = trianglesX[face];
|
||||
int triangleB = trianglesY[face];
|
||||
int triangleC = trianglesZ[face];
|
||||
|
||||
return (vertexY[triangleA] + vertexY[triangleB] + vertexY[triangleC]) / 3;
|
||||
}
|
||||
|
||||
private void uploadModel(Model model, GpuIntBuffer vertexBuffer, GpuFloatBuffer uvBuffer)
|
||||
{
|
||||
if (model.getBufferOffset() > 0)
|
||||
@@ -436,9 +453,32 @@ class SceneUploader
|
||||
|
||||
final int triangleCount = model.getTrianglesCount();
|
||||
int len = 0;
|
||||
for (int i = 0; i < triangleCount; ++i)
|
||||
if (triangleCount > SMALL_TRIANGLE_COUNT && model.getFaceRenderPriorities() == null)
|
||||
{
|
||||
len += pushFace(model, i, vertexBuffer, uvBuffer);
|
||||
Integer[] faces = new Integer[triangleCount];
|
||||
for (int i = 0; i < triangleCount; ++i)
|
||||
{
|
||||
faces[i] = i;
|
||||
}
|
||||
|
||||
Arrays.sort(faces, (i1, i2) ->
|
||||
{
|
||||
int z1 = faceHeight(model, i1);
|
||||
int z2 = faceHeight(model, i2);
|
||||
return Integer.compare(z2, z1);
|
||||
});
|
||||
|
||||
for (int i = 0; i < triangleCount; ++i)
|
||||
{
|
||||
len += pushFace(model, faces[i], vertexBuffer, uvBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < triangleCount; ++i)
|
||||
{
|
||||
len += pushFace(model, i, vertexBuffer, uvBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
offset += len;
|
||||
@@ -546,4 +586,4 @@ class SceneUploader
|
||||
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class TextureManager
|
||||
* @param textureProvider
|
||||
* @return
|
||||
*/
|
||||
private boolean allTexturesLoaded(TextureProvider textureProvider)
|
||||
private static boolean allTexturesLoaded(TextureProvider textureProvider)
|
||||
{
|
||||
Texture[] textures = textureProvider.getTextures();
|
||||
if (textures == null || textures.length == 0)
|
||||
@@ -109,7 +109,7 @@ class TextureManager
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateTextures(TextureProvider textureProvider, GL4 gl, int textureArrayId)
|
||||
private static void updateTextures(TextureProvider textureProvider, GL4 gl, int textureArrayId)
|
||||
{
|
||||
Texture[] textures = textureProvider.getTextures();
|
||||
|
||||
@@ -232,4 +232,4 @@ class TextureManager
|
||||
texture.setU(u);
|
||||
texture.setV(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2018, pacf531 <https://github.com/pacf531>
|
||||
* 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.gpu.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum AnisotropicFilteringMode
|
||||
{
|
||||
DISABLED("Disabled", 0f),
|
||||
BILINEAR("Bilinear", 0.5f),
|
||||
TRILINEAR("Trilinear", 1f),
|
||||
AF_2("x2", 2f),
|
||||
AF_4("x4", 4f),
|
||||
AF_8("x8", 8f),
|
||||
AF_16("x16", 16f);
|
||||
|
||||
private final String name;
|
||||
private final float samples;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ class GrandExchangeItemPanel extends JPanel
|
||||
{
|
||||
private static final Dimension ICON_SIZE = new Dimension(32, 32);
|
||||
|
||||
GrandExchangeItemPanel(AsyncBufferedImage icon, String name, int itemID, int gePrice, Double
|
||||
GrandExchangeItemPanel(AsyncBufferedImage icon, String name, int itemID, int gePrice, int
|
||||
haPrice, int geItemLimit)
|
||||
{
|
||||
BorderLayout layout = new BorderLayout();
|
||||
@@ -139,7 +139,7 @@ class GrandExchangeItemPanel extends JPanel
|
||||
|
||||
// Alch price
|
||||
JLabel haPriceLabel = new JLabel();
|
||||
haPriceLabel.setText(StackFormatter.formatNumber(haPrice.intValue()) + " alch");
|
||||
haPriceLabel.setText(StackFormatter.formatNumber(haPrice) + " alch");
|
||||
haPriceLabel.setForeground(ColorScheme.GRAND_EXCHANGE_ALCH);
|
||||
alchAndLimitPanel.add(haPriceLabel, BorderLayout.WEST);
|
||||
|
||||
|
||||
@@ -34,6 +34,6 @@ class GrandExchangeItems
|
||||
private final String name;
|
||||
private final int itemId;
|
||||
private final int gePrice;
|
||||
private final double haPrice;
|
||||
private final int haPrice;
|
||||
private final int geItemLimit;
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ class GrandExchangeSearchPanel extends JPanel
|
||||
int itemLimit = itemGELimits.getOrDefault(itemId, 0);
|
||||
AsyncBufferedImage itemImage = itemManager.getImage(itemId);
|
||||
|
||||
itemsList.add(new GrandExchangeItems(itemImage, item.getName(), itemId, itemPrice, itemComp.getPrice() * 0.6, itemLimit));
|
||||
itemsList.add(new GrandExchangeItems(itemImage, item.getName(), itemId, itemPrice, itemManager.getAlchValue(itemId), itemLimit));
|
||||
|
||||
// If using hotkey to lookup item, stop after finding match.
|
||||
if (exactMatch && item.getName().equalsIgnoreCase(lookup))
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package net.runelite.client.plugins.inventoryhighlight;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Stub;
|
||||
|
||||
@ConfigGroup("inventoryHighlight")
|
||||
public interface InventoryHighlightConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "showItem",
|
||||
name = "Show the item",
|
||||
description = "Show a preview of the item in the new slot"
|
||||
)
|
||||
default boolean showItem()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "gridStub",
|
||||
name = "Grid",
|
||||
description = "",
|
||||
position = 1
|
||||
)
|
||||
default Stub gridStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showGrid",
|
||||
name = "Show a grid",
|
||||
description = "Show a grid on the inventory while dragging",
|
||||
parent = "gridStub"
|
||||
)
|
||||
default boolean showGrid()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showHighlight",
|
||||
name = "Show background highlight",
|
||||
description = "Show a green background highlight in the new slot",
|
||||
parent = "gridStub"
|
||||
)
|
||||
default boolean showHighlight()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
|
||||
* 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.inventoryhighlight;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.event.MouseEvent;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Point;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.api.widgets.WidgetItem;
|
||||
import net.runelite.client.input.MouseListener;
|
||||
|
||||
public class InventoryHighlightInputListener implements MouseListener
|
||||
{
|
||||
private final InventoryHighlightPlugin plugin;
|
||||
private final Client client;
|
||||
|
||||
@Inject
|
||||
public InventoryHighlightInputListener(InventoryHighlightPlugin plugin, Client client)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseDragged(MouseEvent mouseEvent)
|
||||
{
|
||||
plugin.setDragging(true);
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseMoved(MouseEvent mouseEvent)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseClicked(MouseEvent mouseEvent)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mousePressed(MouseEvent mouseEvent)
|
||||
{
|
||||
if (client.getGameState() != GameState.LOGGED_IN)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
|
||||
final Widget bankInventoryWidget = client.getWidget(WidgetInfo.BANK_INVENTORY_ITEMS_CONTAINER);
|
||||
|
||||
if ((inventoryWidget == null || inventoryWidget.isSelfHidden()) &&
|
||||
(inventoryWidget == null || bankInventoryWidget == null || bankInventoryWidget.isSelfHidden()))
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
final Point mouse = client.getMouseCanvasPosition();
|
||||
|
||||
for (WidgetItem item : inventoryWidget.getWidgetItems())
|
||||
{
|
||||
if (item.getCanvasBounds().contains(mouse.getX(), mouse.getY()))
|
||||
{
|
||||
plugin.setDraggingItem(item.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseReleased(MouseEvent mouseEvent)
|
||||
{
|
||||
plugin.setDragging(false);
|
||||
plugin.setDraggingItem(-1);
|
||||
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseEntered(MouseEvent mouseEvent)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MouseEvent mouseExited(MouseEvent mouseEvent)
|
||||
{
|
||||
return mouseEvent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
|
||||
* 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.inventoryhighlight;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.ui.overlay.Overlay;
|
||||
import net.runelite.client.ui.overlay.OverlayLayer;
|
||||
|
||||
public class InventoryHighlightOverlay extends Overlay
|
||||
{
|
||||
private final InventoryHighlightPlugin plugin;
|
||||
private final InventoryHighlightConfig config;
|
||||
private final Client client;
|
||||
private final ItemManager itemManager;
|
||||
|
||||
// the inventory widget location is slightly off
|
||||
private static final int FIXED_MARGIN_X = -10;
|
||||
private static final int FIXED_MARGIN_Y = -25;
|
||||
private static final int RESIZEABLE_MARGIN_X = -6;
|
||||
private static final int RESIZEABLE_MARGIN_Y = -21;
|
||||
|
||||
private static final int ITEM_WIDTH = 32;
|
||||
private static final int ITEM_HEIGHT = 32;
|
||||
private static final int ITEM_MARGIN_X = 10;
|
||||
private static final int ITEM_MARGIN_Y = 4;
|
||||
|
||||
private static final Color HIGHLIGHT = new Color(0, 255, 0, 45);
|
||||
private static final Color GRID = new Color(255, 255, 255, 45);
|
||||
|
||||
@Inject
|
||||
public InventoryHighlightOverlay(InventoryHighlightPlugin plugin, InventoryHighlightConfig config, Client client, ItemManager itemManager)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.itemManager = itemManager;
|
||||
this.client = client;
|
||||
this.config = config;
|
||||
|
||||
setLayer(OverlayLayer.ABOVE_WIDGETS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension render(Graphics2D graphics)
|
||||
{
|
||||
if (plugin.getDraggingItem() == -1 || !plugin.isDragging())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int marginX, marginY;
|
||||
if (client.isResized())
|
||||
{
|
||||
marginX = RESIZEABLE_MARGIN_X;
|
||||
marginY = RESIZEABLE_MARGIN_Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
marginX = FIXED_MARGIN_X;
|
||||
marginY = FIXED_MARGIN_Y;
|
||||
}
|
||||
|
||||
final net.runelite.api.Point mouse = client.getMouseCanvasPosition();
|
||||
final Point updatedMouse = new Point(mouse.getX() + marginX, mouse.getY() + marginY);
|
||||
|
||||
// null checks for inventory are checked during dragging events
|
||||
final Widget inventoryWidget = client.getWidget(WidgetInfo.INVENTORY);
|
||||
|
||||
final int inventoryX = inventoryWidget.getCanvasLocation().getX() + marginX;
|
||||
final int inventoryY = inventoryWidget.getCanvasLocation().getY() + marginY;
|
||||
|
||||
final BufferedImage draggedItemImage = itemManager.getImage(plugin.getDraggingItem());
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
for (int j = 0; j < 7; j++)
|
||||
{
|
||||
final int x = (ITEM_WIDTH + ITEM_MARGIN_X) * i + inventoryX;
|
||||
final int y = (ITEM_HEIGHT + ITEM_MARGIN_Y) * j + inventoryY;
|
||||
final Rectangle bounds = new Rectangle(x, y, ITEM_WIDTH, ITEM_HEIGHT);
|
||||
|
||||
if (config.showItem() && bounds.contains(updatedMouse))
|
||||
{
|
||||
graphics.setComposite(AlphaComposite.SrcOver.derive(0.3f));
|
||||
graphics.drawImage(draggedItemImage, x, y, null);
|
||||
graphics.setComposite(AlphaComposite.SrcOver);
|
||||
}
|
||||
|
||||
if (config.showHighlight() && bounds.contains(updatedMouse))
|
||||
{
|
||||
graphics.setColor(HIGHLIGHT);
|
||||
graphics.fill(bounds);
|
||||
}
|
||||
|
||||
if (config.showGrid())
|
||||
{
|
||||
// don't set color on highlighted slot
|
||||
if (!config.showHighlight() || !(config.showHighlight() && bounds.contains(updatedMouse)))
|
||||
{
|
||||
graphics.setColor(GRID);
|
||||
graphics.fill(bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Jeremy Plsek <https://github.com/jplsek>
|
||||
* 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.inventoryhighlight;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provides;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.runelite.api.events.FocusChanged;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.input.MouseManager;
|
||||
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;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Inventory Highlight",
|
||||
description = "Shows a preview of where items will be dragged",
|
||||
tags = {"items", "overlay"},
|
||||
enabledByDefault = false,
|
||||
type = PluginType.UTILITY
|
||||
)
|
||||
public class InventoryHighlightPlugin extends Plugin
|
||||
{
|
||||
@Inject
|
||||
private InventoryHighlightOverlay overlay;
|
||||
|
||||
@Inject
|
||||
private InventoryHighlightInputListener inputListener;
|
||||
|
||||
@Inject
|
||||
private MouseManager mouseManager;
|
||||
|
||||
@Inject
|
||||
private OverlayManager overlayManager;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private int draggingItem = -1;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private boolean dragging = false;
|
||||
|
||||
@Override
|
||||
public void startUp()
|
||||
{
|
||||
overlayManager.add(overlay);
|
||||
mouseManager.registerMouseListener(inputListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutDown()
|
||||
{
|
||||
mouseManager.unregisterMouseListener(inputListener);
|
||||
overlayManager.remove(overlay);
|
||||
}
|
||||
|
||||
@Provides
|
||||
InventoryHighlightConfig getConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(InventoryHighlightConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onFocusChanged(FocusChanged focusChanged)
|
||||
{
|
||||
if (!focusChanged.isFocused())
|
||||
{
|
||||
dragging = false;
|
||||
draggingItem = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,9 +48,6 @@ import net.runelite.client.util.StackFormatter;
|
||||
|
||||
class ItemPricesOverlay extends Overlay
|
||||
{
|
||||
// Used when getting High Alchemy value - multiplied by general store price.
|
||||
private static final float HIGH_ALCHEMY_CONSTANT = 0.6f;
|
||||
|
||||
private static final int INVENTORY_ITEM_WIDGETID = WidgetInfo.INVENTORY.getPackedId();
|
||||
private static final int BANK_INVENTORY_ITEM_WIDGETID = WidgetInfo.BANK_INVENTORY_ITEMS_CONTAINER.getPackedId();
|
||||
private static final int BANK_ITEM_WIDGETID = WidgetInfo.BANK_ITEM_CONTAINER.getPackedId();
|
||||
@@ -204,7 +201,7 @@ class ItemPricesOverlay extends Overlay
|
||||
}
|
||||
if (config.showHAValue())
|
||||
{
|
||||
haPrice = Math.round(itemDef.getPrice() * HIGH_ALCHEMY_CONSTANT);
|
||||
haPrice = itemManager.getAlchValue(id);
|
||||
}
|
||||
if (gePrice > 0 && haPrice > 0 && config.showAlchProfit())
|
||||
{
|
||||
|
||||
@@ -28,171 +28,42 @@ package net.runelite.client.plugins.runecraft;
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Stub;
|
||||
|
||||
@ConfigGroup("runecraft")
|
||||
public interface RunecraftConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "showRifts",
|
||||
name = "Show Rifts in Abyss",
|
||||
description = "Configures whether the rifts in the abyss will be displayed",
|
||||
keyName = "utilStub",
|
||||
name = "Utility",
|
||||
description = "",
|
||||
position = 1
|
||||
)
|
||||
default Stub utilStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "Lavas",
|
||||
name = "Lavas",
|
||||
description = "Swaps Ring of dueling menu entry depending on location, requires fire tiara or RC cape to be worn.",
|
||||
parent = "utilStub",
|
||||
position = 2
|
||||
)
|
||||
default boolean Lavas()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "essPouch",
|
||||
name = "Swap essence pouch",
|
||||
description = "Makes essence pouch left-click fill in bank",
|
||||
parent = "utilStub",
|
||||
position = 3
|
||||
)
|
||||
default boolean showRifts()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showAir",
|
||||
name = "Show Air rift",
|
||||
description = "Configures whether to display the air rift",
|
||||
position = 4
|
||||
)
|
||||
default boolean showAir()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showBlood",
|
||||
name = "Show Blood rift",
|
||||
description = "Configures whether to display the Blood rift",
|
||||
position = 5
|
||||
)
|
||||
default boolean showBlood()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showBody",
|
||||
name = "Show Body rift",
|
||||
description = "Configures whether to display the Body rift",
|
||||
position = 6
|
||||
)
|
||||
default boolean showBody()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showChaos",
|
||||
name = "Show Chaos rift",
|
||||
description = "Configures whether to display the Chaos rift",
|
||||
position = 7
|
||||
)
|
||||
default boolean showChaos()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showCosmic",
|
||||
name = "Show Cosmic rift",
|
||||
description = "Configures whether to display the Cosmic rift",
|
||||
position = 8
|
||||
)
|
||||
default boolean showCosmic()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showDeath",
|
||||
name = "Show Death rift",
|
||||
description = "Configures whether to display the Death rift",
|
||||
position = 9
|
||||
)
|
||||
default boolean showDeath()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showEarth",
|
||||
name = "Show Earth rift",
|
||||
description = "Configures whether to display the Earth rift",
|
||||
position = 10
|
||||
)
|
||||
default boolean showEarth()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showFire",
|
||||
name = "Show Fire rift",
|
||||
description = "Configures whether to display the Fire rift",
|
||||
position = 11
|
||||
)
|
||||
default boolean showFire()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showLaw",
|
||||
name = "Show Law rift",
|
||||
description = "Configures whether to display the Law rift",
|
||||
position = 12
|
||||
)
|
||||
default boolean showLaw()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showMind",
|
||||
name = "Show Mind rift",
|
||||
description = "Configures whether to display the Mind rift",
|
||||
position = 13
|
||||
)
|
||||
default boolean showMind()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showNature",
|
||||
name = "Show Nature rift",
|
||||
description = "Configures whether to display the Nature rift",
|
||||
position = 14
|
||||
)
|
||||
default boolean showNature()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showSoul",
|
||||
name = "Show Soul rift",
|
||||
description = "Configures whether to display the Soul rift",
|
||||
position = 15
|
||||
)
|
||||
default boolean showSoul()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showWater",
|
||||
name = "Show Water rift",
|
||||
description = "Configures whether to display the Water rift",
|
||||
position = 16
|
||||
)
|
||||
default boolean showWater()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showClickBox",
|
||||
name = "Show Rift click box",
|
||||
description = "Configures whether to display the click box of the rift",
|
||||
position = 17
|
||||
)
|
||||
default boolean showClickBox()
|
||||
default boolean essPouch()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -201,7 +72,8 @@ public interface RunecraftConfig extends Config
|
||||
keyName = "hightlightDarkMage",
|
||||
name = "Highlight Dark Mage NPC",
|
||||
description = "Configures whether to highlight the Dark Mage when pouches are degraded",
|
||||
position = 18
|
||||
position = 4,
|
||||
parent = "utilStub"
|
||||
)
|
||||
default boolean hightlightDarkMage()
|
||||
{
|
||||
@@ -212,29 +84,230 @@ public interface RunecraftConfig extends Config
|
||||
keyName = "degradingNotification",
|
||||
name = "Notify when pouch degrades",
|
||||
description = "Send a notification when a pouch degrades",
|
||||
position = 19
|
||||
position = 5,
|
||||
parent = "utilStub"
|
||||
)
|
||||
default boolean degradingNotification()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "Lavas",
|
||||
name = "Lavas",
|
||||
description = "Swaps Ring of dueling menu entry depending on location, requires fire tiara or RC cape to be worn."
|
||||
keyName = "riftsStub",
|
||||
name = "Rifts",
|
||||
description = "",
|
||||
position = 6
|
||||
)
|
||||
default boolean Lavas()
|
||||
default Stub riftsStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showRifts",
|
||||
name = "Show Rifts in Abyss",
|
||||
description = "Configures whether the rifts in the abyss will be displayed",
|
||||
position = 7,
|
||||
parent = "riftsStub"
|
||||
)
|
||||
default boolean showRifts()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "essPouch",
|
||||
name = "Swap essence pouch",
|
||||
description = "Makes essence pouch left-click fill in bank"
|
||||
keyName = "showAir",
|
||||
name = "Show Air rift",
|
||||
description = "Configures whether to display the air rift",
|
||||
position = 8,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean essPouch()
|
||||
default boolean showAir()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showBlood",
|
||||
name = "Show Blood rift",
|
||||
description = "Configures whether to display the Blood rift",
|
||||
position = 9,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showBlood()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showBody",
|
||||
name = "Show Body rift",
|
||||
description = "Configures whether to display the Body rift",
|
||||
position = 10,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showBody()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showChaos",
|
||||
name = "Show Chaos rift",
|
||||
description = "Configures whether to display the Chaos rift",
|
||||
position = 11,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showChaos()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showCosmic",
|
||||
name = "Show Cosmic rift",
|
||||
description = "Configures whether to display the Cosmic rift",
|
||||
position = 12,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showCosmic()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showDeath",
|
||||
name = "Show Death rift",
|
||||
description = "Configures whether to display the Death rift",
|
||||
position = 13,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showDeath()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showEarth",
|
||||
name = "Show Earth rift",
|
||||
description = "Configures whether to display the Earth rift",
|
||||
position = 14,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showEarth()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showFire",
|
||||
name = "Show Fire rift",
|
||||
description = "Configures whether to display the Fire rift",
|
||||
position = 15,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showFire()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showLaw",
|
||||
name = "Show Law rift",
|
||||
description = "Configures whether to display the Law rift",
|
||||
position = 16,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showLaw()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showMind",
|
||||
name = "Show Mind rift",
|
||||
description = "Configures whether to display the Mind rift",
|
||||
position = 17,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showMind()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showNature",
|
||||
name = "Show Nature rift",
|
||||
description = "Configures whether to display the Nature rift",
|
||||
position = 18,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showNature()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showSoul",
|
||||
name = "Show Soul rift",
|
||||
description = "Configures whether to display the Soul rift",
|
||||
position = 19,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showSoul()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showWater",
|
||||
name = "Show Water rift",
|
||||
description = "Configures whether to display the Water rift",
|
||||
position = 20,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showWater()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "showClickBox",
|
||||
name = "Show Rift click box",
|
||||
description = "Configures whether to display the click box of the rift",
|
||||
position = 21,
|
||||
parent = "riftsStub",
|
||||
hidden = true,
|
||||
unhide = "showRifts"
|
||||
)
|
||||
default boolean showClickBox()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package net.runelite.client.plugins.stonedloottracker;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Getter
|
||||
@RequiredArgsConstructor
|
||||
public enum ItemSortTypes
|
||||
{
|
||||
ALPHABETICAL("Alphabetical"),
|
||||
ITEM_ID("Item ID"),
|
||||
VALUE("Value"),
|
||||
PRICE("Price"),
|
||||
HAPRICE("HA Price");
|
||||
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker;
|
||||
|
||||
import net.runelite.client.config.Config;
|
||||
import net.runelite.client.config.ConfigGroup;
|
||||
import net.runelite.client.config.ConfigItem;
|
||||
import net.runelite.client.config.Stub;
|
||||
|
||||
@ConfigGroup("stonedloottracker")
|
||||
public interface StonedLootTrackerConfig extends Config
|
||||
{
|
||||
@ConfigItem(
|
||||
keyName = "mainStub",
|
||||
name = "Main panel",
|
||||
description = "",
|
||||
position = 1
|
||||
)
|
||||
default Stub mainStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 2,
|
||||
keyName = "bossButtons",
|
||||
name = "Show boss icons",
|
||||
description = "Toggles whether the selection screen will use the boss icons",
|
||||
parent = "mainStub"
|
||||
)
|
||||
default boolean bossButtons()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
keyName = "itemsStub",
|
||||
name = "Items",
|
||||
description = "",
|
||||
position = 3
|
||||
)
|
||||
default Stub itemsStub()
|
||||
{
|
||||
return new Stub();
|
||||
}
|
||||
|
||||
// TODO Option is not working will look into it later
|
||||
@ConfigItem(
|
||||
position = 4,
|
||||
keyName = "hideUniques",
|
||||
name = "Hide uniques",
|
||||
description = "Hides unique items from the item breakdown",
|
||||
parent = "itemsStub",
|
||||
hidden = true
|
||||
)
|
||||
default boolean hideUniques()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 5,
|
||||
keyName = "itemSortType",
|
||||
name = "Sort Items by",
|
||||
description = "Sorts items by the requested value inside the UI. (Doesn't effect session/box view)",
|
||||
parent = "itemsStub"
|
||||
)
|
||||
default ItemSortTypes itemSortType()
|
||||
{
|
||||
return ItemSortTypes.ALPHABETICAL;
|
||||
}
|
||||
|
||||
@ConfigItem(
|
||||
position = 6,
|
||||
keyName = "itemBreakdown",
|
||||
name = "Breakdown individual items",
|
||||
description = "Toggles whether the Individual item UI should be used inside npc-specific tabs",
|
||||
parent = "itemsStub"
|
||||
)
|
||||
default boolean itemBreakdown()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,703 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.stonedloottracker;
|
||||
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.HashMultiset;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Multiset;
|
||||
import com.google.common.collect.Multisets;
|
||||
import com.google.inject.Provides;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.SwingUtilities;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.InventoryID;
|
||||
import net.runelite.api.ItemComposition;
|
||||
import net.runelite.api.ItemContainer;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NpcID;
|
||||
import net.runelite.api.Player;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.ConfigChanged;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.ItemContainerChanged;
|
||||
import net.runelite.api.events.WidgetLoaded;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetID;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import net.runelite.client.callback.ClientThread;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.events.NpcLootReceived;
|
||||
import net.runelite.client.events.PlayerLootReceived;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.game.ItemStack;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootRecordWriter;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.Pet;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.UniqueItem;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.UniqueItemPrepared;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.events.LootTrackerNameChange;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.events.LootTrackerRecordStored;
|
||||
import net.runelite.client.plugins.stonedloottracker.ui.LootTrackerPanel;
|
||||
import net.runelite.client.ui.ClientToolbar;
|
||||
import net.runelite.client.ui.NavigationButton;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@PluginDescriptor(
|
||||
name = "Stoned Loot Tracker",
|
||||
description = "Tracks loot from monsters and minigames",
|
||||
tags = {"drops"},
|
||||
enabledByDefault = false,
|
||||
type = PluginType.UTILITY
|
||||
)
|
||||
@Slf4j
|
||||
public class StonedLootTrackerPlugin extends Plugin
|
||||
{
|
||||
// Activity/Event loot handling
|
||||
private static final Pattern CLUE_SCROLL_PATTERN = Pattern.compile("You have completed ([0-9]+) ([a-z]+) Treasure Trails.");
|
||||
private static final Pattern BOSS_NAME_NUMBER_PATTERN = Pattern.compile("Your (.*) kill count is: ([0-9]*).");
|
||||
private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)");
|
||||
private static final ImmutableList<String> PET_MESSAGES = ImmutableList.of("You have a funny feeling like you're being followed",
|
||||
"You feel something weird sneaking into your backpack",
|
||||
"You have a funny feeling like you would have been followed");
|
||||
private static final int THEATRE_OF_BLOOD_REGION = 12867;
|
||||
|
||||
// Herbiboar loot handling
|
||||
private static final String HERBIBOAR_LOOTED_MESSAGE = "Your herbiboar harvest count is";
|
||||
private static final String HERBIBOR_EVENT = "Herbiboar";
|
||||
|
||||
// Chest loot handling
|
||||
private static final String CHEST_LOOTED_MESSAGE = "You find some treasure in the chest!";
|
||||
private static final Map<Integer, String> CHEST_EVENT_TYPES = ImmutableMap.of(
|
||||
5179, "Brimstone Chest",
|
||||
11573, "Crystal Chest"
|
||||
);
|
||||
|
||||
@Inject
|
||||
private ClientToolbar clientToolbar;
|
||||
|
||||
@Inject
|
||||
private ItemManager itemManager;
|
||||
|
||||
@Inject
|
||||
private Client client;
|
||||
|
||||
@Inject
|
||||
public StonedLootTrackerConfig config;
|
||||
|
||||
@Inject
|
||||
private ClientThread clientThread;
|
||||
|
||||
@Inject
|
||||
private LootRecordWriter writer;
|
||||
|
||||
private Multiset<Integer> inventorySnapshot;
|
||||
|
||||
@Provides
|
||||
StonedLootTrackerConfig provideConfig(ConfigManager configManager)
|
||||
{
|
||||
return configManager.getConfig(StonedLootTrackerConfig.class);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onConfigChanged(ConfigChanged event)
|
||||
{
|
||||
if (event.getGroup().equals("stonedloottracker"))
|
||||
{
|
||||
panel.refreshUI();
|
||||
}
|
||||
}
|
||||
|
||||
private LootTrackerPanel panel;
|
||||
private NavigationButton navButton;
|
||||
private String eventType;
|
||||
|
||||
private Multimap<String, LootRecordCustom> lootRecordMultimap = ArrayListMultimap.create();
|
||||
private Multimap<String, UniqueItemPrepared> uniques = ArrayListMultimap.create();
|
||||
private Map<String, Integer> killCountMap = new HashMap<>();
|
||||
|
||||
// key = name, value=current killCount
|
||||
private boolean loaded = false;
|
||||
private boolean gotPet = false;
|
||||
|
||||
@Override
|
||||
protected void startUp() throws Exception
|
||||
{
|
||||
panel = new LootTrackerPanel(itemManager, this);
|
||||
|
||||
final BufferedImage icon = ImageUtil.getResourceStreamFromClass(getClass(), "panel_icon.png");
|
||||
|
||||
navButton = NavigationButton.builder()
|
||||
.tooltip("Stoned Loot Tracker")
|
||||
.icon(icon)
|
||||
.priority(5)
|
||||
.panel(panel)
|
||||
.build();
|
||||
|
||||
clientToolbar.addNavigation(navButton);
|
||||
|
||||
if (!loaded)
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
switch (client.getGameState())
|
||||
{
|
||||
case UNKNOWN:
|
||||
case STARTING:
|
||||
return false;
|
||||
}
|
||||
|
||||
prepareUniqueItems();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareUniqueItems()
|
||||
{
|
||||
loaded = true;
|
||||
for (UniqueItem i : UniqueItem.values())
|
||||
{
|
||||
ItemComposition c = itemManager.getItemComposition(i.getItemID());
|
||||
for (String s : i.getActivities())
|
||||
{
|
||||
uniques.put(s.toUpperCase(), new UniqueItemPrepared(c.getLinkedNoteId(), itemManager.getItemPrice(i.getItemID()), i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<UniqueItemPrepared> getUniques(String name)
|
||||
{
|
||||
return uniques.get(name.toUpperCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutDown()
|
||||
{
|
||||
clientToolbar.removeNavigation(navButton);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onLootTrackerRecordStored(LootTrackerRecordStored s)
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> panel.addLog(s.getRecord()));
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
public void onLootTrackerNameChange(LootTrackerNameChange c)
|
||||
{
|
||||
refreshData();
|
||||
SwingUtilities.invokeLater(() -> panel.updateNames());
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onNpcLootReceived(final NpcLootReceived npcLootReceived)
|
||||
{
|
||||
final NPC npc = npcLootReceived.getNpc();
|
||||
final Collection<ItemStack> items = npcLootReceived.getItems();
|
||||
final String name = npc.getName().toLowerCase().contains("vet'ion reborn") ? "Vet'ion" : npc.getName();
|
||||
final int combat = npc.getCombatLevel();
|
||||
final int killCount = killCountMap.getOrDefault(name.toUpperCase(), -1);
|
||||
final LootTrackerItemEntry[] entries = buildEntries(items);
|
||||
|
||||
if (gotPet)
|
||||
{
|
||||
ItemStack pet = handlePet(name);
|
||||
if (pet == null)
|
||||
{
|
||||
log.warn("Error finding pet for npc name: {}", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
items.add(pet);
|
||||
}
|
||||
}
|
||||
|
||||
LootRecordCustom rec = new LootRecordCustom(npc.getId(), name, combat, killCount, Arrays.asList(entries));
|
||||
addLog(name, rec);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onPlayerLootReceived(final PlayerLootReceived playerLootReceived)
|
||||
{
|
||||
final Player player = playerLootReceived.getPlayer();
|
||||
final Collection<ItemStack> items = playerLootReceived.getItems();
|
||||
final String name = player.getName();
|
||||
final int combat = player.getCombatLevel();
|
||||
final int killCount = killCountMap.getOrDefault(name.toUpperCase(), -1);
|
||||
final LootTrackerItemEntry[] entries = buildEntries(items);
|
||||
LootRecordCustom rec = new LootRecordCustom(-1, name, combat, killCount, Arrays.asList(entries));
|
||||
addLog(name, rec);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onWidgetLoaded(WidgetLoaded event)
|
||||
{
|
||||
final ItemContainer container;
|
||||
switch (event.getGroupId())
|
||||
{
|
||||
case (WidgetID.BARROWS_REWARD_GROUP_ID):
|
||||
eventType = "Barrows";
|
||||
container = client.getItemContainer(InventoryID.BARROWS_REWARD);
|
||||
break;
|
||||
case (WidgetID.CHAMBERS_OF_XERIC_REWARD_GROUP_ID):
|
||||
eventType = "Chambers of Xeric";
|
||||
container = client.getItemContainer(InventoryID.CHAMBERS_OF_XERIC_CHEST);
|
||||
break;
|
||||
case (WidgetID.THEATRE_OF_BLOOD_GROUP_ID):
|
||||
int region = WorldPoint.fromLocalInstance(client, client.getLocalPlayer().getLocalLocation()).getRegionID();
|
||||
if (region != THEATRE_OF_BLOOD_REGION)
|
||||
{
|
||||
return;
|
||||
}
|
||||
eventType = "Theatre of Blood";
|
||||
container = client.getItemContainer(InventoryID.THEATRE_OF_BLOOD_CHEST);
|
||||
break;
|
||||
case (WidgetID.CLUE_SCROLL_REWARD_GROUP_ID):
|
||||
// event type should be set via ChatMessage for clue scrolls.
|
||||
// Clue Scrolls use same InventoryID as Barrows
|
||||
container = client.getItemContainer(InventoryID.BARROWS_REWARD);
|
||||
break;
|
||||
// Unsired redemption tracking
|
||||
case (WidgetID.DIALOG_SPRITE_GROUP_ID):
|
||||
Widget text = client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT);
|
||||
if ("you place the unsired into the font of consumption...".equals(text.getText().toLowerCase()))
|
||||
{
|
||||
checkUnsiredWidget();
|
||||
}
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (container == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert container items to array of ItemStack
|
||||
final Collection<ItemStack> items = Arrays.stream(container.getItems())
|
||||
.filter(item -> item.getId() > 0)
|
||||
.map(item -> new ItemStack(item.getId(), item.getQuantity(), client.getLocalPlayer().getLocalLocation()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (items.isEmpty())
|
||||
{
|
||||
log.debug("No items to find for Event: {} | Container: {}", eventType, container);
|
||||
return;
|
||||
}
|
||||
|
||||
final LootTrackerItemEntry[] entries = buildEntries(items);
|
||||
final int killCount = killCountMap.getOrDefault(eventType.toUpperCase(), -1);
|
||||
LootRecordCustom rec = new LootRecordCustom(-1, eventType, -1, killCount, Arrays.asList(entries));
|
||||
addLog(eventType, rec);
|
||||
}
|
||||
|
||||
private void addLog(String name, LootRecordCustom record)
|
||||
{
|
||||
lootRecordMultimap.put(name, record);
|
||||
writer.addLootTrackerRecord(record);
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onChatMessage(ChatMessage event)
|
||||
{
|
||||
if (event.getType() != ChatMessageType.GAMEMESSAGE && event.getType() != ChatMessageType.SPAM)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
String chatMessage = Text.removeTags(event.getMessage());
|
||||
|
||||
// Check if message is for a clue scroll reward
|
||||
final Matcher m = CLUE_SCROLL_PATTERN.matcher(chatMessage);
|
||||
if (m.find())
|
||||
{
|
||||
final String type = m.group(2).toLowerCase();
|
||||
switch (type)
|
||||
{
|
||||
case "beginner":
|
||||
eventType = "Clue Scroll (Beginner)";
|
||||
break;
|
||||
case "easy":
|
||||
eventType = "Clue Scroll (Easy)";
|
||||
break;
|
||||
case "medium":
|
||||
eventType = "Clue Scroll (Medium)";
|
||||
break;
|
||||
case "hard":
|
||||
eventType = "Clue Scroll (Hard)";
|
||||
break;
|
||||
case "elite":
|
||||
eventType = "Clue Scroll (Elite)";
|
||||
break;
|
||||
case "master":
|
||||
eventType = "Clue Scroll (Master)";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
int killCount = Integer.valueOf(m.group(1));
|
||||
killCountMap.put(eventType.toUpperCase(), killCount);
|
||||
return;
|
||||
}
|
||||
// TODO: Figure out better way to handle Barrows and Raids/Raids 2
|
||||
// Barrows KC
|
||||
if (chatMessage.startsWith("Your Barrows chest count is"))
|
||||
{
|
||||
Matcher n = NUMBER_PATTERN.matcher(chatMessage);
|
||||
if (n.find())
|
||||
{
|
||||
killCountMap.put("BARROWS", Integer.valueOf(n.group()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Raids KC
|
||||
if (chatMessage.startsWith("Your completed Chambers of Xeric count is"))
|
||||
{
|
||||
Matcher n = NUMBER_PATTERN.matcher(chatMessage);
|
||||
if (n.find())
|
||||
{
|
||||
killCountMap.put("RAIDS", Integer.valueOf(n.group()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Raids KC
|
||||
if (chatMessage.startsWith("Your completed Theatre of Blood count is"))
|
||||
{
|
||||
Matcher n = NUMBER_PATTERN.matcher(chatMessage);
|
||||
if (n.find())
|
||||
{
|
||||
killCountMap.put("THEATRE OF BLOOD", Integer.valueOf(n.group()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Handle all other boss
|
||||
Matcher boss = BOSS_NAME_NUMBER_PATTERN.matcher(chatMessage);
|
||||
if (boss.find())
|
||||
{
|
||||
String bossName = boss.group(1);
|
||||
int killCount = Integer.valueOf(boss.group(2));
|
||||
killCountMap.put(bossName.toUpperCase(), killCount);
|
||||
}
|
||||
|
||||
if (PET_MESSAGES.stream().anyMatch(chatMessage::contains))
|
||||
{
|
||||
gotPet = true;
|
||||
}
|
||||
|
||||
if (chatMessage.equals(CHEST_LOOTED_MESSAGE))
|
||||
{
|
||||
final int regionID = client.getLocalPlayer().getWorldLocation().getRegionID();
|
||||
if (!CHEST_EVENT_TYPES.containsKey(regionID))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
eventType = CHEST_EVENT_TYPES.get(regionID);
|
||||
|
||||
takeInventorySnapshot();
|
||||
|
||||
Matcher n = NUMBER_PATTERN.matcher(chatMessage);
|
||||
if (n.find())
|
||||
{
|
||||
killCountMap.put(eventType, Integer.valueOf(n.group()));
|
||||
}
|
||||
}
|
||||
|
||||
if (chatMessage.startsWith(HERBIBOAR_LOOTED_MESSAGE))
|
||||
{
|
||||
eventType = HERBIBOR_EVENT;
|
||||
takeInventorySnapshot();
|
||||
|
||||
Matcher n = NUMBER_PATTERN.matcher(chatMessage);
|
||||
|
||||
if (n.find())
|
||||
{
|
||||
killCountMap.put(HERBIBOR_EVENT, Integer.valueOf(n.group()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onItemContainerChanged(ItemContainerChanged event)
|
||||
{
|
||||
if (eventType != null && (CHEST_EVENT_TYPES.containsValue(eventType) || HERBIBOR_EVENT.equals(eventType)))
|
||||
{
|
||||
if (event.getItemContainer() != client.getItemContainer(InventoryID.INVENTORY))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
processInventoryLoot(eventType, event.getItemContainer());
|
||||
eventType = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void takeInventorySnapshot()
|
||||
{
|
||||
final ItemContainer itemContainer = client.getItemContainer(InventoryID.INVENTORY);
|
||||
if (itemContainer != null)
|
||||
{
|
||||
inventorySnapshot = HashMultiset.create();
|
||||
Arrays.stream(itemContainer.getItems())
|
||||
.forEach(item -> inventorySnapshot.add(item.getId(), item.getQuantity()));
|
||||
}
|
||||
}
|
||||
|
||||
private void processInventoryLoot(String eventType, ItemContainer inventoryContainer)
|
||||
{
|
||||
if (inventorySnapshot != null)
|
||||
{
|
||||
Multiset<Integer> currentInventory = HashMultiset.create();
|
||||
Arrays.stream(inventoryContainer.getItems())
|
||||
.forEach(item -> currentInventory.add(item.getId(), item.getQuantity()));
|
||||
|
||||
final Multiset<Integer> diff = Multisets.difference(currentInventory, inventorySnapshot);
|
||||
|
||||
List<ItemStack> items = diff.entrySet().stream()
|
||||
.map(e -> new ItemStack(e.getElement(), e.getCount(), client.getLocalPlayer().getLocalLocation()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
final LootTrackerItemEntry[] entries = buildEntries(items);
|
||||
|
||||
LootRecordCustom rec = new LootRecordCustom(-1, eventType, -1, killCountMap.getOrDefault(eventType, -1), Arrays.asList(entries));
|
||||
addLog(eventType, rec);
|
||||
|
||||
inventorySnapshot = null;
|
||||
}
|
||||
}
|
||||
|
||||
private LootTrackerItemEntry[] buildEntries(final Collection<ItemStack> itemStacks)
|
||||
{
|
||||
return itemStacks.stream().map(itemStack ->
|
||||
{
|
||||
final ItemComposition itemComposition = itemManager.getItemComposition(itemStack.getId());
|
||||
final int realItemId = itemComposition.getNote() != -1 ? itemComposition.getLinkedNoteId() : itemStack.getId();
|
||||
final long price = itemManager.getItemPrice(realItemId);
|
||||
final long haPrice = itemManager.getAlchValue(realItemId);
|
||||
|
||||
return new LootTrackerItemEntry(
|
||||
itemComposition.getName(),
|
||||
itemStack.getId(),
|
||||
itemStack.getQuantity(),
|
||||
price,
|
||||
haPrice,
|
||||
itemComposition.isStackable());
|
||||
}).toArray(LootTrackerItemEntry[]::new);
|
||||
}
|
||||
|
||||
public Collection<LootRecordCustom> getData()
|
||||
{
|
||||
return lootRecordMultimap.values();
|
||||
}
|
||||
|
||||
public Collection<LootRecordCustom> getDataByName(String name)
|
||||
{
|
||||
return lootRecordMultimap.get(name);
|
||||
}
|
||||
|
||||
private void refreshData()
|
||||
{
|
||||
// Pull data from files
|
||||
lootRecordMultimap.clear();
|
||||
Collection<LootRecordCustom> recs = writer.loadAllLootTrackerRecords();
|
||||
for (LootRecordCustom r : recs)
|
||||
{
|
||||
lootRecordMultimap.put(r.getName(), r);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshDataByName(String name)
|
||||
{
|
||||
lootRecordMultimap.removeAll(name);
|
||||
Collection<LootRecordCustom> recs = writer.loadLootTrackerRecords(name);
|
||||
lootRecordMultimap.putAll(name, recs);
|
||||
}
|
||||
|
||||
public void clearStoredDataByName(String name)
|
||||
{
|
||||
lootRecordMultimap.removeAll(name);
|
||||
writer.deleteLootTrackerRecords(name);
|
||||
}
|
||||
|
||||
public TreeSet<String> getNames()
|
||||
{
|
||||
return new TreeSet<>(lootRecordMultimap.keySet());
|
||||
}
|
||||
|
||||
// Pet Handling
|
||||
private ItemStack handlePet(String name)
|
||||
{
|
||||
gotPet = false;
|
||||
|
||||
int petID = getPetId(name);
|
||||
if (petID == -1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ItemStack(petID, 1, client.getLocalPlayer().getLocalLocation());
|
||||
}
|
||||
|
||||
private int getPetId(String name)
|
||||
{
|
||||
Pet pet = Pet.getByBossName(name);
|
||||
if (pet != null)
|
||||
{
|
||||
return pet.getPetID();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Handles adding the unsired loot to the tracker
|
||||
private void receivedUnsiredLoot(int itemID)
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
Collection<LootRecordCustom> data = getDataByName("Abyssal sire");
|
||||
ItemComposition c = itemManager.getItemComposition(itemID);
|
||||
LootTrackerItemEntry itemEntry = new LootTrackerItemEntry(c.getName(), itemID, 1, 0, 0, false);
|
||||
|
||||
log.debug("Received Unsired item: {}", c.getName());
|
||||
|
||||
// Don't have data for sire, create a new record with just this data.
|
||||
if (data == null)
|
||||
{
|
||||
log.debug("No previous Abyssal sire loot, creating new loot record");
|
||||
LootRecordCustom r = new LootRecordCustom(NpcID.ABYSSAL_SIRE, "Abyssal sire", 350, -1, Collections.singletonList(itemEntry));
|
||||
writer.addLootTrackerRecord(r);
|
||||
return;
|
||||
}
|
||||
|
||||
log.debug("Adding drop to last abyssal sire loot record");
|
||||
// Add data to last kill count
|
||||
List<LootRecordCustom> items = new ArrayList<>(data);
|
||||
LootRecordCustom r = items.get(items.size() - 1);
|
||||
r.addDropEntry(itemEntry);
|
||||
writer.writeLootTrackerFile("Abyssal sire", items);
|
||||
});
|
||||
}
|
||||
|
||||
private boolean unsiredThreadRunning = false;
|
||||
private int unsiredThreadTries = 0;
|
||||
|
||||
// Handles checking for unsired loot reclamation
|
||||
private void checkUnsiredWidget()
|
||||
{
|
||||
if (unsiredThreadRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
unsiredThreadRunning = true;
|
||||
unsiredThreadTries = 0;
|
||||
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
log.debug("Checking for text widget change...");
|
||||
Widget text = client.getWidget(WidgetInfo.DIALOG_SPRITE_TEXT);
|
||||
if ("the font consumes the unsired and returns you a reward.".equals(text.getText().toLowerCase()))
|
||||
{
|
||||
Widget sprite = client.getWidget(WidgetInfo.DIALOG_SPRITE);
|
||||
log.debug("Sprite: {}", sprite);
|
||||
log.debug("Sprite Item ID: {}", sprite.getItemId());
|
||||
log.debug("Sprite Model ID: {}", sprite.getModelId());
|
||||
receivedUnsiredLoot(sprite.getItemId());
|
||||
unsiredThreadRunning = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unsiredThreadTries >= 10)
|
||||
{
|
||||
log.debug("Tried 10 times, canceling...");
|
||||
return true;
|
||||
}
|
||||
unsiredThreadTries++;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onGameStateChanged(GameStateChanged c)
|
||||
{
|
||||
if (c.getGameState().equals(GameState.LOGGED_IN))
|
||||
{
|
||||
clientThread.invokeLater(() ->
|
||||
{
|
||||
switch (client.getGameState())
|
||||
{
|
||||
case LOGGED_IN:
|
||||
break;
|
||||
case LOGGING_IN:
|
||||
case LOADING:
|
||||
return false;
|
||||
default:
|
||||
// Quit running if any other state
|
||||
return true;
|
||||
}
|
||||
|
||||
String name = client.getLocalPlayer().getName();
|
||||
if (name != null)
|
||||
{
|
||||
writer.setPlayerUsername(name);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <www.github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
@Getter
|
||||
public enum BossTab
|
||||
{
|
||||
// Chest Rewards
|
||||
BARROWS("Barrows", ItemID.BARROWS_TELEPORT, "Other"),
|
||||
RAIDS("Chambers of Xeric", ItemID.OLMLET, "Other"),
|
||||
RAIDS_2("Theatre of Blood", ItemID.LIL_ZIK, "Other"),
|
||||
|
||||
// Loot received on NPC death
|
||||
ZULRAH("Zulrah", ItemID.PET_SNAKELING, "Other"),
|
||||
VORKATH("Vorkath", ItemID.VORKI, "Other"),
|
||||
|
||||
// God wars dungeon
|
||||
ARMADYL("Kree'arra", ItemID.PET_KREEARRA , "God Wars Dungeon"),
|
||||
BANDOS("General Graardor", ItemID.PET_GENERAL_GRAARDOR , "God Wars Dungeon"),
|
||||
SARADOMIN("Commander Zilyana", ItemID.PET_ZILYANA , "God Wars Dungeon"),
|
||||
ZAMMY("K'ril Tsutsaroth", ItemID.PET_KRIL_TSUTSAROTH , "God Wars Dungeon"),
|
||||
|
||||
// Wildy Bosses
|
||||
VETION("Vet'ion", ItemID.VETION_JR , "Wilderness"),
|
||||
VENENATIS("Venenatis", ItemID.VENENATIS_SPIDERLING , "Wilderness"),
|
||||
CALLISTO("Callisto", ItemID.CALLISTO_CUB , "Wilderness"),
|
||||
CHAOS_ELEMENTAL("Chaos Elemental", ItemID.PET_CHAOS_ELEMENTAL , "Wilderness"),
|
||||
// Wildy Demi-Bosses
|
||||
SCORPIA("Scorpia", ItemID.SCORPIAS_OFFSPRING, "Wilderness"),
|
||||
CHAOS_FANATIC("Chaos Fanatic", ItemID.ANCIENT_STAFF , "Wilderness"),
|
||||
CRAZY_ARCHAEOLOGIST("Crazy Archaeologist", ItemID.FEDORA , "Wilderness"),
|
||||
// Wildy Other
|
||||
KING_BLACK_DRAGON("King Black Dragon", ItemID.PRINCE_BLACK_DRAGON , "Wilderness"),
|
||||
|
||||
// Slayer Bosses
|
||||
KALPHITE_QUEEN("Kalphite Queen", ItemID.KALPHITE_PRINCESS, "Other"),
|
||||
SKOTIZO("Skotizo", ItemID.SKOTOS, "Slayer"),
|
||||
GROTESQUE_GUARDIANS("Dusk", ItemID.NOON, "Slayer"),
|
||||
ABYSSAL_SIRE("Abyssal Sire", ItemID.ABYSSAL_ORPHAN, "Slayer"),
|
||||
KRAKEN("Kraken", ItemID.PET_KRAKEN, "Slayer"),
|
||||
CERBERUS("Cerberus", ItemID.HELLPUPPY, "Slayer"),
|
||||
THERMONUCLEAR_SMOKE_DEVIL("Thermonuclear Smoke Devil", ItemID.PET_SMOKE_DEVIL, "Slayer"),
|
||||
|
||||
// Other Bosses
|
||||
GIANT_MOLE("Giant Mole", ItemID.BABY_MOLE, "Other"),
|
||||
CORPOREAL_BEAST("Corporeal Beast", ItemID.PET_CORPOREAL_CRITTER, "Other"),
|
||||
// Dagannoth Kings
|
||||
DAGANNOTH_REX("Dagannoth Rex", ItemID.PET_DAGANNOTH_REX, "Dagannoth Kings"),
|
||||
DAGANNOTH_PRIME("Dagannoth Prime", ItemID.PET_DAGANNOTH_PRIME, "Dagannoth Kings"),
|
||||
DAGANNOTH_SUPREME("Dagannoth Supreme", ItemID.PET_DAGANNOTH_SUPREME, "Dagannoth Kings"),
|
||||
|
||||
// Clue scrolls
|
||||
CLUE_SCROLL_BEGINNER("Clue Scroll (Beginner)", ItemID.CLUE_SCROLL_BEGINNER, "Clue Scrolls"),
|
||||
CLUE_SCROLL_EASY("Clue Scroll (Easy)", ItemID.CLUE_SCROLL_EASY, "Clue Scrolls"),
|
||||
CLUE_SCROLL_MEDIUM("Clue Scroll (Medium)", ItemID.CLUE_SCROLL_MEDIUM, "Clue Scrolls"),
|
||||
CLUE_SCROLL_HARD("Clue Scroll (Hard)", ItemID.CLUE_SCROLL_HARD, "Clue Scrolls"),
|
||||
CLUE_SCROLL_ELITE("Clue Scroll (Elite)", ItemID.CLUE_SCROLL_ELITE, "Clue Scrolls"),
|
||||
CLUE_SCROLL_MASTER("Clue Scroll (Master)", ItemID.CLUE_SCROLL_MASTER, "Clue Scrolls"),
|
||||
|
||||
// Hunter
|
||||
HERBIBOAR("Herbiboar", ItemID.HERBI, "Hunter");
|
||||
|
||||
BossTab(String name, int iconItem, String category)
|
||||
{
|
||||
this.name = name;
|
||||
this.itemID = iconItem;
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final int itemID;
|
||||
private final String category;
|
||||
|
||||
// By Boss Name
|
||||
private static final Map<String, BossTab> byName = buildMap();
|
||||
public static BossTab getByName(String name)
|
||||
{
|
||||
return byName.get(name.toUpperCase());
|
||||
}
|
||||
private static Map<String, BossTab> buildMap()
|
||||
{
|
||||
Map<String, BossTab> byName = new HashMap<>();
|
||||
for (BossTab tab : values())
|
||||
{
|
||||
byName.put(tab.getName().toUpperCase(), tab);
|
||||
}
|
||||
|
||||
return byName;
|
||||
}
|
||||
|
||||
// By Category Name
|
||||
private static final Map<String, ArrayList<BossTab>> byCategoryName = buildCategoryMap();
|
||||
public static ArrayList<BossTab> getByCategoryName(String name)
|
||||
{
|
||||
return byCategoryName.get(name.toUpperCase());
|
||||
}
|
||||
private static Map<String, ArrayList<BossTab>> buildCategoryMap()
|
||||
{
|
||||
Map<String, ArrayList<BossTab>> map = new HashMap<>();
|
||||
for (BossTab tab : values())
|
||||
{
|
||||
map.computeIfAbsent(tab.getCategory().toUpperCase(), e -> new ArrayList<>()).add(tab);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
// All Categories
|
||||
public static final Set<String> categories = getCategories();
|
||||
private static Set<String> getCategories()
|
||||
{
|
||||
Set<String> s = new TreeSet<>();
|
||||
for (BossTab tab : values())
|
||||
{
|
||||
s.add(tab.getCategory());
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Deprecated
|
||||
public class LootRecord
|
||||
{
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final int level;
|
||||
private final int killCount;
|
||||
final Collection<LootTrackerItemEntry> drops;
|
||||
|
||||
public LootRecord(int id, String name, int level, int kc, Collection<LootTrackerItemEntry> drops)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.level = level;
|
||||
this.killCount = kc;
|
||||
this.drops = (drops == null ? new ArrayList<>() : drops);
|
||||
}
|
||||
|
||||
LootRecordCustom toNewFormat()
|
||||
{
|
||||
List<LootTrackerItemEntry> drops = new ArrayList<>();
|
||||
for (LootTrackerItemEntry e : this.getDrops())
|
||||
{
|
||||
drops.add(new LootTrackerItemEntry(e.getName(), e.getId(), e.getQuantity(), e.getPrice(), e.getHaPrice(), e.isStackable()));
|
||||
}
|
||||
|
||||
return new LootRecordCustom(this.getId(), this.getName(), this.getLevel(), this.getKillCount(), drops);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <www.github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class LootRecordCustom
|
||||
{
|
||||
private final int id;
|
||||
private final String name;
|
||||
private final int level;
|
||||
private final int killCount;
|
||||
final Collection<LootTrackerItemEntry> drops;
|
||||
|
||||
public LootRecordCustom(int id, String name, int level, int kc, Collection<LootTrackerItemEntry> drops)
|
||||
{
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.level = level;
|
||||
this.killCount = kc;
|
||||
this.drops = (drops == null ? new ArrayList<>() : drops);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the requested ItemStack to this LootRecord
|
||||
* @param drop ItemStack to add
|
||||
*/
|
||||
public void addDropEntry(LootTrackerItemEntry drop)
|
||||
{
|
||||
drops.add(drop);
|
||||
}
|
||||
|
||||
public static Map<Integer, LootTrackerItemEntry> consolidateLootTrackerItemEntries(Collection<LootRecordCustom> records)
|
||||
{
|
||||
// Store LootTrackerItemEntry by ItemID
|
||||
Map<Integer, LootTrackerItemEntry> itemMap = new HashMap<>();
|
||||
for (LootRecordCustom r : records)
|
||||
{
|
||||
for (LootTrackerItemEntry e : r.getDrops())
|
||||
{
|
||||
int old = 0;
|
||||
if (itemMap.containsKey(e.getId()))
|
||||
{
|
||||
old = itemMap.get(e.getId()).getQuantity();
|
||||
itemMap.remove(e.getId());
|
||||
}
|
||||
itemMap.put(e.getId(), new LootTrackerItemEntry(e.getName(), e.getId(), e.getQuantity() + old, e.getPrice(), e.getHaPrice(), e.isStackable()));
|
||||
}
|
||||
}
|
||||
|
||||
return itemMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder m = new StringBuilder();
|
||||
m.append("LootRecord{id=")
|
||||
.append(id)
|
||||
.append(",name=")
|
||||
.append(name)
|
||||
.append(",level=")
|
||||
.append(level)
|
||||
.append(",killCount=")
|
||||
.append(killCount)
|
||||
.append(",drops=[");
|
||||
|
||||
boolean addComma = false;
|
||||
for (LootTrackerItemEntry d : drops)
|
||||
{
|
||||
if (addComma)
|
||||
{
|
||||
m.append(",");
|
||||
}
|
||||
|
||||
m.append(d.toString());
|
||||
addComma = true;
|
||||
}
|
||||
m.append("]}");
|
||||
|
||||
return m.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import static net.runelite.client.RuneLite.RUNELITE_DIR;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.events.LootTrackerNameChange;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.events.LootTrackerRecordStored;
|
||||
import net.runelite.http.api.RuneLiteAPI;
|
||||
|
||||
@Slf4j
|
||||
@Singleton
|
||||
public class LootRecordWriter
|
||||
{
|
||||
private static final String FILE_EXTENSION = ".log";
|
||||
private static final File LOOT_RECORD_DIR = new File(RUNELITE_DIR, "loots");
|
||||
|
||||
// Data is stored in a folder with the players in-game username
|
||||
private File playerFolder = LOOT_RECORD_DIR;
|
||||
|
||||
private final EventBus bus;
|
||||
|
||||
@Inject
|
||||
public LootRecordWriter(EventBus bus)
|
||||
{
|
||||
this.bus = bus;
|
||||
playerFolder.mkdir();
|
||||
}
|
||||
|
||||
private static String npcNameToFileName(String npcName)
|
||||
{
|
||||
return npcName.toLowerCase().trim() + FILE_EXTENSION;
|
||||
}
|
||||
|
||||
public void setPlayerUsername(String username)
|
||||
{
|
||||
playerFolder = new File(LOOT_RECORD_DIR, username);
|
||||
playerFolder.mkdir();
|
||||
bus.post(new LootTrackerNameChange());
|
||||
}
|
||||
|
||||
public Set<String> getKnownFileNames()
|
||||
{
|
||||
Set<String> fileNames = new HashSet<>();
|
||||
|
||||
File[] files = playerFolder.listFiles((dir, name) -> name.endsWith(FILE_EXTENSION));
|
||||
if (files != null)
|
||||
{
|
||||
for (File f : files)
|
||||
{
|
||||
fileNames.add(f.getName().replace(FILE_EXTENSION, ""));
|
||||
}
|
||||
}
|
||||
|
||||
return fileNames;
|
||||
}
|
||||
|
||||
public synchronized Collection<LootRecordCustom> loadLootTrackerRecords(String npcName)
|
||||
{
|
||||
String fileName = npcNameToFileName(npcName);
|
||||
File file = new File(playerFolder, fileName);
|
||||
Collection<LootRecordCustom> data = new ArrayList<>();
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(file)))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
// Skip empty line at end of file
|
||||
if (line.length() > 0)
|
||||
{
|
||||
LootRecordCustom r = RuneLiteAPI.GSON.fromJson(line, LootRecordCustom.class);
|
||||
data.add(r);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
log.debug("File not found: {}", fileName);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.warn("IOException for file {}: {}", fileName, e.getMessage());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public synchronized boolean addLootTrackerRecord(LootRecordCustom rec)
|
||||
{
|
||||
// Grab file
|
||||
String fileName = npcNameToFileName(rec.getName());
|
||||
File lootFile = new File(playerFolder, fileName);
|
||||
|
||||
// Convert entry to JSON
|
||||
String dataAsString = RuneLiteAPI.GSON.toJson(rec);
|
||||
|
||||
// Open File in append mode and write new data
|
||||
try
|
||||
{
|
||||
BufferedWriter file = new BufferedWriter(new FileWriter(String.valueOf(lootFile), true));
|
||||
file.append(dataAsString);
|
||||
file.newLine();
|
||||
file.close();
|
||||
bus.post(new LootTrackerRecordStored(rec));
|
||||
return true;
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
log.warn("Error writing loot data to file {}: {}", fileName, ioe.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Mostly used to adjust previous loot entries such as adding pet drops/abyssal sire drops
|
||||
public synchronized boolean writeLootTrackerFile(String npcName, Collection<LootRecordCustom> loots)
|
||||
{
|
||||
String fileName = npcNameToFileName(npcName);
|
||||
File lootFile = new File(playerFolder, fileName);
|
||||
|
||||
try
|
||||
{
|
||||
BufferedWriter file = new BufferedWriter(new FileWriter(String.valueOf(lootFile), false));
|
||||
for (LootRecordCustom rec : loots)
|
||||
{
|
||||
// Convert entry to JSON
|
||||
String dataAsString = RuneLiteAPI.GSON.toJson(rec);
|
||||
file.append(dataAsString);
|
||||
file.newLine();
|
||||
}
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
log.warn("Error rewriting loot data to file {}: {}", fileName, ioe.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean deleteLootTrackerRecords(String npcName)
|
||||
{
|
||||
String fileName = npcNameToFileName(npcName);
|
||||
|
||||
File lootFile = new File(playerFolder, fileName);
|
||||
|
||||
if (lootFile.delete())
|
||||
{
|
||||
log.debug("Deleted loot file: {}", fileName);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
log.debug("Couldn't delete file: {}", fileName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<LootRecordCustom> loadAllLootTrackerRecords()
|
||||
{
|
||||
List<LootRecordCustom> recs = new ArrayList<>();
|
||||
|
||||
for (String n : getKnownFileNames())
|
||||
{
|
||||
recs.addAll(loadLootTrackerRecords(n));
|
||||
}
|
||||
|
||||
return recs;
|
||||
}
|
||||
|
||||
public void convertFileFormats()
|
||||
{
|
||||
for (String f : getKnownFileNames())
|
||||
{
|
||||
updateFileFormat(npcNameToFileName(f));
|
||||
}
|
||||
log.info("Done converting");
|
||||
}
|
||||
|
||||
private void updateFileFormat(String fileName)
|
||||
{
|
||||
File lootFile = new File(playerFolder, fileName);
|
||||
Collection<LootRecordCustom> data = new ArrayList<>();
|
||||
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(lootFile)))
|
||||
{
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
{
|
||||
// Skip empty line at end of file
|
||||
if (line.length() > 0)
|
||||
{
|
||||
LootRecordCustom r = RuneLiteAPI.GSON.fromJson(line, LootRecord.class).toNewFormat();
|
||||
data.add(r);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
log.info("File not found: {}", fileName);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.warn("IOException for file {}: {}", fileName, e.getMessage());
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
BufferedWriter file = new BufferedWriter(new FileWriter(String.valueOf(lootFile), false));
|
||||
for (LootRecordCustom rec : data)
|
||||
{
|
||||
// Convert entry to JSON
|
||||
String dataAsString = RuneLiteAPI.GSON.toJson(rec);
|
||||
file.append(dataAsString);
|
||||
file.newLine();
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
log.warn("Error rewriting loot data to file {}: {}", fileName, ioe.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* Copyright (c) 2018, TheStonedTurtle <www.github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class LootTrackerItemEntry
|
||||
{
|
||||
private final String name;
|
||||
private final int id;
|
||||
private int quantity;
|
||||
private final long price;
|
||||
private final long haPrice;
|
||||
private long total;
|
||||
private long haTotal;
|
||||
private final boolean stackable;
|
||||
|
||||
public LootTrackerItemEntry(String name, int id, int quantity, long price, long haPrice, boolean stackable)
|
||||
{
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
this.quantity = quantity;
|
||||
this.price = price;
|
||||
this.haPrice = haPrice;
|
||||
this.stackable = stackable;
|
||||
this.total = price * quantity;
|
||||
this.haTotal = haPrice * quantity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "LootTrackerItemEntry(name=" + name + ",id=" + id + ",quantity=" + quantity + ",price=" + price + ",haprice=" + haPrice + ",total=" + total + ",haTotal=" + haTotal + ",stackable=" + stackable + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package net.runelite.client.plugins.stonedloottracker.data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import lombok.Getter;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
@Getter
|
||||
public enum Pet
|
||||
{
|
||||
// GWD Pets
|
||||
PET_GENERAL_GRAARDOR(ItemID.PET_GENERAL_GRAARDOR, "General graador"),
|
||||
PET_KREEARRA(ItemID.PET_KREEARRA, "Kree'arra"),
|
||||
PET_KRIL_TSUTSAROTH(ItemID.PET_KRIL_TSUTSAROTH, "K'ril tsutsaroth"),
|
||||
PET_ZILYANA(ItemID.PET_ZILYANA, "Commander zilyana"),
|
||||
// Wildy Pets
|
||||
CALLISTO_CUB(ItemID.CALLISTO_CUB, "Callisto"),
|
||||
PET_CHAOS_ELEMENTAL(ItemID.PET_CHAOS_ELEMENTAL, "Chaos Elemental", "Chaos Fanatic"),
|
||||
SCORPIAS_OFFSPRING(ItemID.SCORPIAS_OFFSPRING, "Scorpia"),
|
||||
VENENATIS_SPIDERLING(ItemID.VENENATIS_SPIDERLING, "Venenatis"),
|
||||
VETION_JR(ItemID.VETION_JR, "Vet'ion"),
|
||||
// KBD isn't really in wildy but meh
|
||||
PRINCE_BLACK_DRAGON(ItemID.PRINCE_BLACK_DRAGON, "King Black Dragon"),
|
||||
// Slayer Pets
|
||||
ABYSSAL_ORPHAN(ItemID.ABYSSAL_ORPHAN, "Abyssal Sire"),
|
||||
HELLPUPPY(ItemID.HELLPUPPY, "Cerberus"),
|
||||
NOON(ItemID.NOON, "Noon", "Dusk"),
|
||||
PET_KRAKEN(ItemID.PET_KRAKEN, "Kraken"),
|
||||
PET_SMOKE_DEVIL(ItemID.PET_SMOKE_DEVIL, "Thermonuclear Smoke Devil"),
|
||||
SKOTOS(ItemID.SKOTOS, "Skotizo"),
|
||||
// Other Bosses
|
||||
BABY_MOLE(ItemID.BABY_MOLE, "Giant Mole"),
|
||||
KALPHITE_PRINCESS(ItemID.KALPHITE_PRINCESS, "Kalphite Queen"),
|
||||
OLMLET(ItemID.OLMLET, "Chambers of Xeric"),
|
||||
LIL_ZIK(ItemID.LIL_ZIK, "Theatre of Blood"),
|
||||
PET_DARK_CORE(ItemID.PET_DARK_CORE, "Corporeal Beast"),
|
||||
PET_SNAKELING(ItemID.PET_SNAKELING, "Zulrah"),
|
||||
PET_DAGANNOTH_REX(ItemID.PET_DAGANNOTH_REX, "Dagannoth Rex"),
|
||||
PET_DAGANNOTH_PRIME(ItemID.PET_DAGANNOTH_PRIME, "Dagannoth Prime"),
|
||||
PET_DAGANNOTH_SUPREME(ItemID.PET_DAGANNOTH_SUPREME, "Dagannoth Supreme"),
|
||||
VORKI(ItemID.VORKI, "Vorkath"),
|
||||
BLOODHOUND(ItemID.BLOODHOUND, "Clue Scroll Master"),
|
||||
HERBI(ItemID.HERBI, "Herbiboar");
|
||||
|
||||
private final int petID;
|
||||
private final String[] bossNames;
|
||||
private static final Map<String, Pet> byBossName = buildBossMap();
|
||||
|
||||
Pet(int id, String... bossNames)
|
||||
{
|
||||
this.petID = id;
|
||||
this.bossNames = bossNames;
|
||||
}
|
||||
|
||||
public static Pet getByBossName(String name)
|
||||
{
|
||||
return byBossName.get(name.toUpperCase());
|
||||
}
|
||||
|
||||
private static Map<String, Pet> buildBossMap()
|
||||
{
|
||||
Map<String, Pet> byName = new HashMap<>();
|
||||
for (Pet pet : values())
|
||||
{
|
||||
String[] droppingBosses = pet.getBossNames();
|
||||
for (String bossName : droppingBosses)
|
||||
{
|
||||
byName.put(bossName.toUpperCase(), pet);
|
||||
}
|
||||
}
|
||||
return byName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,929 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <www.github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.runelite.api.ItemID;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum UniqueItem
|
||||
{
|
||||
// Shared "Uniques" (Dropped by multiple activities)
|
||||
// God Wars
|
||||
GODSWORD_SHARD_1("Godsword shard 1", ItemID.GODSWORD_SHARD_1, "Kree'arra", "General Graardor", "Commander Zilyana", "K'ril Tsutsaroth"),
|
||||
GODSWORD_SHARD_2("Godsword shard 2", ItemID.GODSWORD_SHARD_2, "Kree'arra", "General Graardor", "Commander Zilyana", "K'ril Tsutsaroth"),
|
||||
GODSWORD_SHARD_3("Godsword shard 3", ItemID.GODSWORD_SHARD_3, "Kree'arra", "General Graardor", "Commander Zilyana", "K'ril Tsutsaroth"),
|
||||
// Wildy
|
||||
PET_CHAOS_ELEMENTAL("Pet chaos elemental", ItemID.PET_CHAOS_ELEMENTAL, "Chaos Elemental", "Chaos Fanatic"),
|
||||
// MYSTERIOUS_EMBLEM("Mysterious emblem", ItemID.MYSTERIOUS_EMBLEM , ""),
|
||||
CURVED_BONE("Curved bone", ItemID.CURVED_BONE, "Callisto", "Vet'ion", "Venenatis", "Giant Mole"),
|
||||
DRAGON_PICKAXE("Dragon pickaxe", ItemID.DRAGON_PICKAXE , "Callisto", "Vet'ion", "Venenatis", "King Black Dragon", "Chaos Elemental"),
|
||||
DRAGON_2H_SWORD("Dragon 2h sword", ItemID.DRAGON_2H_SWORD , "Callisto", "Vet'ion", "Venenatis", "Kalphite Queen"),
|
||||
// Other
|
||||
DRAGON_CHAINBODY("Dragon chainbody", ItemID.DRAGON_CHAINBODY_3140, "Thermonuclear Smoke Devil", "Kalphite Queen"),
|
||||
DRAGON_AXE("Dragon axe", ItemID.DRAGON_AXE, "Dagannoth Rex", "Dagannoth Prime", "Dagannoth Supreme"),
|
||||
UNCUT_ONYX("Uncut onyx", ItemID.UNCUT_ONYX, "Zulrah", "Skotizo"),
|
||||
DRACONIC_VISAGE("Draconic visage", ItemID.DRACONIC_VISAGE, "Vorkath", "King Black Dragon"),
|
||||
|
||||
// Unique Items
|
||||
// Barrows Uniques
|
||||
// Ahrim
|
||||
AHRIMS_HOOD("Ahrim's hood", ItemID.AHRIMS_HOOD, "Barrows", "Ahrims", 0),
|
||||
AHRIMS_ROBETOP("Ahrim's robetop", ItemID.AHRIMS_ROBETOP, "Barrows", "Ahrims", 0),
|
||||
AHRIMS_ROBESKIRT("Ahrim's robeskirt", ItemID.AHRIMS_ROBESKIRT, "Barrows", "Ahrims", 0),
|
||||
AHRIMS_STAFF("Ahrim's staff", ItemID.AHRIMS_STAFF, "Barrows", "Ahrims", 0),
|
||||
// Dharok
|
||||
DHAROKS_HELM("Dharok's helm", ItemID.DHAROKS_HELM, "Barrows", "Dharoks", 1),
|
||||
DHAROKS_PLATEBODY("Dharok's platebody", ItemID.DHAROKS_PLATEBODY, "Barrows", "Dharoks", 1),
|
||||
DHAROKS_PLATELEGS("Dharok's platelegs", ItemID.DHAROKS_PLATELEGS, "Barrows", "Dharoks", 1),
|
||||
DHAROKS_GREATAXE("Dharok's greataxe", ItemID.DHAROKS_GREATAXE, "Barrows", "Dharoks", 1),
|
||||
// Guthans
|
||||
GUTHANS_HELM("Guthan's helm", ItemID.GUTHANS_HELM, "Barrows", "Guthans", 2),
|
||||
GUTHANS_PLATEBODY("Guthan's platebody", ItemID.GUTHANS_PLATEBODY, "Barrows", "Guthans", 2),
|
||||
GUTHANS_CHAINSKIRT("Guthan's Chainskirt", ItemID.GUTHANS_CHAINSKIRT, "Barrows", "Guthans", 2),
|
||||
GUTHANS_WARSPEAR("Guthan's warspear", ItemID.GUTHANS_WARSPEAR, "Barrows", "Guthans", 2),
|
||||
// Karils
|
||||
KARILS_COIF("Karil's coif", ItemID.KARILS_COIF, "Barrows", "Karils", 3),
|
||||
KARILS_LEATHERTOP("Karil's leathertop", ItemID.KARILS_LEATHERTOP, "Barrows", "Karils", 3),
|
||||
KARILS_LEATHERSKIRT("Karil's leatherskirt", ItemID.KARILS_LEATHERSKIRT, "Barrows", "Karils", 3),
|
||||
KARILS_CROSSBOW("Karil's crossbow ", ItemID.KARILS_CROSSBOW, "Barrows", "Karils", 3),
|
||||
//Torag
|
||||
TORAGS_HELM("Torag's helm", ItemID.TORAGS_HELM, "Barrows", "Torags", 4),
|
||||
TORAGS_PLATEBODY("Torags's platebody", ItemID.TORAGS_PLATEBODY, "Barrows", "Torags", 4),
|
||||
TORAGS_PLATELEGS("Torags's platelegs", ItemID.TORAGS_PLATELEGS, "Barrows", "Torags", 4),
|
||||
TORAGS_HAMMERS("Torag's hammers", ItemID.TORAGS_HAMMERS, "Barrows", "Torags", 4),
|
||||
// Veracs
|
||||
VERACS_HELM("Verac's helm", ItemID.VERACS_HELM, "Barrows", "Veracs", 5),
|
||||
VERACS_BRASSARD("Verac's brassard", ItemID.VERACS_BRASSARD, "Barrows", "Veracs", 5),
|
||||
VERACS_PLATESKIRT("Verac's plateskirt", ItemID.VERACS_PLATESKIRT, "Barrows", "Veracs", 5),
|
||||
VERACS_FLAIL("Verac's flail", ItemID.VERACS_FLAIL, "Barrows", "Veracs", 5),
|
||||
|
||||
// Raids Uniques
|
||||
// Mage
|
||||
KODAI_INSIGNIA("Kodai insignia", ItemID.KODAI_INSIGNIA, "Chambers of Xeric", "Mage", 0),
|
||||
ANCESTRAL_HAT("Ancestral hat", ItemID.ANCESTRAL_HAT, "Chambers of Xeric", "Mage", 0),
|
||||
ANCESTRAL_ROBE_TOP("Ancestral robe top", ItemID.ANCESTRAL_ROBE_TOP, "Chambers of Xeric", "Mage", 0),
|
||||
ANCESTRAL_ROBE_BOTTOM("Ancestral robe bottom", ItemID.ANCESTRAL_ROBE_BOTTOM, "Chambers of Xeric", "Mage", 0),
|
||||
// Range
|
||||
DRAGON_THROWNAXE("Dragon thrownaxe", ItemID.DRAGON_THROWNAXE, "Chambers of Xeric", "Range", 1),
|
||||
DRAGON_HUNTER_CROSSBOW("Dragon hunter crossbow", ItemID.DRAGON_HUNTER_CROSSBOW, "Chambers of Xeric", "Range", 1),
|
||||
TWISTED_BUCKLER("Twisted buckler", ItemID.TWISTED_BUCKLER, "Chambers of Xeric", "Range", 1),
|
||||
TWISTED_BOW("Twisted bow", ItemID.TWISTED_BOW, "Chambers of Xeric", "Range", 1),
|
||||
// Melee
|
||||
DRAGON_SWORD("Dragon sword", ItemID.DRAGON_SWORD, "Chambers of Xeric", "Melee", 2),
|
||||
DRAGON_CLAWS("Dragon claws", ItemID.DRAGON_CLAWS, "Chambers of Xeric", "Melee", 2),
|
||||
DINHS_BULWARK("Dinh's bulwark", ItemID.DINHS_BULWARK, "Chambers of Xeric", "Melee", 2),
|
||||
ELDER_MAUL("Elder maul", ItemID.ELDER_MAUL, "Chambers of Xeric", "Melee", 2),
|
||||
// Prayers
|
||||
TORN_PRAYER_SCROLL("Torn prayer scroll", ItemID.TORN_PRAYER_SCROLL, "Chambers of Xeric", "Prayer", 3),
|
||||
ARCANE_PRAYER_SCROLL("Arcane prayer scroll", ItemID.ARCANE_PRAYER_SCROLL, "Chambers of Xeric", "Prayer", 3),
|
||||
DEXTEROUS_PRAYER_SCROLL("Dexterous prayer scroll", ItemID.DEXTEROUS_PRAYER_SCROLL, "Chambers of Xeric", "Prayer", 3),
|
||||
// Other
|
||||
DRAGON_HARPOON("Dragon harpoon", ItemID.DRAGON_HARPOON, "Chambers of Xeric", "Other", 4),
|
||||
DARK_RELIC("Dark relic", ItemID.DARK_RELIC, "Chambers of Xeric", "Other", 4),
|
||||
|
||||
// Raids 2 Unqiues (Theater of Blood)
|
||||
// Weapons / Pet
|
||||
GHRAZI_RAPIER("Ghrazi rapier", ItemID.GHRAZI_RAPIER, "Theatre of Blood", "Weapons", 0),
|
||||
SCYTHE_OF_VITUR_UNCHARGED("Scythe of vitur (uncharged)", ItemID.SCYTHE_OF_VITUR_UNCHARGED, "Theatre of Blood", "Weapons", 0),
|
||||
SANGUINESTI_STAFF_UNCHAGRED("Sanguinesti staff (uncharged)", ItemID.SANGUINESTI_STAFF_UNCHARGED, "Theatre of Blood", "Weapons", 0),
|
||||
LIL_ZIK("Lil' zik", ItemID.LIL_ZIK, "Theatre of Blood", "Weapons", 0),
|
||||
// Armor
|
||||
AVERNIC_DEFENDER_HILT("Avernic defender hilt", ItemID.AVERNIC_DEFENDER_HILT, "Theatre of Blood", "Armor", 1),
|
||||
JUSTICIAR_FACEGUARD("Justiciar faceguard", ItemID.JUSTICIAR_FACEGUARD, "Theatre of Blood", "Armor", 1),
|
||||
JUSTICIAR_CHESTGUARD("Justiciar chestguard", ItemID.JUSTICIAR_CHESTGUARD, "Theatre of Blood", "Armor", 1),
|
||||
JUSTICIAR_LEGGUARDS("Justiciar legguards", ItemID.JUSTICIAR_LEGGUARDS, "Theatre of Blood", "Armor", 1),
|
||||
|
||||
|
||||
// Zulrah
|
||||
// Uniques
|
||||
TANZANITE_FANG("Tanzanite fang", ItemID.TANZANITE_FANG, "Zulrah", "Uniques", -1),
|
||||
MAGIC_FANG("Magic fang", ItemID.MAGIC_FANG, "Zulrah", "Uniques", -1),
|
||||
SERPENTINE_VISAGE("Serpentine visage", ItemID.SERPENTINE_VISAGE, "Zulrah", "Uniques", -1),
|
||||
// Rares
|
||||
PET_SNAKELING("Pet snakeling", ItemID.PET_SNAKELING, "Zulrah", "Rares", 0),
|
||||
TANZANITE_MUTAGEN("Tanzanite mutagen", ItemID.TANZANITE_MUTAGEN, "Zulrah", "Rares", 0),
|
||||
MAGMA_MUTAGEN("Magma mutagen", ItemID.MAGMA_MUTAGEN, "Zulrah", "Rares", 0),
|
||||
JAR_OF_SWAMP("Jar of swamp", ItemID.JAR_OF_SWAMP, "Zulrah", "Rares", 0),
|
||||
|
||||
// Vorkath
|
||||
DRAGONBONE_NECKLACE("Dragonbone necklace", ItemID.DRAGONBONE_NECKLACE, "Vorkath", "Uniques", 0),
|
||||
VORKATHS_HEAD("Vorkath's head", ItemID.VORKATHS_HEAD_21907, "Vorkath", "Uniques", 0),
|
||||
JAR_OF_DECAY("Jar of decay", ItemID.JAR_OF_DECAY, "Vorkath", "Uniques", 0),
|
||||
SKELETAL_VISAGE("Skeletal visage", ItemID.SKELETAL_VISAGE, "Vorkath", "Uniques", -1),
|
||||
VORKI("Vorki", ItemID.VORKI, "Vorkath", "Uniques", -1),
|
||||
|
||||
|
||||
// God Wars Dungeon
|
||||
// Kree'arra (Armadyl)
|
||||
ARMADYL_HELMET("Armadyl helmet", ItemID.ARMADYL_HELMET, "Kree'arra", "Uniques", 0),
|
||||
ARMADYL_CHESTPLATE("Armadyl chestplate", ItemID.ARMADYL_CHESTPLATE, "Kree'arra", "Uniques", 0),
|
||||
ARMADYL_CHAINSKIRT("Armadyl chainskirt", ItemID.ARMADYL_CHAINSKIRT, "Kree'arra", "Uniques", 0),
|
||||
ARMADYL_HILT("Armadyl hilt", ItemID.ARMADYL_HILT, "Kree'arra", "Uniques", 0),
|
||||
PET_KREEARRA("Pet Kree'arra", ItemID.PET_KREEARRA, "Kree'arra", "Pet", -1),
|
||||
// General Graardor (Bandos)
|
||||
BANDOS_CHESTPLATE("Bandos chestplate", ItemID.BANDOS_CHESTPLATE, "General Graardor", "Uniques", 0),
|
||||
BANDOS_TASSETS("Bandos tassets", ItemID.BANDOS_TASSETS, "General Graardor", "Uniques", 0),
|
||||
BANDOS_BOOTS("Bandos boots", ItemID.BANDOS_BOOTS, "General Graardor", "Uniques", 0),
|
||||
BANDOS_HILT("Bandos hilt", ItemID.BANDOS_HILT, "General Graardor", "Uniques", 0),
|
||||
PET_GENERAL_GRAARDOR("Pet general graardor", ItemID.PET_GENERAL_GRAARDOR, "General Graardor", "Pet", -1),
|
||||
// Command Zilyana (Saradomin)
|
||||
SARADOMIN_SWORD("Saradomin sword", ItemID.SARADOMIN_SWORD, "Commander Zilyana", "Uniques", 0),
|
||||
ARMADYL_CROSSBOW("Armadyl crossbow", ItemID.ARMADYL_CROSSBOW, "Commander Zilyana", "Uniques", 0),
|
||||
SARADOMINS_LIGHT("Saradomins light", ItemID.SARADOMINS_LIGHT, "Commander Zilyana", "Uniques", 0),
|
||||
SARADOMIN_HILT("Saradomin hilt", ItemID.SARADOMIN_HILT, "Commander Zilyana", "Uniques", 0),
|
||||
PET_ZILYANA("Pet zilyana", ItemID.PET_ZILYANA, "Commander Zilyana", "Pet", -1),
|
||||
// K'ril Tsutsaroth (Zammy)
|
||||
STEAM_BATTLESTAFF("Steam battlestaff", ItemID.STEAM_BATTLESTAFF, "K'ril Tsutsaroth", "Uniques", 0),
|
||||
STAFF_OF_THE_DEAD("Staff of the dead", ItemID.STAFF_OF_THE_DEAD, "K'ril Tsutsaroth", "Uniques", 0),
|
||||
ZAMORAKIAN_SPEAR("Zamorakian spear", ItemID.ZAMORAKIAN_SPEAR, "K'ril Tsutsaroth", "Uniques", 0),
|
||||
ZAMORAK_HILT("Zamorak hilt", ItemID.ZAMORAK_HILT, "K'ril Tsutsaroth", "Uniques", 0),
|
||||
PET_KRIL_TSUTSAROTH("Pet k'ril tsutsaroth", ItemID.PET_KRIL_TSUTSAROTH, "K'ril Tsutsaroth", "Pet", -1),
|
||||
|
||||
|
||||
// Wildy Bosses
|
||||
// Vet'ion
|
||||
RING_OF_THE_GODS("Ring of the gods", ItemID.RING_OF_THE_GODS , "Vet'ion", "Uniques", 0),
|
||||
VETION_JR("Vet'ion jr.", ItemID.VETION_JR , "Vet'ion", "Uniques", 0),
|
||||
SKELETON_CHAMPION_SCROLL("Skeleton champion scroll", ItemID.SKELETON_CHAMPION_SCROLL , "Vet'ion", "Uniques", 0),
|
||||
// Venenatis
|
||||
TREASONOUS_RING("Treasonous ring", ItemID.TREASONOUS_RING , "Venenatis", "Uniques", -1),
|
||||
VENENATIS_SPIDERLING("Venenatis spiderling", ItemID.VENENATIS_SPIDERLING , "Venenatis", "Uniques", -1),
|
||||
// Callisto
|
||||
TYRANNICAL_RING("Tyrannical ring", ItemID.TYRANNICAL_RING , "Callisto", "Uniques", -1),
|
||||
CALLISTO_CUB("Callisto cub", ItemID.CALLISTO_CUB , "Callisto", "Uniques", -1),
|
||||
// Chaos Elemental Uniques are all in Shared
|
||||
// Chaos Fanatic
|
||||
ODIUM_SHARD_1("Odium shard 1", ItemID.ODIUM_SHARD_1 , "Chaos Fanatic", "Uniques", -1),
|
||||
MALEDICTION_SHARD_1("Malediction shard 1", ItemID.MALEDICTION_SHARD_1 , "Chaos Fanatic", "Uniques", -1),
|
||||
// Crazy Archaeologist
|
||||
ODIUM_SHARD_2("Odium shard 2", ItemID.ODIUM_SHARD_2 , "Crazy Archaeologist", "Uniques", 0),
|
||||
MALEDICTION_SHARD_2("Malediction shard 2", ItemID.MALEDICTION_SHARD_2 , "Crazy Archaeologist", "Uniques", 0),
|
||||
FEDORA("Fedora", ItemID.FEDORA , "Crazy Archaeologist", "Uniques", 0),
|
||||
// Scorpia
|
||||
ODIUM_SHARD_3("Odium shard 3", ItemID.ODIUM_SHARD_3 , "Scorpia", "Uniques", 0),
|
||||
MALEDICTION_SHARD_3("Malediction shard 3", ItemID.MALEDICTION_SHARD_3 , "Scorpia", "Uniques", 0),
|
||||
SCORPIAS_OFFSPRING("Scorpia's offspring", ItemID.SCORPIAS_OFFSPRING , "Scorpia", "Uniques", 0),
|
||||
// King Black Dragon,
|
||||
KBD_HEADS("Kbd heads", ItemID.KBD_HEADS , "King Black Dragon", "Uniques", -1),
|
||||
PRINCE_BLACK_DRAGON("Prince black dragon", ItemID.PRINCE_BLACK_DRAGON , "King Black Dragon", "Uniques", -1),
|
||||
|
||||
// Slayer Bosses
|
||||
// Skotizo
|
||||
DARK_CLAW("Dark claw", ItemID.DARK_CLAW, "Skotizo", "Uniques", -1),
|
||||
SKOTOS("Skotos", ItemID.SKOTOS, "Skotizo", "Uniques", -1),
|
||||
JAR_OF_DARKNESS("Jar of darkness", ItemID.JAR_OF_DARKNESS, "Skotizo", "Uniques", -1),
|
||||
// Grotesque Guardians
|
||||
GRANITE_GLOVES("Granite gloves", ItemID.GRANITE_GLOVES, "Dusk", "Uniques", 0),
|
||||
GRANITE_RING("Granite ring", ItemID.GRANITE_RING, "Dusk", "Uniques", 0),
|
||||
GRANITE_HAMMER("Granite hammer", ItemID.GRANITE_HAMMER, "Dusk", "Uniques", 0),
|
||||
BLACK_TOURMALINE_CORE("Black touramline core", ItemID.BLACK_TOURMALINE_CORE, "Dusk", "Uniques 2", 1),
|
||||
NOON("Noon", ItemID.NOON, "Dusk", "Uniques 2", 1),
|
||||
JAR_OF_STONE("Jar of stone", ItemID.JAR_OF_STONE, "Dusk", "Uniques 2", 1),
|
||||
// Abyssal Sire
|
||||
UNSIRED("Unsired", ItemID.UNSIRED, "Abyssal Sire", "Uniques", 0),
|
||||
BLUDGEON_CLAW("Bludgeon claw", ItemID.BLUDGEON_CLAW, "Abyssal Sire", "Uniques", 0),
|
||||
BLUDGEON_SPINE("Bludgeon spine", ItemID.BLUDGEON_SPINE, "Abyssal Sire", "Uniques", 0),
|
||||
BLUDGEON_AXON("Bludgeon axon", ItemID.BLUDGEON_AXON, "Abyssal Sire", "Uniques", 0),
|
||||
ABYSSAL_DAGGER("Abyssal dagger", ItemID.ABYSSAL_DAGGER, "Abyssal Sire", "Uniques 2", 1),
|
||||
ABYSSAL_WHIP("Abyssal whip", ItemID.ABYSSAL_WHIP, "Abyssal Sire", "Uniques 2", 1),
|
||||
ABYSSAL_ORPHAN("Abyssal orphan", ItemID.ABYSSAL_ORPHAN, "Abyssal Sire", "Uniques 2", 1),
|
||||
JAR_OF_MIASMA("Jar of miasma", ItemID.JAR_OF_MIASMA, "Abyssal Sire", "Uniques 2", 1),
|
||||
ABYSSAL_HEAD("Abyssal head", ItemID.ABYSSAL_HEAD, "Abyssal Sire", "Uniques 2", 1),
|
||||
// Kraken
|
||||
TRIDENT_OF_THE_SEAS_FULL("Trident of the seas (full)", ItemID.TRIDENT_OF_THE_SEAS_FULL, "Kraken", "Uniques", 0),
|
||||
KRAKEN_TENTACLE("Kraken tentacle", ItemID.KRAKEN_TENTACLE, "Kraken", "Uniques", 0),
|
||||
JAR_OF_DIRT("Jar of dirt", ItemID.JAR_OF_DIRT, "Kraken", "Uniques", 0),
|
||||
PET_KRAKEN("Pet kraken", ItemID.PET_KRAKEN, "Kraken", "Uniques", 0),
|
||||
// Cerberus
|
||||
PRIMORDIAL_CRYSTAL("Primordial crystal", ItemID.PRIMORDIAL_CRYSTAL, "Cerberus", "Uniques", 0),
|
||||
PEGASIAN_CRYSTAL("Pegasian crystal", ItemID.PEGASIAN_CRYSTAL, "Cerberus", "Uniques", 0),
|
||||
ETERNAL_CRYSTAL("Eternal crystal", ItemID.ETERNAL_CRYSTAL, "Cerberus", "Uniques", 0),
|
||||
SMOULDERING_STONE("Smouldering stone", ItemID.SMOULDERING_STONE, "Cerberus", "Uniques", 1),
|
||||
JAR_OF_SOULS("Jar of souls", ItemID.JAR_OF_SOULS, "Cerberus", "Uniques", 1),
|
||||
HELLPUPPY("Hellpuppy", ItemID.HELLPUPPY, "Cerberus", "Uniques", 1),
|
||||
// Thermonuclear Smoke Devil
|
||||
SMOKE_BATTLESTAFF("Smoke battlestaff", ItemID.SMOKE_BATTLESTAFF, "Thermonuclear Smoke Devil", "Uniques", -1),
|
||||
OCCULT_NECKLACE("Occult necklace", ItemID.OCCULT_NECKLACE, "Thermonuclear Smoke Devil", "Uniques", -1),
|
||||
PET_SMOKE_DEVIL("Pet smoke devil", ItemID.PET_SMOKE_DEVIL, "Thermonuclear Smoke Devil", "Uniques", -1),
|
||||
|
||||
|
||||
// Other Bosses
|
||||
// Giant Mole
|
||||
BABY_MOLE("Baby Mole", ItemID.BABY_MOLE, "Giant Mole", "Uniques", -1),
|
||||
// Kalphite Queen
|
||||
KQ_HEAD("Kq head", ItemID.KQ_HEAD, "Kalphite Queen", "Uniques", -1),
|
||||
JAR_OF_SAND("Jar of sand", ItemID.JAR_OF_SAND, "Kalphite Queen", "Uniques", -1),
|
||||
KALPHITE_PRINCESS("Kalphite princess", ItemID.KALPHITE_PRINCESS, "Kalphite Queen", "Uniques", -1),
|
||||
// Corporeal Beast
|
||||
SPIRIT_SHIELD("Spirit shield", ItemID.SPIRIT_SHIELD, "Corporeal Beast", "Uniques", 0),
|
||||
HOLY_ELIXIR("Holy elixir", ItemID.HOLY_ELIXIR, "Corporeal Beast", "Uniques", 0),
|
||||
PET_DARK_CORE("Pet dark core", ItemID.PET_DARK_CORE, "Corporeal Beast", "Uniques", 0),
|
||||
SPECTRAL_SIGIL("Spectral sigil", ItemID.SPECTRAL_SIGIL, "Corporeal Beast", "Sigil", 1),
|
||||
ARCANE_SIGIL("Arcane sigil", ItemID.ARCANE_SIGIL, "Corporeal Beast", "Sigil", 1),
|
||||
ELYSIAN_SIGIL("Elysian sigil", ItemID.ELYSIAN_SIGIL, "Corporeal Beast", "Sigil", 1),
|
||||
// Dagannoth Rex
|
||||
WARRIOR_RING("Warrior ring", ItemID.WARRIOR_RING, "Dagannoth Rex", "Uniques", -1),
|
||||
BERSERKER_RING("Berserk ring", ItemID.BERSERKER_RING, "Dagannoth Rex", "Uniques", -1),
|
||||
PET_DAGANNOTH_REX("Pet dagannoth rex", ItemID.PET_DAGANNOTH_REX, "Dagannoth Rex", "Uniques", -1),
|
||||
// Dagannoth Prime
|
||||
MUD_BATTLESTAFF("Mud battlestaff", ItemID.MUD_BATTLESTAFF, "Dagannoth Prime", "Uniques", -1),
|
||||
SEERS_RING("Seers ring", ItemID.SEERS_RING, "Dagannoth Prime", "Uniques", -1),
|
||||
PET_DAGANNOTH_PRIME("Pet dagannoth prime", ItemID.PET_DAGANNOTH_PRIME, "Dagannoth Prime", "Uniques", -1),
|
||||
// Dagannoth Supreme
|
||||
SEERCULL("Seercrull", ItemID.SEERCULL, "Dagannoth Supreme", "Uniques", -1),
|
||||
ARCHERS_RING("Archers ring", ItemID.ARCHERS_RING, "Dagannoth Supreme", "Uniques", -1),
|
||||
PET_DAGANNOTH_SUPREME("Pet dagannoth supreme", ItemID.PET_DAGANNOTH_SUPREME, "Dagannoth Supreme", "Uniques", -1),
|
||||
|
||||
// Beginner Clue Scrolls
|
||||
MOLE_SLIPPERS("Mole slippers", ItemID.MOLE_SLIPPERS, "Clue Scroll (Beginner)", "Slippers", -1),
|
||||
FROG_SLIPPERS("Frog slippers", ItemID.FROG_SLIPPERS, "Clue Scroll (Beginner)", "Slippers", -1),
|
||||
BEAR_FEET("Bear slippers", ItemID.BEAR_FEET, "Clue Scroll (Beginner)", "Slippers", -1),
|
||||
DEMON_FEET("Demon slippers", ItemID.DEMON_FEET, "Clue Scroll (Beginner)", "Slippers", -1),
|
||||
SANDWICH_LADY_HAT("Sandwich lady hat", ItemID.SANDWICH_LADY_HAT, "Clue Scroll (Beginner)", "Sandwich Lady", 0),
|
||||
SANDWICH_LADY_TOP("Sandwich lady top", ItemID.SANDWICH_LADY_TOP, "Clue Scroll (Beginner)", "Sandwich Lady", 0),
|
||||
SANDWICH_LADY_BOTTOM("Sandwich lady bottom", ItemID.SANDWICH_LADY_BOTTOM, "Clue Scroll (Beginner)", "Sandwich Lady", 0),
|
||||
MONKS_ROBE_TOP_T("Monk robe top (t)", ItemID.MONKS_ROBE_TOP_T, "Clue Scroll (Beginner)", "Monk Robes", 1),
|
||||
MONKS_ROBE_T("Monk robe (t)", ItemID.MONKS_ROBE_T, "Clue Scroll (Beginner)", "Monk Robes", 1),
|
||||
JESTER_CAPE("Jester cape", ItemID.JESTER_CAPE, "Clue Scroll (Beginner)", "Other", 2),
|
||||
SHOULDER_PARROT("Shoulder parrot", ItemID.SHOULDER_PARROT, "Clue Scroll (Beginner)", "Other", 2),
|
||||
AMULET_OF_DEFENCE_T("Amulet of Defence (t)", ItemID.AMULET_OF_DEFENCE_T, "Clue Scroll (Beginner)", "Other", 2),
|
||||
RUNE_SCIMITAR_ORNAMENT_KIT_GUTHIX("Rune scimitar Guthix ornament kit", ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_GUTHIX, "Clue Scroll (Beginner)", "God Ornament Kit", 3),
|
||||
RUNE_SCIMITAR_ORNAMENT_KIT_SARADOMIN("Rune scimitar Saradomin ornament kit", ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_SARADOMIN, "Clue Scroll (Beginner)", "God Ornament Kit", 3),
|
||||
RUNE_SCIMITAR_ORNAMENT_KIT_ZAMORAK("Rune scimitar Zamorak ornament kit", ItemID.RUNE_SCIMITAR_ORNAMENT_KIT_ZAMORAK, "Clue Scroll (Beginner)", "God Ornament Kit", 3),
|
||||
|
||||
// Easy Clue Scrolls
|
||||
BRONZE_FULL_HELM_T("Bronze full helm (t)", ItemID.BRONZE_FULL_HELM_T, "Clue Scroll (Easy)", "Armor", -1),
|
||||
BRONZE_PLATEBODY_T("Bronze platebody (t)", ItemID.BRONZE_PLATEBODY_T, "Clue Scroll (Easy)", "Armor", -1),
|
||||
BRONZE_PLATELEGS_T("Bronze platelegs (t)", ItemID.BRONZE_PLATELEGS_T, "Clue Scroll (Easy)", "Armor", -1),
|
||||
BRONZE_PLATESKIRT_T("Bronze plateskirt (t)", ItemID.BRONZE_PLATESKIRT_T, "Clue Scroll (Easy)", "Armor", -1),
|
||||
BRONZE_KITESHIELD_T("Bronze kiteshield (t)", ItemID.BRONZE_KITESHIELD_T, "Clue Scroll (Easy)", "Armor", -1),
|
||||
BRONZE_FULL_HELM_G("Bronze full helm (g)", ItemID.BRONZE_FULL_HELM_G, "Clue Scroll (Easy)", "Armor", 0),
|
||||
BRONZE_PLATEBODY_G("Bronze platebody (g)", ItemID.BRONZE_PLATEBODY_G, "Clue Scroll (Easy)", "Armor", 0),
|
||||
BRONZE_PLATELEGS_G("Bronze platelegs (g)", ItemID.BRONZE_PLATELEGS_G, "Clue Scroll (Easy)", "Armor", 0),
|
||||
BRONZE_PLATESKIRT_G("Bronze plateskirt (g)", ItemID.BRONZE_PLATESKIRT_G, "Clue Scroll (Easy)", "Armor", 0),
|
||||
BRONZE_KITESHIELD_G("Bronze kiteshield (g)", ItemID.BRONZE_KITESHIELD_G, "Clue Scroll (Easy)", "Armor", 0),
|
||||
IRON_FULL_HELM_T("Iron full helm (t)", ItemID.IRON_FULL_HELM_T, "Clue Scroll (Easy)", "Armor", 1),
|
||||
IRON_PLATEBODY_T("Iron platebody (t)", ItemID.IRON_PLATEBODY_T, "Clue Scroll (Easy)", "Armor", 1),
|
||||
IRON_PLATELEGS_T("Iron platelegs (t)", ItemID.IRON_PLATELEGS_T, "Clue Scroll (Easy)", "Armor", 1),
|
||||
IRON_PLATESKIRT_T("Iron plateskirt (t)", ItemID.IRON_PLATESKIRT_T, "Clue Scroll (Easy)", "Armor", 1),
|
||||
IRON_KITESHIELD_T("Iron kiteshield (t)", ItemID.IRON_KITESHIELD_T, "Clue Scroll (Easy)", "Armor", 1),
|
||||
IRON_FULL_HELM_G("Iron full helm (g)", ItemID.IRON_FULL_HELM_G, "Clue Scroll (Easy)", "Armor", 2),
|
||||
IRON_PLATEBODY_G("Iron platebody (g)", ItemID.IRON_PLATEBODY_G, "Clue Scroll (Easy)", "Armor", 2),
|
||||
IRON_PLATELEGS_G("Iron platelegs (g)", ItemID.IRON_PLATELEGS_G, "Clue Scroll (Easy)", "Armor", 2),
|
||||
IRON_PLATESKIRT_G("Iron plateskirt (g)", ItemID.IRON_PLATESKIRT_G, "Clue Scroll (Easy)", "Armor", 2),
|
||||
IRON_KITESHIELD_G("Iron kiteshield (g)", ItemID.IRON_KITESHIELD_G, "Clue Scroll (Easy)", "Armor", 2),
|
||||
STEEL_FULL_HELM_T("Steel full helm (t)", ItemID.STEEL_FULL_HELM_T, "Clue Scroll (Easy)", "Armor", 3),
|
||||
STEEL_PLATEBODY_T("Steel platebody (t)", ItemID.STEEL_PLATEBODY_T, "Clue Scroll (Easy)", "Armor", 3),
|
||||
STEEL_PLATELEGS_T("Steel platelegs (t)", ItemID.STEEL_PLATELEGS_T, "Clue Scroll (Easy)", "Armor", 3),
|
||||
STEEL_PLATESKIRT_T("Steel plateskirt (t)", ItemID.STEEL_PLATESKIRT_T, "Clue Scroll (Easy)", "Armor", 3),
|
||||
STEEL_KITESHIELD_T("Steel kiteshield (t)", ItemID.STEEL_KITESHIELD_T, "Clue Scroll (Easy)", "Armor", 3),
|
||||
STEEL_FULL_HELM_G("Steel full helm (g)", ItemID.STEEL_FULL_HELM_G, "Clue Scroll (Easy)", "Armor", 4),
|
||||
STEEL_PLATEBODY_G("Steel platebody (g)", ItemID.STEEL_PLATEBODY_G, "Clue Scroll (Easy)", "Armor", 4),
|
||||
STEEL_PLATELEGS_G("Steel platelegs (g)", ItemID.STEEL_PLATELEGS_G, "Clue Scroll (Easy)", "Armor", 4),
|
||||
STEEL_PLATESKIRT_G("Steel plateskirt (g)", ItemID.STEEL_PLATESKIRT_G, "Clue Scroll (Easy)", "Armor", 4),
|
||||
STEEL_KITESHIELD_G("Steel kiteshield (g)", ItemID.STEEL_KITESHIELD_G, "Clue Scroll (Easy)", "Armor", 4),
|
||||
BLACK_FULL_HELM_T("Black full helm (t)", ItemID.BLACK_FULL_HELM_T, "Clue Scroll (Easy)", "Armor", 5),
|
||||
BLACK_PLATEBODY_T("Black platebody (t)", ItemID.BLACK_PLATEBODY_T, "Clue Scroll (Easy)", "Armor", 5),
|
||||
BLACK_PLATELEGS_T("Black platelegs (t)", ItemID.BLACK_PLATELEGS_T, "Clue Scroll (Easy)", "Armor", 5),
|
||||
BLACK_PLATESKIRT_T("Black plateskirt (t)", ItemID.BLACK_PLATESKIRT_T, "Clue Scroll (Easy)", "Armor", 5),
|
||||
BLACK_KITESHIELD_T("Black kiteshield (t)", ItemID.BLACK_KITESHIELD_T, "Clue Scroll (Easy)", "Armor", 5),
|
||||
BLACK_FULL_HELM_G("Black full helm (g)", ItemID.BLACK_FULL_HELM_G, "Clue Scroll (Easy)", "Armor", 6),
|
||||
BLACK_PLATEBODY_G("Black platebody (g)", ItemID.BLACK_PLATEBODY_G, "Clue Scroll (Easy)", "Armor", 6),
|
||||
BLACK_PLATELEGS_G("Black platelegs (g)", ItemID.BLACK_PLATELEGS_G, "Clue Scroll (Easy)", "Armor", 6),
|
||||
BLACK_PLATESKIRT_G("Black plateskirt (g)", ItemID.BLACK_PLATESKIRT_G, "Clue Scroll (Easy)", "Armor", 6),
|
||||
BLACK_KITESHIELD_G("Black kiteshield (g)", ItemID.BLACK_KITESHIELD_G, "Clue Scroll (Easy)", "Armor", 6),
|
||||
BLUE_WIZARD_HAT_T("Blue wizard hat (t)", ItemID.BLUE_WIZARD_HAT_T, "Clue Scroll (Easy)", "Wizard Robes", 7),
|
||||
BLUE_WIZARD_ROBE_T("Blue wizard robe (t)", ItemID.BLUE_WIZARD_ROBE_T, "Clue Scroll (Easy)", "Wizard Robes", 7),
|
||||
BLUE_SKIRT_T("Blue skirt (t)", ItemID.BLUE_SKIRT_T, "Clue Scroll (Easy)", "Wizard Robes", 7),
|
||||
BLUE_WIZARD_HAT_G("Blue wizard hat (g)", ItemID.BLUE_WIZARD_HAT_G, "Clue Scroll (Easy)", "Wizard Robes", 8),
|
||||
BLUE_WIZARD_ROBE_G("Blue wizard robe (g)", ItemID.BLUE_WIZARD_ROBE_G, "Clue Scroll (Easy)", "Wizard Robes", 8),
|
||||
BLUE_SKIRT_G("Blue skirt (g)", ItemID.BLUE_SKIRT_G, "Clue Scroll (Easy)", "Wizard Robes", 8),
|
||||
BLACK_WIZARD_HAT_T("Black wizard hat (t)", ItemID.BLACK_WIZARD_HAT_T, "Clue Scroll (Easy)", "Wizard Robes", 9),
|
||||
BLACK_WIZARD_ROBE_T("Black wizard robe (t)", ItemID.BLACK_WIZARD_ROBE_T, "Clue Scroll (Easy)", "Wizard Robes", 9),
|
||||
BLACK_SKIRT_T("Black skirt (t)", ItemID.BLACK_SKIRT_T, "Clue Scroll (Easy)", "Wizard Robes", 9),
|
||||
BLACK_WIZARD_HAT_G("Black wizard hat (g)", ItemID.BLACK_WIZARD_HAT_G, "Clue Scroll (Easy)", "Wizard Robes", 10),
|
||||
BLACK_WIZARD_ROBE_G("Black wizard robe (g)", ItemID.BLACK_WIZARD_ROBE_G, "Clue Scroll (Easy)", "Wizard Robes", 10),
|
||||
BLACK_SKIRT_G("Black skirt (g)", ItemID.BLACK_SKIRT_G, "Clue Scroll (Easy)", "Wizard Robes", 10),
|
||||
STUDDED_BODY_T("Studded body (t)", ItemID.STUDDED_BODY_T, "Clue Scroll (Easy)", "Leather Armor", 11),
|
||||
STUDDED_CHAPS_T("Studded chaps (t)", ItemID.STUDDED_CHAPS_T, "Clue Scroll (Easy)", "Leather Armor", 11),
|
||||
STUDDED_BODY_G("Studded body (g)", ItemID.STUDDED_BODY_G, "Clue Scroll (Easy)", "Leather Armor", 11),
|
||||
STUDDED_CHAPS_G("Studded chaps (g)", ItemID.STUDDED_CHAPS_G, "Clue Scroll (Easy)", "Leather Armor", 11),
|
||||
LEATHER_CHAPS_G("Leather chaps (g)", ItemID.LEATHER_CHAPS_G, "Clue Scroll (Easy)", "Leather Armor", 12),
|
||||
LEATHER_BODY_G("Leather chaps (g)", ItemID.LEATHER_BODY_G, "Clue Scroll (Easy)", "Leather Armor", 12),
|
||||
BLACK_HELM_H1("Black helm (h1)", ItemID.BLACK_HELM_H1, "Clue Scroll (Easy)", "Heralid Helm", 13),
|
||||
BLACK_HELM_H2("Black helm (h2)", ItemID.BLACK_HELM_H2, "Clue Scroll (Easy)", "Heralid Helm", 13),
|
||||
BLACK_HELM_H3("Black helm (h3)", ItemID.BLACK_HELM_H3, "Clue Scroll (Easy)", "Heralid Helm", 13),
|
||||
BLACK_HELM_H4("Black helm (h4)", ItemID.BLACK_HELM_H4, "Clue Scroll (Easy)", "Heralid Helm", 13),
|
||||
BLACK_HELM_H5("Black helm (h5)", ItemID.BLACK_HELM_H5, "Clue Scroll (Easy)", "Heralid Helm", 13),
|
||||
BLACK_PLATEBODY_H1("Black platebody (h1)", ItemID.BLACK_PLATEBODY_H1, "Clue Scroll (Easy)", "Heralid Platebody", 14),
|
||||
BLACK_PLATEBODY_H2("Black platebody (h2)", ItemID.BLACK_PLATEBODY_H2, "Clue Scroll (Easy)", "Heralid Platebody", 14),
|
||||
BLACK_PLATEBODY_H3("Black platebody (h3)", ItemID.BLACK_PLATEBODY_H3, "Clue Scroll (Easy)", "Heralid Platebody", 14),
|
||||
BLACK_PLATEBODY_H4("Black platebody (h4)", ItemID.BLACK_PLATEBODY_H4, "Clue Scroll (Easy)", "Heralid Platebody", 14),
|
||||
BLACK_PLATEBODY_H5("Black platebody (h5)", ItemID.BLACK_PLATEBODY_H5, "Clue Scroll (Easy)", "Heralid Platebody", 14),
|
||||
BLACK_SHIELD_H1("Black shield (h1)", ItemID.BLACK_SHIELD_H1, "Clue Scroll (Easy)", "Heralid Shield", 15),
|
||||
BLACK_SHIELD_H2("Black shield (h2)", ItemID.BLACK_SHIELD_H2, "Clue Scroll (Easy)", "Heralid Shield", 15),
|
||||
BLACK_SHIELD_H3("Black shield (h3)", ItemID.BLACK_SHIELD_H3, "Clue Scroll (Easy)", "Heralid Shield", 15),
|
||||
BLACK_SHIELD_H4("Black shield (h4)", ItemID.BLACK_SHIELD_H4, "Clue Scroll (Easy)", "Heralid Shield", 15),
|
||||
BLACK_SHIELD_H5("Black shield (h5)", ItemID.BLACK_SHIELD_H5, "Clue Scroll (Easy)", "Heralid Shield", 15),
|
||||
BLUE_ELEGANT_SHIRT("Blue elegant shirt", ItemID.BLUE_ELEGANT_SHIRT, "Clue Scroll (Easy)", "Elegant", 16),
|
||||
BLUE_ELEGANT_LEGS("Blue elegant legs", ItemID.BLUE_ELEGANT_LEGS, "Clue Scroll (Easy)", "Elegant", 16),
|
||||
BLUE_ELEGANT_BLOUSE("Blue elegant blouse", ItemID.BLUE_ELEGANT_BLOUSE, "Clue Scroll (Easy)", "Elegant", 16),
|
||||
BLUE_ELEGANT_SKIRT("Blue elegant skirt", ItemID.BLUE_ELEGANT_SKIRT, "Clue Scroll (Easy)", "Elegant", 16),
|
||||
GREEN_ELEGANT_SHIRT("Green elegant shirt", ItemID.GREEN_ELEGANT_SHIRT, "Clue Scroll (Easy)", "Elegant", 17),
|
||||
GREEN_ELEGANT_LEGS("Green elegant legs", ItemID.GREEN_ELEGANT_LEGS, "Clue Scroll (Easy)", "Elegant", 17),
|
||||
GREEN_ELEGANT_BLOUSE("Green elegant blouse", ItemID.GREEN_ELEGANT_BLOUSE, "Clue Scroll (Easy)", "Elegant", 17),
|
||||
GREEN_ELEGANT_SKIRT("Green elegant skirt", ItemID.GREEN_ELEGANT_SKIRT, "Clue Scroll (Easy)", "Elegant", 17),
|
||||
RED_ELEGANT_SHIRT("Red elegant shirt", ItemID.RED_ELEGANT_SHIRT, "Clue Scroll (Easy)", "Elegant", 18),
|
||||
RED_ELEGANT_LEGS("Red elegant legs", ItemID.RED_ELEGANT_LEGS, "Clue Scroll (Easy)", "Elegant", 18),
|
||||
RED_ELEGANT_BLOUSE("Red elegant blouse", ItemID.RED_ELEGANT_BLOUSE, "Clue Scroll (Easy)", "Elegant", 18),
|
||||
RED_ELEGANT_SKIRT("Red elegant skirt", ItemID.RED_ELEGANT_SKIRT, "Clue Scroll (Easy)", "Elegant", 18),
|
||||
BOBS_RED_SHIRT("Bob's red shirt", ItemID.BOBS_RED_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19),
|
||||
BOBS_BLUE_SHIRT("Bob's blue shirt", ItemID.BOBS_BLUE_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19),
|
||||
BOBS_GREEN_SHIRT("Bob's green shirt", ItemID.BOBS_GREEN_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19),
|
||||
BOBS_BLACK_SHIRT("Bob's black shirt", ItemID.BOBS_BLACK_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19),
|
||||
BOBS_PURPLE_SHIRT("Bob's purple shirt", ItemID.BOBS_PURPLE_SHIRT, "Clue Scroll (Easy)", "Bobs Shirt", 19),
|
||||
A_POWDERED_WIG("A powdered wig", ItemID.A_POWDERED_WIG, "Clue Scroll (Easy)", "Emote Enhancers", 20),
|
||||
FLARED_TROUSERS("Flared trousers", ItemID.FLARED_TROUSERS, "Clue Scroll (Easy)", "Emote Enhancers", 20),
|
||||
PANTALOONS("Pantaloons", ItemID.PANTALOONS, "Clue Scroll (Easy)", "Emote Enhancers", 20),
|
||||
SLEEPING_CAP("Sleeping cap", ItemID.SLEEPING_CAP, "Clue Scroll (Easy)", "Emote Enhancers", 20),
|
||||
GUTHIX_ROBE_TOP("Guthix robe top", ItemID.GUTHIX_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 21),
|
||||
GUTHIX_ROBE_LEGS("Guthix robe legs", ItemID.GUTHIX_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 21),
|
||||
SARADOMIN_ROBE_TOP("Saradomin robe top", ItemID.SARADOMIN_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 21),
|
||||
SARADOMIN_ROBE_LEGS("Saradomin robe legs", ItemID.SARADOMIN_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 21),
|
||||
ZAMORAK_ROBE_TOP("Zamorak robe top", ItemID.ZAMORAK_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 21),
|
||||
ZAMORAK_ROBE_LEGS("Zamorak robe legs", ItemID.ZAMORAK_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 21),
|
||||
ANCIENT_ROBE_TOP("Ancient robe top", ItemID.ANCIENT_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 22),
|
||||
ANCIENT_ROBE_LEGS("Ancient robe legs", ItemID.ANCIENT_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 22),
|
||||
BANDOS_ROBE_TOP("Bandos robe top", ItemID.BANDOS_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 22),
|
||||
BANDOS_ROBE_LEGS("Bandos robe legs", ItemID.BANDOS_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 22),
|
||||
ARMADYL_ROBE_TOP("Armadyl robe top", ItemID.ARMADYL_ROBE_TOP, "Clue Scroll (Easy)", "Vestment Robes", 22),
|
||||
ARMADYL_ROBE_LEGS("Armadyl robe legs", ItemID.ARMADYL_ROBE_LEGS, "Clue Scroll (Easy)", "Vestment Robes", 22),
|
||||
BLACK_BERET("Black beret", ItemID.BLACK_BERET, "Clue Scroll (Easy)", "Berets", 23),
|
||||
BLUE_BERET("Blue beret", ItemID.BLUE_BERET, "Clue Scroll (Easy)", "Berets", 23),
|
||||
WHITE_BERET("White beret", ItemID.WHITE_BERET, "Clue Scroll (Easy)", "Berets", 23),
|
||||
RED_BERET("Red beret", ItemID.RED_BERET, "Clue Scroll (Easy)", "Berets", 23),
|
||||
HIGHWAYMAN_MASK("Highwayman mask", ItemID.HIGHWAYMAN_MASK, "Clue Scroll (Easy)", "Masks", 24),
|
||||
IMP_MASK("Imp mask", ItemID.IMP_MASK, "Clue Scroll (Easy)", "Masks", 24),
|
||||
GOBLIN_MASK("Goblin mask", ItemID.GOBLIN_MASK, "Clue Scroll (Easy)", "Masks", 24),
|
||||
BEANIE("Beanie", ItemID.BEANIE, "Clue Scroll (Easy)", "Masks", 24),
|
||||
TEAM_CAPE_I("Team cape i", ItemID.TEAM_CAPE_I, "Clue Scroll (Easy)", "Cape", 25),
|
||||
TEAM_CAPE_X("Team cape x", ItemID.TEAM_CAPE_X, "Clue Scroll (Easy)", "Cape", 25),
|
||||
TEAM_CAPE_ZERO("Team cape zero", ItemID.TEAM_CAPE_ZERO, "Clue Scroll (Easy)", "Cape", 25),
|
||||
CAPE_OF_SKULLS("Cape of Skulls", ItemID.CAPE_OF_SKULLS, "Clue Scroll (Easy)", "CApe", 25),
|
||||
AMULET_OF_MAGIC_T("Amulet of magic (t)", ItemID.AMULET_OF_MAGIC_T, "Clue Scroll (Easy)", "Other", 26),
|
||||
AMULET_OF_POWER_T("Power Amulet (t)", ItemID.AMULET_OF_POWER_T, "Clue Scroll (Easy)", "Other", 26),
|
||||
BLACK_CANE("Black cane", ItemID.BLACK_CANE, "Clue Scroll (Easy)", "Other", 26),
|
||||
BLACK_PICKAXE("Black pickaxe", ItemID.BLACK_PICKAXE, "Clue Scroll (Easy)", "Other", 26),
|
||||
LARGE_SPADE("Large spade", ItemID.LARGE_SPADE, "Clue Scroll (Easy)", "Other", 26),
|
||||
WOODEN_SHIELD_G("Wooden shield (g)", ItemID.WOODEN_SHIELD_G, "Clue Scroll (Easy)", "Golden", 27),
|
||||
GOLDEN_CHEFS_HAT("Golden chef's hat", ItemID.GOLDEN_CHEFS_HAT, "Clue Scroll (Easy)", "Golden", 27),
|
||||
GOLDEN_APRON("Golden apron", ItemID.GOLDEN_APRON, "Clue Scroll (Easy)", "Golden", 27),
|
||||
MONKS_ROBE_TOP_G("Monk robe top (g)", ItemID.MONKS_ROBE_TOP_G, "Clue Scroll (Easy)", "Golden", 27),
|
||||
MONKS_ROBE_G("Monk robe (g)", ItemID.MONKS_ROBE_G, "Clue Scroll (Easy)", "Golden", 27),
|
||||
RAIN_BOW("Rain bow", ItemID.RAIN_BOW, "Clue Scroll (Easy)", "Other", 28),
|
||||
HAM_JOINT("Ham joint", ItemID.HAM_JOINT, "Clue Scroll (Easy)", "Other", 28),
|
||||
STAFF_OF_BOB_THE_CAT("Staff of Bob the Cat", ItemID.STAFF_OF_BOB_THE_CAT, "Clue Scroll (Easy)", "Other", 28),
|
||||
|
||||
// Medium Clue Scrolls
|
||||
MITHRIL_FULL_HELM_T("Mithril full helm (t)", ItemID.MITHRIL_FULL_HELM_T, "Clue Scroll (Medium)", "Armor", -1),
|
||||
MITHRIL_PLATEBODY_T("Mithril platebody (t)", ItemID.MITHRIL_PLATEBODY_T, "Clue Scroll (Medium)", "Armor", -1),
|
||||
MITHRIL_PLATELEGS_T("Mithril platelegs (t)", ItemID.MITHRIL_PLATELEGS_T, "Clue Scroll (Medium)", "Armor", -1),
|
||||
MITHRIL_PLATESKIRT_T("Mithril plateskirt (t)", ItemID.MITHRIL_PLATESKIRT_T, "Clue Scroll (Medium)", "Armor", -1),
|
||||
MITHRIL_KITESHIELD_T("Mithril kiteshield (t)", ItemID.MITHRIL_KITESHIELD_T, "Clue Scroll (Medium)", "Armor", -1),
|
||||
MITHRIL_FULL_HELM_G("Mithril full helm (g)", ItemID.MITHRIL_FULL_HELM_G, "Clue Scroll (Medium)", "Armor", 0),
|
||||
MITHRIL_PLATEBODY_G("Mithril platebody (g)", ItemID.MITHRIL_PLATEBODY_G, "Clue Scroll (Medium)", "Armor", 0),
|
||||
MITHRIL_PLATELEGS_G("Mithril platelegs (g)", ItemID.MITHRIL_PLATELEGS_G, "Clue Scroll (Medium)", "Armor", 0),
|
||||
MITHRIL_PLATESKIRT_G("Mithril plateskirt (g)", ItemID.MITHRIL_PLATESKIRT_G, "Clue Scroll (Medium)", "Armor", 0),
|
||||
MITHRIL_KITESHIELD_G("Mithril kiteshield (g)", ItemID.MITHRIL_KITESHIELD_G, "Clue Scroll (Medium)", "Armor", 0),
|
||||
ADAMANT_FULL_HELM_T("Adamant full helm (t)", ItemID.ADAMANT_FULL_HELM_T, "Clue Scroll (Medium)", "Armor", 1),
|
||||
ADAMANT_PLATEBODY_T("Adamant platebody (t)", ItemID.ADAMANT_PLATEBODY_T, "Clue Scroll (Medium)", "Armor", 1),
|
||||
ADAMANT_PLATELEGS_T("Adamant platelegs (t)", ItemID.ADAMANT_PLATELEGS_T, "Clue Scroll (Medium)", "Armor", 1),
|
||||
ADAMANT_PLATESKIRT_T("Adamant plateskirt (t)", ItemID.ADAMANT_PLATESKIRT_T, "Clue Scroll (Medium)", "Armor", 1),
|
||||
ADAMANT_KITESHIELD_T("Adamant kiteshield (t)", ItemID.ADAMANT_KITESHIELD_T, "Clue Scroll (Medium)", "Armor", 1),
|
||||
ADAMANT_FULL_HELM_G("Adamant full helm (g)", ItemID.ADAMANT_FULL_HELM_G, "Clue Scroll (Medium)", "Armor", 2),
|
||||
ADAMANT_PLATEBODY_G("Adamant platebody (g)", ItemID.ADAMANT_PLATEBODY_G, "Clue Scroll (Medium)", "Armor", 2),
|
||||
ADAMANT_PLATELEGS_G("Adamant platelegs (g)", ItemID.ADAMANT_PLATELEGS_G, "Clue Scroll (Medium)", "Armor", 2),
|
||||
ADAMANT_PLATESKIRT_G("Adamant plateskirt (g)", ItemID.ADAMANT_PLATESKIRT_G, "Clue Scroll (Medium)", "Armor", 2),
|
||||
ADAMANT_KITESHIELD_G("Adamant kiteshield (g)", ItemID.ADAMANT_KITESHIELD_G, "Clue Scroll (Medium)", "Armor", 2),
|
||||
RANGER_BOOTS("Ranger boots", ItemID.RANGER_BOOTS, "Clue Scroll (Medium)", "Boots", 3),
|
||||
HOLY_SANDALS("Holy sandals", ItemID.HOLY_SANDALS, "Clue Scroll (Medium)", "Boots", 3),
|
||||
WIZARD_BOOTS("Wizard boots", ItemID.WIZARD_BOOTS, "Clue Scroll (Medium)", "Boots", 3),
|
||||
RED_HEADBAND("Red headband", ItemID.RED_HEADBAND, "Clue Scroll (Medium)", "Headbands", 4),
|
||||
BLACK_HEADBAND("Black headband", ItemID.BLACK_HEADBAND, "Clue Scroll (Medium)", "Headbands", 4),
|
||||
BROWN_HEADBAND("Brown headband", ItemID.BROWN_HEADBAND, "Clue Scroll (Medium)", "Headbands", 4),
|
||||
PINK_HEADBAND("Pink headband", ItemID.PINK_HEADBAND, "Clue Scroll (Medium)", "Headbands", 4),
|
||||
GREEN_HEADBAND("Green headband", ItemID.GREEN_HEADBAND, "Clue Scroll (Medium)", "Headbands", 5),
|
||||
BLUE_HEADBAND("Blue headband", ItemID.BLUE_HEADBAND, "Clue Scroll (Medium)", "Headbands", 5),
|
||||
GOLD_HEADBAND("Gold headband", ItemID.GOLD_HEADBAND, "Clue Scroll (Medium)", "Headbands", 5),
|
||||
WHITE_HEADBAND("White headband", ItemID.WHITE_HEADBAND, "Clue Scroll (Medium)", "Headbands", 5),
|
||||
RED_BOATER("Red boater", ItemID.RED_BOATER, "Clue Scroll (Medium)", "Boater", 6),
|
||||
ORANGE_BOATER("Orange boater", ItemID.ORANGE_BOATER, "Clue Scroll (Medium)", "Boater", 6),
|
||||
GREEN_BOATER("Green boater", ItemID.GREEN_BOATER, "Clue Scroll (Medium)", "Boater", 6),
|
||||
BLUE_BOATER("Blue boater", ItemID.BLUE_BOATER, "Clue Scroll (Medium)", "Boater", 6),
|
||||
BLACK_BOATER("Black boater", ItemID.BLACK_BOATER, "Clue Scroll (Medium)", "Boater", 7),
|
||||
PINK_BOATER("Pink boater", ItemID.PINK_BOATER, "Clue Scroll (Medium)", "Boater", 7),
|
||||
PURPLE_BOATER("Purple boater", ItemID.PURPLE_BOATER, "Clue Scroll (Medium)", "Boater", 7),
|
||||
WHITE_BOATER("White boater", ItemID.WHITE_BOATER, "Clue Scroll (Medium)", "Boater", 7),
|
||||
ADAMANT_HELM_H1("Adamant helm (h1)", ItemID.ADAMANT_HELM_H1, "Clue Scroll (Medium)", "Heraldic", 8),
|
||||
ADAMANT_HELM_H2("Adamant helm (h2)", ItemID.ADAMANT_HELM_H2, "Clue Scroll (Medium)", "Heraldic", 8),
|
||||
ADAMANT_HELM_H3("Adamant helm (h3)", ItemID.ADAMANT_HELM_H3, "Clue Scroll (Medium)", "Heraldic", 8),
|
||||
ADAMANT_HELM_H4("Adamant helm (h4)", ItemID.ADAMANT_HELM_H4, "Clue Scroll (Medium)", "Heraldic", 8),
|
||||
ADAMANT_HELM_H5("Adamant helm (h5)", ItemID.ADAMANT_HELM_H5, "Clue Scroll (Medium)", "Heraldic", 8),
|
||||
ADAMANT_SHIELD_H1("Adamant shield (h1)", ItemID.ADAMANT_SHIELD_H1, "Clue Scroll (Medium)", "Heraldic", 9),
|
||||
ADAMANT_SHIELD_H2("Adamant shield (h2)", ItemID.ADAMANT_SHIELD_H2, "Clue Scroll (Medium)", "Heraldic", 9),
|
||||
ADAMANT_SHIELD_H3("Adamant shield (h3)", ItemID.ADAMANT_SHIELD_H3, "Clue Scroll (Medium)", "Heraldic", 9),
|
||||
ADAMANT_SHIELD_H4("Adamant shield (h4)", ItemID.ADAMANT_SHIELD_H4, "Clue Scroll (Medium)", "Heraldic", 9),
|
||||
ADAMANT_SHIELD_H5("Adamant shield (h5)", ItemID.ADAMANT_SHIELD_H5, "Clue Scroll (Medium)", "Heraldic", 9),
|
||||
ADAMANT_PLATEBODY_H1("Adamant platebody (h1)", ItemID.ADAMANT_PLATEBODY_H1, "Clue Scroll (Medium)", "Armor", 10),
|
||||
ADAMANT_PLATEBODY_H2("Adamant platebody (h2)", ItemID.ADAMANT_PLATEBODY_H2, "Clue Scroll (Medium)", "Armor", 10),
|
||||
ADAMANT_PLATEBODY_H3("Adamant platebody (h3)", ItemID.ADAMANT_PLATEBODY_H3, "Clue Scroll (Medium)", "Armor", 10),
|
||||
ADAMANT_PLATEBODY_H4("Adamant platebody (h4)", ItemID.ADAMANT_PLATEBODY_H4, "Clue Scroll (Medium)", "Armor", 10),
|
||||
ADAMANT_PLATEBODY_H5("Adamant platebody (h5)", ItemID.ADAMANT_PLATEBODY_H5, "Clue Scroll (Medium)", "Armor", 10),
|
||||
GREEN_DHIDE_BODY_T("Green dragonhide body (t)", ItemID.GREEN_DHIDE_BODY_T, "Clue Scroll (Medium)", "Dhide", 11),
|
||||
GREEN_DHIDE_CHAPS_T("Green dragonhide chaps (t)", ItemID.GREEN_DHIDE_CHAPS_T, "Clue Scroll (Medium)", "Dhide", 11),
|
||||
GREEN_DHIDE_BODY_G("Green dragonhide body (g)", ItemID.GREEN_DHIDE_BODY_G, "Clue Scroll (Medium)", "Dhide", 11),
|
||||
GREEN_DHIDE_CHAPS_G("Green dragonhide chaps (g)", ItemID.GREEN_DHIDE_CHAPS_G, "Clue Scroll (Medium)", "Dhide", 11),
|
||||
BLACK_ELEGANT_SHIRT("Black elegant shirt", ItemID.BLACK_ELEGANT_SHIRT, "Clue Scroll (Medium)", "Elegeant", 12),
|
||||
BLACK_ELEGANT_LEGS("Black elegant legs", ItemID.BLACK_ELEGANT_LEGS, "Clue Scroll (Medium)", "Elegeant", 12),
|
||||
WHITE_ELEGANT_BLOUSE("White elegant blouse", ItemID.WHITE_ELEGANT_BLOUSE, "Clue Scroll (Medium)", "Elegeant", 12),
|
||||
WHITE_ELEGANT_SKIRT("White elegant skirt", ItemID.WHITE_ELEGANT_SKIRT, "Clue Scroll (Medium)", "Elegeant", 12),
|
||||
PURPLE_ELEGANT_SHIRT("Purple elegant shirt", ItemID.PURPLE_ELEGANT_SHIRT, "Clue Scroll (Medium)", "Elegeant", 13),
|
||||
PURPLE_ELEGANT_LEGS("Purple elegant legs", ItemID.PURPLE_ELEGANT_LEGS, "Clue Scroll (Medium)", "Elegeant", 13),
|
||||
PURPLE_ELEGANT_BLOUSE("Purple elegant blouse", ItemID.PURPLE_ELEGANT_BLOUSE, "Clue Scroll (Medium)", "Elegeant", 13),
|
||||
PURPLE_ELEGANT_SKIRT("Purple elegant skirt", ItemID.PURPLE_ELEGANT_SKIRT, "Clue Scroll (Medium)", "Elegeant", 13),
|
||||
PINK_ELEGANT_SHIRT("Pink elegant shirt", ItemID.PINK_ELEGANT_SHIRT, "Clue Scroll (Medium)", "Elegeant", 14),
|
||||
PINK_ELEGANT_LEGS("Pink elegant legs", ItemID.PINK_ELEGANT_LEGS, "Clue Scroll (Medium)", "Elegeant", 14),
|
||||
PINK_ELEGANT_BLOUSE("Pink elegant blouse", ItemID.PINK_ELEGANT_BLOUSE, "Clue Scroll (Medium)", "Elegeant", 14),
|
||||
PINK_ELEGANT_SKIRT("Pink elegant skirt", ItemID.PINK_ELEGANT_SKIRT, "Clue Scroll (Medium)", "Elegeant", 14),
|
||||
GOLD_ELEGANT_SHIRT("Gold elegant shirt", ItemID.GOLD_ELEGANT_SHIRT, "Clue Scroll (Medium)", "Elegeant", 15),
|
||||
GOLD_ELEGANT_LEGS("Gold elegant legs", ItemID.GOLD_ELEGANT_LEGS, "Clue Scroll (Medium)", "Elegeant", 15),
|
||||
GOLD_ELEGANT_BLOUSE("Gold elegant blouse", ItemID.GOLD_ELEGANT_BLOUSE, "Clue Scroll (Medium)", "Elegeant", 15),
|
||||
GOLD_ELEGANT_SKIRT("Gold elegant skirt", ItemID.GOLD_ELEGANT_SKIRT, "Clue Scroll (Medium)", "Elegeant", 15),
|
||||
GUTHIX_MITRE("Guthix mitre", ItemID.GUTHIX_MITRE, "Clue Scroll (Medium)", "Vestment", 16),
|
||||
GUTHIX_CLOAK("Guthix cloak", ItemID.GUTHIX_CLOAK, "Clue Scroll (Medium)", "Vestment", 16),
|
||||
SARADOMIN_MITRE("Saradomin mitre", ItemID.SARADOMIN_MITRE, "Clue Scroll (Medium)", "Vestment", 16),
|
||||
SARADOMIN_CLOAK("Saradomin cloak", ItemID.SARADOMIN_CLOAK, "Clue Scroll (Medium)", "Vestment", 16),
|
||||
ZAMORAK_MITRE("Zamorak mitre", ItemID.ZAMORAK_MITRE, "Clue Scroll (Medium)", "Vestment", 16),
|
||||
ZAMORAK_CLOAK("Zamorak cloak", ItemID.ZAMORAK_CLOAK, "Clue Scroll (Medium)", "Vestment", 16),
|
||||
ANCIENT_MITRE("Anicent mitre", ItemID.ANCIENT_MITRE, "Clue Scroll (Medium)", "Vestment", 17),
|
||||
ANCIENT_CLOAK("Anicent cloak", ItemID.ANCIENT_CLOAK, "Clue Scroll (Medium)", "Vestment", 17),
|
||||
BANDOS_MITRE("Bandos mitre", ItemID.BANDOS_MITRE, "Clue Scroll (Medium)", "Vestment", 17),
|
||||
BANDOS_CLOAK("Bandos cloak", ItemID.BANDOS_CLOAK, "Clue Scroll (Medium)", "Vestment", 17),
|
||||
ARMADYL_MITRE("Armadyl mitre", ItemID.ARMADYL_MITRE, "Clue Scroll (Medium)", "Vestment", 17),
|
||||
ARMADYL_CLOAK("Armadyl cloak", ItemID.ARMADYL_CLOAK, "Clue Scroll (Medium)", "Vestment", 17),
|
||||
ARMADYL_STOLE("Armadyl stole", ItemID.ARMADYL_STOLE, "Clue Scroll (Medium)", "Vestment", 18),
|
||||
ARMADYL_CROZIER("Armadyl crozier", ItemID.ARMADYL_CROZIER, "Clue Scroll (Medium)", "Vestment", 18),
|
||||
ANCIENT_STOLE("Anicent stole", ItemID.ANCIENT_STOLE, "Clue Scroll (Medium)", "Vestment", 18),
|
||||
ANCIENT_CROZIER("Anicent crozier", ItemID.ANCIENT_CROZIER, "Clue Scroll (Medium)", "Vestment", 18),
|
||||
BANDOS_STOLE("Bandos stole", ItemID.BANDOS_STOLE, "Clue Scroll (Medium)", "Vestment", 18),
|
||||
BANDOS_CROZIER("Bandos crozier", ItemID.BANDOS_CROZIER, "Clue Scroll (Medium)", "Vestment", 18),
|
||||
CAT_MASK("Cat mask", ItemID.CAT_MASK, "Clue Scroll (Medium)", "Masks", 19),
|
||||
PENGUIN_MASK("Penguin mask", ItemID.PENGUIN_MASK, "Clue Scroll (Medium)", "Masks", 19),
|
||||
BLACK_UNICORN_MASK("Black unicorn mask", ItemID.BLACK_UNICORN_MASK, "Clue Scroll (Medium)", "Masks", 19),
|
||||
WHITE_UNICORN_MASK("White unicorn mask", ItemID.WHITE_UNICORN_MASK, "Clue Scroll (Medium)", "Masks", 19),
|
||||
LEPRECHAUN_HAT("Leprechaun hat", ItemID.LEPRECHAUN_HAT, "Clue Scroll (Medium)", "Masks", 19),
|
||||
BLACK_LEPRECHAUN_HAT("Black leprechaun hat", ItemID.BLACK_LEPRECHAUN_HAT, "Clue Scroll (Medium)", "Masks", 19),
|
||||
CRIER_HAT("Crier hat", ItemID.CRIER_HAT, "Clue Scroll (Medium)", "Crier", 20),
|
||||
CRIER_BELL("Crier bell", ItemID.CRIER_BELL, "Clue Scroll (Medium)", "Crier", 20),
|
||||
CRIER_COAT("Crier coat", ItemID.CRIER_COAT, "Clue Scroll (Medium)", "Crier", 20),
|
||||
ARCEUUS_BANNER("Arceeus banner", ItemID.ARCEUUS_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21),
|
||||
HOSIDIUS_BANNER("Hosidius banner", ItemID.HOSIDIUS_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21),
|
||||
LOVAKENGJ_BANNER("Lovakengj banner", ItemID.LOVAKENGJ_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21),
|
||||
PISCARILIUS_BANNER("Picarilius banner", ItemID.PISCARILIUS_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21),
|
||||
SHAYZIEN_BANNER("Shayzien banner", ItemID.SHAYZIEN_BANNER, "Clue Scroll (Medium)", "Zeah Banners", 21),
|
||||
STRENGTH_AMULET_T("Strength amulet (t)", ItemID.STRENGTH_AMULET_T, "Clue Scroll (Medium)", "Other", 22),
|
||||
ADAMANT_CANE("Adamant cane", ItemID.ADAMANT_CANE, "Clue Scroll (Medium)", "Other", 22),
|
||||
GNOMISH_FIRELIGHTER("Gnomish firelighter", ItemID.GNOMISH_FIRELIGHTER, "Clue Scroll (Medium)", "Other", 22),
|
||||
CABBAGE_ROUND_SHIELD("Cabbage round shield", ItemID.CABBAGE_ROUND_SHIELD, "Clue Scroll (Medium)", "Other", 22),
|
||||
CLUELESS_SCROLL("Clueless scroll", ItemID.CLUELESS_SCROLL, "Clue Scroll (Medium)", "Other", 22),
|
||||
SPIKED_MANACLES("Spiked manacles", ItemID.SPIKED_MANACLES, "Clue Scroll (Medium)", "Other", 23),
|
||||
WOLF_MASK("Wolf mask", ItemID.WOLF_MASK, "Clue Scroll (Medium)", "Other", 23),
|
||||
WOLF_CLOAK("Wolf cloak", ItemID.WOLF_CLOAK, "Clue Scroll (Medium)", "Other", 23),
|
||||
CLIMBING_BOOTS_G("Climbing boots (g)", ItemID.CLIMBING_BOOTS_G, "Clue Scroll (Medium)", "Other", 23),
|
||||
|
||||
// Hard Clue Scrolls
|
||||
RUNE_FULL_HELM_T("Rune full helm (t)", ItemID.RUNE_FULL_HELM_T, "Clue Scroll (Hard)", "Armor", -1),
|
||||
RUNE_PLATEBODY_T("Rune platebody (t)", ItemID.RUNE_PLATEBODY_T, "Clue Scroll (Hard)", "Armor", -1),
|
||||
RUNE_PLATELEGS_T("Rune platelegs (t)", ItemID.RUNE_PLATELEGS_T, "Clue Scroll (Hard)", "Armor", -1),
|
||||
RUNE_PLATESKIRT_T("Rune plateskirt (t)", ItemID.RUNE_PLATESKIRT_T, "Clue Scroll (Hard)", "Armor", -1),
|
||||
RUNE_KITESHIELD_T("Rune kiteshield (t)", ItemID.RUNE_KITESHIELD_T, "Clue Scroll (Hard)", "Armor", -1),
|
||||
RUNE_FULL_HELM_G("Rune full helm (g)", ItemID.RUNE_FULL_HELM_G, "Clue Scroll (Hard)", "Armor", 0),
|
||||
RUNE_PLATEBODY_G("Rune platebody (g)", ItemID.RUNE_PLATEBODY_G, "Clue Scroll (Hard)", "Armor", 0),
|
||||
RUNE_PLATELEGS_G("Rune platelegs (g)", ItemID.RUNE_PLATELEGS_G, "Clue Scroll (Hard)", "Armor", 0),
|
||||
RUNE_PLATESKIRT_G("Rune plateskirt (g)", ItemID.RUNE_PLATESKIRT_G, "Clue Scroll (Hard)", "Armor", 0),
|
||||
RUNE_KITESHIELD_G("Rune kiteshield (g)", ItemID.RUNE_KITESHIELD_G, "Clue Scroll (Hard)", "Armor", 0),
|
||||
GUTHIX_FULL_HELM("Guthix full helm", ItemID.GUTHIX_FULL_HELM, "Clue Scroll (Hard)", "Armor", 1),
|
||||
GUTHIX_PLATEBODY("Guthix platebody", ItemID.GUTHIX_PLATEBODY, "Clue Scroll (Hard)", "Armor", 1),
|
||||
GUTHIX_PLATELEGS("Guthix platelegs", ItemID.GUTHIX_PLATELEGS, "Clue Scroll (Hard)", "Armor", 1),
|
||||
GUTHIX_PLATESKIRT("Guthix plateskirt", ItemID.GUTHIX_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 1),
|
||||
GUTHIX_KITESHIELD("Guthix kiteshield", ItemID.GUTHIX_KITESHIELD, "Clue Scroll (Hard)", "Armor", 1),
|
||||
SARADOMIN_FULL_HELM("Saradomin full helm", ItemID.SARADOMIN_FULL_HELM, "Clue Scroll (Hard)", "Armor", 2),
|
||||
SARADOMIN_PLATEBODY("Saradomin platebody", ItemID.SARADOMIN_PLATEBODY, "Clue Scroll (Hard)", "Armor", 2),
|
||||
SARADOMIN_PLATELEGS("Saradomin platelegs", ItemID.SARADOMIN_PLATELEGS, "Clue Scroll (Hard)", "Armor", 2),
|
||||
SARADOMIN_PLATESKIRT("Saradomin plateskirt", ItemID.SARADOMIN_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 2),
|
||||
SARADOMIN_KITESHIELD("Saradomin kiteshield", ItemID.SARADOMIN_KITESHIELD, "Clue Scroll (Hard)", "Armor", 2),
|
||||
ZAMORAK_FULL_HELM("Zamorak full helm", ItemID.ZAMORAK_FULL_HELM, "Clue Scroll (Hard)", "Armor", 3),
|
||||
ZAMORAK_PLATEBODY("Zamorak platebody", ItemID.ZAMORAK_PLATEBODY, "Clue Scroll (Hard)", "Armor", 3),
|
||||
ZAMORAK_PLATELEGS("Zamorak platelegs", ItemID.ZAMORAK_PLATELEGS, "Clue Scroll (Hard)", "Armor", 3),
|
||||
ZAMORAK_PLATESKIRT("Zamorak plateskirt", ItemID.ZAMORAK_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 3),
|
||||
ZAMORAK_KITESHIELD("Zamorak kiteshield", ItemID.ZAMORAK_KITESHIELD, "Clue Scroll (Hard)", "Armor", 3),
|
||||
ANCIENT_FULL_HELM("Ancient full helm", ItemID.ANCIENT_FULL_HELM, "Clue Scroll (Hard)", "Armor", 4),
|
||||
ANCIENT_PLATEBODY("Ancient platebody", ItemID.ANCIENT_PLATEBODY, "Clue Scroll (Hard)", "Armor", 4),
|
||||
ANCIENT_PLATELEGS("Ancient platelegs", ItemID.ANCIENT_PLATELEGS, "Clue Scroll (Hard)", "Armor", 4),
|
||||
ANCIENT_PLATESKIRT("Ancient plateskirt", ItemID.ANCIENT_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 4),
|
||||
ANCIENT_KITESHIELD("Ancient kiteshield", ItemID.ANCIENT_KITESHIELD, "Clue Scroll (Hard)", "Armor", 4),
|
||||
BANDOS_FULL_HELM("Bandos full helm", ItemID.BANDOS_FULL_HELM, "Clue Scroll (Hard)", "Armor", 5),
|
||||
BANDOS_PLATEBODY("Bandos platebody", ItemID.BANDOS_PLATEBODY, "Clue Scroll (Hard)", "Armor", 5),
|
||||
BANDOS_PLATELEGS("Bandos platelegs", ItemID.BANDOS_PLATELEGS, "Clue Scroll (Hard)", "Armor", 5),
|
||||
BANDOS_PLATESKIRT("Bandos plateskirt", ItemID.BANDOS_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 5),
|
||||
BANDOS_KITESHIELD("Bandos kiteshield", ItemID.BANDOS_KITESHIELD, "Clue Scroll (Hard)", "Armor", 5),
|
||||
ARMADYL_FULL_HELM("Armadyl full helm", ItemID.ARMADYL_FULL_HELM, "Clue Scroll (Hard)", "Armor", 6),
|
||||
ARMADYL_PLATEBODY("Armadyl platebody", ItemID.ARMADYL_PLATEBODY, "Clue Scroll (Hard)", "Armor", 6),
|
||||
ARMADYL_PLATELEGS("Armadyl platelegs", ItemID.ARMADYL_PLATELEGS, "Clue Scroll (Hard)", "Armor", 6),
|
||||
ARMADYL_PLATESKIRT("Armadyl plateskirt", ItemID.ARMADYL_PLATESKIRT, "Clue Scroll (Hard)", "Armor", 6),
|
||||
ARMADYL_KITESHIELD("Armadyl kiteshield", ItemID.ARMADYL_KITESHIELD, "Clue Scroll (Hard)", "Armor", 6),
|
||||
GILDED_FULL_HELM("Gilded full helm", ItemID.GILDED_FULL_HELM, "Clue Scroll (Hard)", "Gilded", 7),
|
||||
GILDED_PLATEBODY("Gilded platebody", ItemID.GILDED_PLATEBODY, "Clue Scroll (Hard)", "Gilded", 7),
|
||||
GILDED_PLATELEGS("Gilded platelegs", ItemID.GILDED_PLATELEGS, "Clue Scroll (Hard)", "Gilded", 7),
|
||||
GILDED_PLATESKIRT("Gilded plateskirt", ItemID.GILDED_PLATESKIRT, "Clue Scroll (Hard)", "Gilded", 7),
|
||||
GILDED_KITESHIELD("Gilded kiteshield", ItemID.GILDED_KITESHIELD, "Clue Scroll (Hard)", "Gilded", 7),
|
||||
GILDED_MED_HELM("Gilded med helm", ItemID.GILDED_MED_HELM, "Clue Scroll (Hard)", "Gilded", 8),
|
||||
GILDED_CHAINBODY("Gilded chainbody", ItemID.GILDED_CHAINBODY, "Clue Scroll (Hard)", "Gilded", 8),
|
||||
GILDED_SQ_SHIELD("Gilded sq shield", ItemID.GILDED_SQ_SHIELD, "Clue Scroll (Hard)", "Gilded", 8),
|
||||
GILDED_2H_SWORD("Gilded 2H sword", ItemID.GILDED_2H_SWORD, "Clue Scroll (Hard)", "Gilded", 8),
|
||||
GILDED_SPEAR("Gilded spear", ItemID.GILDED_SPEAR, "Clue Scroll (Hard)", "Gilded", 8),
|
||||
GILDED_HASTA("Gilded hasta", ItemID.GILDED_HASTA, "Clue Scroll (Hard)", "Gilded", 8),
|
||||
RUNE_HELM_H1("Rune helm (h1)", ItemID.RUNE_HELM_H1, "Clue Scroll (Hard)", "Heraldic", 9),
|
||||
RUNE_HELM_H2("Rune helm (h2)", ItemID.RUNE_HELM_H2, "Clue Scroll (Hard)", "Heraldic", 9),
|
||||
RUNE_HELM_H3("Rune helm (h3)", ItemID.RUNE_HELM_H3, "Clue Scroll (Hard)", "Heraldic", 9),
|
||||
RUNE_HELM_H4("Rune helm (h4)", ItemID.RUNE_HELM_H4, "Clue Scroll (Hard)", "Heraldic", 9),
|
||||
RUNE_HELM_H5("Rune helm (h5)", ItemID.RUNE_HELM_H5, "Clue Scroll (Hard)", "Heraldic", 9),
|
||||
RUNE_SHIELD_H1("Rune shield (h1)", ItemID.RUNE_SHIELD_H1, "Clue Scroll (Hard)", "Heraldic", 10),
|
||||
RUNE_SHIELD_H2("Rune shield (h2)", ItemID.RUNE_SHIELD_H2, "Clue Scroll (Hard)", "Heraldic", 10),
|
||||
RUNE_SHIELD_H3("Rune shield (h3)", ItemID.RUNE_SHIELD_H3, "Clue Scroll (Hard)", "Heraldic", 10),
|
||||
RUNE_SHIELD_H4("Rune shield (h4)", ItemID.RUNE_SHIELD_H4, "Clue Scroll (Hard)", "Heraldic", 10),
|
||||
RUNE_SHIELD_H5("Rune shield (h5)", ItemID.RUNE_SHIELD_H5, "Clue Scroll (Hard)", "Heraldic", 10),
|
||||
RUNE_PLATEBODY_H1("Rune platebody (h1)", ItemID.RUNE_PLATEBODY_H1, "Clue Scroll (Hard)", "Heraldic", 11),
|
||||
RUNE_PLATEBODY_H2("Rune platebody (h2)", ItemID.RUNE_PLATEBODY_H2, "Clue Scroll (Hard)", "Heraldic", 11),
|
||||
RUNE_PLATEBODY_H3("Rune platebody (h3)", ItemID.RUNE_PLATEBODY_H3, "Clue Scroll (Hard)", "Heraldic", 11),
|
||||
RUNE_PLATEBODY_H4("Rune platebody (h4)", ItemID.RUNE_PLATEBODY_H4, "Clue Scroll (Hard)", "Heraldic", 11),
|
||||
RUNE_PLATEBODY_H5 ("Rune platebody (h5)", ItemID.RUNE_PLATEBODY_H5, "Clue Scroll (Hard)", "Heraldic", 11),
|
||||
|
||||
BLUE_DHIDE_BODY_T("Blue dhide body (t)", ItemID.BLUE_DHIDE_BODY_T, "Clue Scroll (Hard)", "Dhide", 12),
|
||||
BLUE_DHIDE_CHAPS_T("Blue dhide chaps (t)", ItemID.BLUE_DHIDE_CHAPS_T, "Clue Scroll (Hard)", "Dhide", 12),
|
||||
BLUE_DHIDE_BODY_G("Blue dhide body (g)", ItemID.BLUE_DHIDE_BODY_G, "Clue Scroll (Hard)", "Dhide", 12),
|
||||
BLUE_DHIDE_CHAPS_G("Blue dhide chaps (g)", ItemID.BLUE_DHIDE_CHAPS_G, "Clue Scroll (Hard)", "Dhide", 12),
|
||||
RED_DHIDE_BODY_T("Red dhide body (t)", ItemID.RED_DHIDE_BODY_T, "Clue Scroll (Hard)", "Dhide", 13),
|
||||
RED_DHIDE_CHAPS_T("Red dhide chaps (t)", ItemID.RED_DHIDE_CHAPS_T, "Clue Scroll (Hard)", "Dhide", 13),
|
||||
RED_DHIDE_BODY_G("Red dhide body (g)", ItemID.RED_DHIDE_BODY_G, "Clue Scroll (Hard)", "Dhide", 13),
|
||||
RED_DHIDE_CHAPS_G("Red dhide chaps (g)", ItemID.RED_DHIDE_CHAPS_G, "Clue Scroll (Hard)", "Dhide", 13),
|
||||
ENCHANTED_HAT("Enchanted hat", ItemID.ENCHANTED_HAT, "Clue Scroll (Hard)", "Enchanted", 14),
|
||||
ENCHANTED_TOP("Enchanted top", ItemID.ENCHANTED_TOP, "Clue Scroll (Hard)", "Enchanted", 14),
|
||||
ENCHANTED_ROBE("Enchanted robe", ItemID.ENCHANTED_ROBE, "Clue Scroll (Hard)", "Enchanted", 14),
|
||||
AMULET_OF_GLORY_T("Amulet of glory (t)", ItemID.AMULET_OF_GLORY_T, "Clue Scroll (Hard)", "Enchanted", 14),
|
||||
ROBIN_HOOD_HAT("Robin hood hat", ItemID.ROBIN_HOOD_HAT, "Clue Scroll (Hard)", "Hats", 15),
|
||||
PIRATE_HAT("Pirate hat", ItemID.PIRATE_HAT, "Clue Scroll (Hard)", "Hats", 15),
|
||||
PITH_HELMET("Pith helmet", ItemID.PITH_HELMET, "Clue Scroll (Hard)", "Hats", 15),
|
||||
EXPLORER_BACKPACK("Explorer backpack", ItemID.EXPLORER_BACKPACK, "Clue Scroll (Hard)", "Hats", 15),
|
||||
RED_CAVALIER("Red cavalier", ItemID.RED_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16),
|
||||
TAN_CAVALIER("Tan cavalier", ItemID.TAN_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16),
|
||||
DARK_CAVALIER("Dark cavalier", ItemID.DARK_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16),
|
||||
BLACK_CAVALIER("Black cavalier", ItemID.BLACK_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16),
|
||||
NAVY_CAVALIER("Navy cavalier", ItemID.NAVY_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16),
|
||||
WHITE_CAVALIER("White cavalier", ItemID.WHITE_CAVALIER, "Clue Scroll (Hard)", "Cavalier", 16),
|
||||
_3RD_AGE_FULL_HELMET("3rd age full helm", ItemID._3RD_AGE_FULL_HELMET, "Clue Scroll (Hard)", "Third age", 17),
|
||||
_3RD_AGE_PLATEBODY("3rd age platebody", ItemID._3RD_AGE_PLATEBODY, "Clue Scroll (Hard)", "Third age", 17),
|
||||
_3RD_AGE_PLATELEGS("3rd age platelegs", ItemID._3RD_AGE_PLATELEGS, "Clue Scroll (Hard)", "Third age", 17),
|
||||
_3RD_AGE_PLATESKIRT("3rd age plateskirt", ItemID._3RD_AGE_PLATESKIRT, "Clue Scroll (Hard)", "Third age", 17),
|
||||
_3RD_AGE_KITESHIELD("3rd age kiteshield", ItemID._3RD_AGE_KITESHIELD, "Clue Scroll (Hard)", "Third age", 17),
|
||||
_3RD_AGE_RANGE_COIF("3rd age range coif", ItemID._3RD_AGE_RANGE_COIF, "Clue Scroll (Hard)", "Third age", 18),
|
||||
_3RD_AGE_RANGE_TOP("3rd age range top", ItemID._3RD_AGE_RANGE_TOP, "Clue Scroll (Hard)", "Third age", 18),
|
||||
_3RD_AGE_RANGE_LEGS("3rd age range legs", ItemID._3RD_AGE_RANGE_LEGS, "Clue Scroll (Hard)", "Third age", 18),
|
||||
_3RD_AGE_VAMBRACES("3rd age vambraces", ItemID._3RD_AGE_VAMBRACES, "Clue Scroll (Hard)", "Third age", 18),
|
||||
_3RD_AGE_MAGE_HAT("3rd age mage hat", ItemID._3RD_AGE_MAGE_HAT, "Clue Scroll (Hard)", "Third age", 19),
|
||||
_3RD_AGE_ROBE_TOP("3rd age robe top", ItemID._3RD_AGE_ROBE_TOP, "Clue Scroll (Hard)", "Third age", 19),
|
||||
_3RD_AGE_ROBE("3rd age robe", ItemID._3RD_AGE_ROBE, "Clue Scroll (Hard)", "Third age", 19),
|
||||
_3RD_AGE_AMULET("3rd age amulet", ItemID._3RD_AGE_AMULET, "Clue Scroll (Hard)", "Third age", 19),
|
||||
GUTHIX_COIF("Guthix coif", ItemID.GUTHIX_COIF, "Clue Scroll (Hard)", "God Dhide", 20),
|
||||
GUTHIX_DHIDE("Guthix dragonhide", ItemID.GUTHIX_DRAGONHIDE, "Clue Scroll (Hard)", "God Dhide", 20),
|
||||
GUTHIX_CHAPS("Guthix chaps", ItemID.GUTHIX_CHAPS, "Clue Scroll (Hard)", "God Dhide", 20),
|
||||
GUTHIX_BRACERS("Guthix bracers", ItemID.GUTHIX_BRACERS, "Clue Scroll (Hard)", "God Dhide", 20),
|
||||
GUTHIX_DHIDE_BOOTS("Guthix dhide boots", ItemID.GUTHIX_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 20),
|
||||
GUTHIX_DHIDE_SHIELD("Guthix dhide shield", ItemID.GUTHIX_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 20),
|
||||
SARADOMIN_COIF("Saradomin coif", ItemID.SARADOMIN_COIF, "Clue Scroll (Hard)", "God Dhide", 21),
|
||||
SARADOMIN_DHIDE("Saradomin dragonhide", ItemID.SARADOMIN_DHIDE, "Clue Scroll (Hard)", "God Dhide", 21),
|
||||
SARADOMIN_CHAPS("Saradomin chaps", ItemID.SARADOMIN_CHAPS, "Clue Scroll (Hard)", "God Dhide", 21),
|
||||
SARADOMIN_BRACERS("Saradomin bracers", ItemID.SARADOMIN_BRACERS, "Clue Scroll (Hard)", "God Dhide", 21),
|
||||
SARADOMIN_DHIDE_BOOTS("Saradomin dhide boots", ItemID.SARADOMIN_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 21),
|
||||
SARADOMIN_DHIDE_SHIELD("Saradomin dhide shield", ItemID.SARADOMIN_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 21),
|
||||
ZAMORAK_COIF("Zamorak coif", ItemID.ZAMORAK_COIF, "Clue Scroll (Hard)", "God Dhide", 22),
|
||||
ZAMORAK_DHIDE("Zamorak dragonhide", ItemID.ZAMORAK_DHIDE, "Clue Scroll (Hard)", "God Dhide", 22),
|
||||
ZAMORAK_CHAPS("Zamorak chaps", ItemID.ZAMORAK_CHAPS, "Clue Scroll (Hard)", "God Dhide", 22),
|
||||
ZAMORAK_BRACERS("Zamorak bracers", ItemID.ZAMORAK_BRACERS, "Clue Scroll (Hard)", "God Dhide", 22),
|
||||
ZAMORAK_DHIDE_BOOTS("Zamorak dhide boots", ItemID.ZAMORAK_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 22),
|
||||
ZAMORAK_DHIDE_SHIELD("Zamorak dhide shield", ItemID.ZAMORAK_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 22),
|
||||
ANCIENT_COIF("Ancient coif", ItemID.ANCIENT_COIF, "Clue Scroll (Hard)", "God Dhide", 23),
|
||||
ANCIENT_DHIDE("Ancient dragonhide", ItemID.ANCIENT_DHIDE, "Clue Scroll (Hard)", "God Dhide", 23),
|
||||
ANCIENT_CHAPS("Ancient chaps", ItemID.ANCIENT_CHAPS, "Clue Scroll (Hard)", "God Dhide", 23),
|
||||
ANCIENT_BRACERS("Ancient bracers", ItemID.ANCIENT_BRACERS, "Clue Scroll (Hard)", "God Dhide", 23),
|
||||
ANCIENT_DHIDE_BOOTS("Ancient dhide boots", ItemID.ANCIENT_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 23),
|
||||
ANCIENT_DHIDE_SHIELD("Ancient dhide shield", ItemID.ANCIENT_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 23),
|
||||
BANDOS_COIF("Bandos coif", ItemID.BANDOS_COIF, "Clue Scroll (Hard)", "God Dhide", 24),
|
||||
BANDOS_DHIDE("Bandos dragonhide", ItemID.BANDOS_DHIDE, "Clue Scroll (Hard)", "God Dhide", 24),
|
||||
BANDOS_CHAPS("Bandos chaps", ItemID.BANDOS_CHAPS, "Clue Scroll (Hard)", "God Dhide", 24),
|
||||
BANDOS_BRACERS("Bandos bracers", ItemID.BANDOS_BRACERS, "Clue Scroll (Hard)", "God Dhide", 24),
|
||||
BANDOS_DHIDE_BOOTS("Bandos dhide boots", ItemID.BANDOS_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 24),
|
||||
BANDOS_DHIDE_SHIELD("Bandos dhide shield", ItemID.BANDOS_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 24),
|
||||
ARMADYL_COIF("Armadyl coif", ItemID.ARMADYL_COIF, "Clue Scroll (Hard)", "God Dhide", 25),
|
||||
ARMADYL_DHIDE("Armadyl dragonhide", ItemID.ARMADYL_DHIDE, "Clue Scroll (Hard)", "God Dhide", 25),
|
||||
ARMADYL_CHAPS("Armadyl chaps", ItemID.ARMADYL_CHAPS, "Clue Scroll (Hard)", "God Dhide", 25),
|
||||
ARMADYL_BRACERS("Armadyl bracers", ItemID.ARMADYL_BRACERS, "Clue Scroll (Hard)", "God Dhide", 25),
|
||||
ARMADYL_DHIDE_BOOTS("Armadyl dhide boots", ItemID.ARMADYL_DHIDE_BOOTS, "Clue Scroll (Hard)", "God Dhide", 25),
|
||||
ARMADYL_DHIDE_SHIELD("Armadyl dhide shield", ItemID.ARMADYL_DHIDE_SHIELD, "Clue Scroll (Hard)", "God Dhide", 25),
|
||||
GUTHIX_STOLE("Guthix stole", ItemID.GUTHIX_STOLE, "Clue Scroll (Hard)", "Vestment", 26),
|
||||
GUTHIX_CROZIER("Guthix crozier", ItemID.GUTHIX_CROZIER, "Clue Scroll (Hard)", "Vestment", 26),
|
||||
SARADOMIN_STOLE("Saradomin stole", ItemID.SARADOMIN_STOLE, "Clue Scroll (Hard)", "Vestment", 26),
|
||||
SARADOMIN_CROZIER("Saradomin crozier", ItemID.SARADOMIN_CROZIER, "Clue Scroll (Hard)", "Vestment", 26),
|
||||
ZAMORAK_STOLE("Zamorak stole", ItemID.ZAMORAK_STOLE, "Clue Scroll (Hard)", "Vestment", 26),
|
||||
ZAMORAK_CROZIER("Zamorak crozier", ItemID.ZAMORAK_CROZIER, "Clue Scroll (Hard)", "Vestment", 26),
|
||||
GREEN_DRAGON_MASK("Green dragon mask", ItemID.GREEN_DRAGON_MASK, "Clue Scroll (Hard)", "Masks", 27),
|
||||
RED_DRAGON_MASK("Red dragon mask", ItemID.RED_DRAGON_MASK, "Clue Scroll (Hard)", "Masks", 27),
|
||||
BLUE_DRAGON_MASK("Blue dragon mask", ItemID.BLUE_DRAGON_MASK, "Clue Scroll (Hard)", "Masks", 27),
|
||||
BLACK_DRAGON_MASK("Black dragon mask", ItemID.BLACK_DRAGON_MASK, "Clue Scroll (Hard)", "Masks", 27),
|
||||
RUNE_CANE("Rune cane", ItemID.RUNE_CANE, "Clue Scroll (Hard)", "Other", 28),
|
||||
ZOMBIE_HEAD("Zombie head", ItemID.ZOMBIE_HEAD, "Clue Scroll (Hard)", "Other", 28),
|
||||
CYCLOPS_HEAD("Cyclops head", ItemID.CYCLOPS_HEAD, "Clue Scroll (Hard)", "Other", 28),
|
||||
NUNCHAKU("Nunchaku", ItemID.NUNCHAKU, "Clue Scroll (Hard)", "Other", 29),
|
||||
DUAL_SAI("Dual sai", ItemID.DUAL_SAI, "Clue Scroll (Hard)", "Other", 29),
|
||||
THIEVING_BAG("Thieving bag", ItemID.THIEVING_BAG, "Clue Scroll (Hard)", "Other", 29),
|
||||
DRAGON_BOOTS_ORNAMENT_KIT("Dragon boots ornament kit", ItemID.DRAGON_BOOTS_ORNAMENT_KIT, "Clue Scroll (Hard)", "Ornament Kit", 30),
|
||||
RUNE_DEFENDER_ORNAMENT_KIT("Rune defender ornament kit", ItemID.RUNE_DEFENDER_ORNAMENT_KIT, "Clue Scroll (Hard)", "Ornament Kit", 30),
|
||||
TZHAARKETOM_ORNAMENT_KIT("Tzhaar-ket-om ornament kit", ItemID.TZHAARKETOM_ORNAMENT_KIT, "Clue Scroll (Hard)", "Ornament Kit", 30),
|
||||
BERSERKER_NECKLACE_ORNAMENT_KIT("Berserker necklace ornament kit", ItemID.BERSERKER_NECKLACE_ORNAMENT_KIT, "Clue Scroll (Hard)", "Ornament Kit", 30),
|
||||
|
||||
// Elite Clue Scrolls
|
||||
DRAGON_FULL_HELM_ORNAMENT_KIT("Dragon full helm ornament kit", ItemID.DRAGON_FULL_HELM_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1),
|
||||
DRAGON_CHAINBODY_ORNAMENT_KIT("Dragon chainbody ornament kit", ItemID.DRAGON_CHAINBODY_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1),
|
||||
DRAGON_LEGSSKIRT_ORNAMENT_KIT("Dragon legs/skirt ornament kit", ItemID.DRAGON_LEGSSKIRT_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1),
|
||||
DRAGON_SQ_SHIELD_ORNAMENT_KIT("Dragon sq shield ornament kit", ItemID.DRAGON_SQ_SHIELD_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1),
|
||||
DRAGON_SCIMITAR_ORNAMENT_KIT("Dragon scimitar ornament kit", ItemID.DRAGON_SCIMITAR_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", -1),
|
||||
LIGHT_INFINITY_COLOUR_KIT("Light infinity colour kit", ItemID.LIGHT_INFINITY_COLOUR_KIT, "Clue Scroll (Elite)", "Colour Kits", 0),
|
||||
DARK_INFINITY_COLOUR_KIT("Dark infinity colour kit", ItemID.DARK_INFINITY_COLOUR_KIT, "Clue Scroll (Elite)", "Colour Kits", 0),
|
||||
FURY_ORNAMENT_KIT("Fury ornament kit", ItemID.FURY_ORNAMENT_KIT, "Clue Scroll (Elite)", "Ornament Kits", 0),
|
||||
MUSKETEER_HAT("Musketeer hat", ItemID.MUSKETEER_HAT, "Clue Scroll (Elite)", "Musketeer", 1),
|
||||
MUSKETEER_TABARD("Musketeer tabard", ItemID.MUSKETEER_TABARD, "Clue Scroll (Elite)", "Musketeer", 1),
|
||||
MUSKETEER_PANTS("Musketeer pants", ItemID.MUSKETEER_PANTS, "Clue Scroll (Elite)", "Musketeer", 1),
|
||||
DRAGON_CANE("Dragon cane", ItemID.DRAGON_CANE, "Clue Scroll (Elite)", "Musketeer", 1),
|
||||
TOP_HAT("Top hat", ItemID.TOP_HAT, "Clue Scroll (Elite)", "Fancy", 2),
|
||||
MONOCLE("Monocle", ItemID.MONOCLE, "Clue Scroll (Elite)", "Fancy", 2),
|
||||
BRIEFCASE("Briefcase", ItemID.BRIEFCASE, "Clue Scroll (Elite)", "Fancy", 2),
|
||||
SAGACIOUS_SPECTACLES("Sagacious spectacles", ItemID.SAGACIOUS_SPECTACLES, "Clue Scroll (Elite)", "Fancy", 2),
|
||||
BIG_PIRATE_HAT("Big pirate hat", ItemID.BIG_PIRATE_HAT, "Clue Scroll (Elite)", "Hats", 3),
|
||||
DEERSTALKER("Deerstalker", ItemID.DEERSTALKER, "Clue Scroll (Elite)", "Hats", 3),
|
||||
BLACKSMITHS_HELM("Blacksmith's helm", ItemID.BLACKSMITHS_HELM, "Clue Scroll (Elite)", "Hats", 3),
|
||||
BUCKET_HELM("Bucket helm", ItemID.BUCKET_HELM, "Clue Scroll (Elite)", "Hats", 3),
|
||||
AFRO("Afro", ItemID.AFRO, "Clue Scroll (Elite)", "Hats", 3),
|
||||
GILDED_BOOTS("Gilded boots", ItemID.GILDED_BOOTS, "Clue Scroll (Elite)", "Rare", 4),
|
||||
GILDED_SCIMITAR("Gilded scimitar", ItemID.GILDED_SCIMITAR, "Clue Scroll (Elite)", "Rare", 4),
|
||||
RANGERS_TUNIC("Rangers' tunic", ItemID.RANGERS_TUNIC, "Clue Scroll (Elite)", "Rare", 4),
|
||||
RANGERS_TIGHTS("Rangers' tights", ItemID.RANGERS_TIGHTS, "Clue Scroll (Elite)", "Rare", 4),
|
||||
RANGER_GLOVES("Ranger gloves", ItemID.RANGER_GLOVES, "Clue Scroll (Elite)", "Rare", 4),
|
||||
BRONZE_DRAGON_MASK("Bronze dragon mask", ItemID.BRONZE_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 5),
|
||||
IRON_DRAGON_MASK("Iron dragon mask", ItemID.IRON_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 5),
|
||||
STEEL_DRAGON_MASK("Steel dragon mask", ItemID.STEEL_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 5),
|
||||
MITHRIL_DRAGON_MASK("Mithril dragon mask", ItemID.MITHRIL_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 5),
|
||||
ADAMANT_DRAGON_MASK("Adamant dragon mask", ItemID.ADAMANT_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 6),
|
||||
RUNE_DRAGON_MASK("Rune dragon mask", ItemID.RUNE_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 6),
|
||||
LAVA_DRAGON_MASK("Lava dragon mask", ItemID.LAVA_DRAGON_MASK, "Clue Scroll (Elite)", "Masks", 6),
|
||||
BLACK_DHIDE_BODY_T("Black dhide body (t)", ItemID.BLACK_DHIDE_BODY_T, "Clue Scroll (Elite)", "Dhide", 7),
|
||||
BLACK_DHIDE_CHAPS_T("Black dhide chaps (t)", ItemID.BLACK_DHIDE_CHAPS_T, "Clue Scroll (Elite)", "Dhide", 7),
|
||||
BLACK_DHIDE_BODY_G("Black dhide body (g)", ItemID.BLACK_DHIDE_BODY_G, "Clue Scroll (Elite)", "Dhide", 7),
|
||||
BLACK_DHIDE_CHAPS_G("Black dhide chaps (g)", ItemID.BLACK_DHIDE_CHAPS_G, "Clue Scroll (Elite)", "Dhide", 7),
|
||||
GILDED_COIF("Gilded coif", ItemID.GILDED_COIF, "Clue Scroll (Elite)", "Dhide", 8),
|
||||
GILDED_DHIDE_BODY("Gilded dhide body", ItemID.GILDED_DHIDE_BODY, "Clue Scroll (Elite)", "Dhide", 8),
|
||||
GILDED_DHIDE_CHAPS("Gilded dhide chaps", ItemID.GILDED_DHIDE_CHAPS, "Clue Scroll (Elite)", "Dhide", 8),
|
||||
GILDED_DHIDE_VAMBS("Gilded dhide vambs", ItemID.GILDED_DHIDE_VAMBS, "Clue Scroll (Elite)", "Dhide", 8),
|
||||
_3RD_AGE_CLOAK("3rd age cloak", ItemID._3RD_AGE_CLOAK, "Clue Scroll (Elite)", "Third Age", 9),
|
||||
_3RD_AGE_WAND("3rd age wand", ItemID._3RD_AGE_WAND, "Clue Scroll (Elite)", "Third Age", 9),
|
||||
_3RD_AGE_BOW("3rd age bow", ItemID._3RD_AGE_BOW, "Clue Scroll (Elite)", "Third Age", 9),
|
||||
_3RD_AGE_LONGSWORD("3rd age longsword", ItemID._3RD_AGE_LONGSWORD, "Clue Scroll (Elite)", "Third Age", 9),
|
||||
ROYAL_CROWN("Royal crown", ItemID.ROYAL_CROWN, "Clue Scroll (Elite)", "Royal", 10),
|
||||
ROYAL_GOWN_TOP("Royal gown top", ItemID.ROYAL_GOWN_TOP, "Clue Scroll (Elite)", "Royal", 10),
|
||||
ROYAL_GOWN_BOTTOM("Royal gown bottom", ItemID.ROYAL_GOWN_BOTTOM, "Clue Scroll (Elite)", "Royal", 10),
|
||||
ROYAL_SCEPTRE("Royal sceptre", ItemID.ROYAL_SCEPTRE, "Clue Scroll (Elite)", "Royal", 10),
|
||||
GILDED_PICKAXE("Gilded pickaxe", ItemID.GILDED_PICKAXE, "Clue Scroll (Elite)", "Gilded", 11),
|
||||
GILDED_AXE("Gilded axe", ItemID.GILDED_AXE, "Clue Scroll (Elite)", "Gilded", 11),
|
||||
GILDED_SPADE("Gilded spade", ItemID.GILDED_SPADE, "Clue Scroll (Elite)", "Gilded", 11),
|
||||
ARCEUUS_SCARF("Arceuus house scarf", ItemID.ARCEUUS_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12),
|
||||
HOSIDIUS_SCARF("Hosidius house scarf", ItemID.HOSIDIUS_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12),
|
||||
LOVAKENGJ_SCARF("Lovakengj house scarf", ItemID.LOVAKENGJ_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12),
|
||||
PISCARILIUS_SCARF("Piscarilius house scarf", ItemID.PISCARILIUS_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12),
|
||||
SHAYZIEN_SCARF("Shayzien house scarf", ItemID.SHAYZIEN_SCARF, "Clue Scroll (Elite)", "Zeah Scarfs", 12),
|
||||
DARK_BOW_TIE("Dark bow tie", ItemID.DARK_BOW_TIE, "Clue Scroll (Elite)", "Dark Tuxedo", 13),
|
||||
DARK_TUXEDO_JACKET("Dark tuxedo jacket", ItemID.DARK_TUXEDO_JACKET, "Clue Scroll (Elite)", "Dark Tuxedo", 13),
|
||||
DARK_TROUSERS("Dark trousers", ItemID.DARK_TROUSERS, "Clue Scroll (Elite)", "Dark Tuxedo", 13),
|
||||
DARK_TUXEDO_CUFFS("Dark tuxedo cuffs", ItemID.DARK_TUXEDO_CUFFS, "Clue Scroll (Elite)", "Dark Tuxedo", 13),
|
||||
DARK_TUXEDO_SHOES("Dark tuxedo shoes", ItemID.DARK_TUXEDO_SHOES, "Clue Scroll (Elite)", "Dark Tuxedo", 13),
|
||||
LIGHT_BOW_TIE("Light bow tie", ItemID.LIGHT_BOW_TIE, "Clue Scroll (Elite)", "Light Tuxedo", 14),
|
||||
LIGHT_TUXEDO_JACKET("Light tuxedo jacket", ItemID.LIGHT_TUXEDO_JACKET, "Clue Scroll (Elite)", "Light Tuxedo", 14),
|
||||
LIGHT_TROUSERS("Light trousers", ItemID.LIGHT_TROUSERS, "Clue Scroll (Elite)", "Light Tuxedo", 14),
|
||||
LIGHT_TUXEDO_CUFFS("Light tuxedo cuffs", ItemID.LIGHT_TUXEDO_CUFFS, "Clue Scroll (Elite)", "Light Tuxedo", 14),
|
||||
LIGHT_TUXEDO_SHOES("Light tuxedo shoes", ItemID.LIGHT_TUXEDO_SHOES, "Clue Scroll (Elite)", "Light Tuxedo", 14),
|
||||
HOLY_WRAPS("Holy wraps", ItemID.HOLY_WRAPS, "Clue Scroll (Elite)", "Other", 15),
|
||||
RING_OF_NATURE("Ring of nature", ItemID.RING_OF_NATURE, "Clue Scroll (Elite)", "Other", 15),
|
||||
HEAVY_CASKET("Heavy casket", ItemID.HEAVY_CASKET, "Clue Scroll (Elite)", "Other", 15),
|
||||
KATANA("Katana", ItemID.KATANA, "Clue Scroll (Elite)", "Other", 16),
|
||||
URIS_HAT("Uri's hat", ItemID.URIS_HAT, "Clue Scroll (Elite)", "Other", 16),
|
||||
FREMENNIK_KILT("Fremennik Kilt", ItemID.FREMENNIK_KILT, "Clue Scroll (Elite)", "Other", 16),
|
||||
|
||||
// Master Clue Scrolls
|
||||
DRAGON_PLATEBODY_ORNAMENT_KIT("Dragon platebody ornament kit", ItemID.DRAGON_PLATEBODY_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1),
|
||||
DRAGON_KITESHIELD_ORNAMENT_KIT("Dragon kiteshield ornament kit", ItemID.DRAGON_KITESHIELD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1),
|
||||
DRAGON_DEFENDER_ORNAMENT_KIT("Dragon defender ornament kit", ItemID.DRAGON_DEFENDER_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1),
|
||||
TORMENTED_ORNAMENT_KIT("Tormented bracelet ornament kit", ItemID.TORMENTED_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1),
|
||||
ANGUISH_ORNAMENT_KIT("Anguish ornament kit", ItemID.ANGUISH_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1),
|
||||
TORTURE_ORNAMENT_KIT("Torture ornament kit", ItemID.TORTURE_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", -1),
|
||||
OCCULT_ORNAMENT_KIT("Occult ornament kit", ItemID.OCCULT_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0),
|
||||
ARMADYL_GODSWORD_ORNAMENT_KIT("Armadyl godsword ornament kit", ItemID.ARMADYL_GODSWORD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0),
|
||||
BANDOS_GODSWORD_ORNAMENT_KIT("Bandos godsword ornament kit", ItemID.BANDOS_GODSWORD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0),
|
||||
SARADOMIN_GODSWORD_ORNAMENT_KIT("Saradomin godsword ornament kit", ItemID.SARADOMIN_GODSWORD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0),
|
||||
ZAMORAK_GODSWORD_ORNAMENT_KIT("Zamorak godsword ornament kit", ItemID.ZAMORAK_GODSWORD_ORNAMENT_KIT, "Clue Scroll (Master)", "Ornament Kits", 0),
|
||||
_3RD_AGE_AXE("3rd age axe", ItemID._3RD_AGE_AXE, "Clue Scroll (Master)", "3rd age", 1),
|
||||
_3RD_AGE_PICKAXE("3rd age pickaxe", ItemID._3RD_AGE_PICKAXE, "Clue Scroll (Master)", "3rd age", 1),
|
||||
_3RD_AGE_DRUIDIC_STAFF("3rd age druidic staff", ItemID._3RD_AGE_DRUIDIC_STAFF, "Clue Scroll (Master)", "3rd age", 2),
|
||||
_3RD_AGE_DRUIDIC_ROBE_TOP("3rd age druidic robe top", ItemID._3RD_AGE_DRUIDIC_ROBE_TOP, "Clue Scroll (Master)", "3rd age", 2),
|
||||
_3RD_AGE_DRUIDIC_ROBE_BOTTOMS("3rd age druidic robe bottom", ItemID._3RD_AGE_DRUIDIC_ROBE_BOTTOMS, "Clue Scroll (Master)", "3rd age", 2),
|
||||
_3RD_AGE_DRUIDIC_CLOAK("3rd age druidic cloak", ItemID._3RD_AGE_DRUIDIC_CLOAK, "Clue Scroll (Master)", "3rd age", 2),
|
||||
LESSER_DEMON_MASK("Lesser demon mask", ItemID.LESSER_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3),
|
||||
GREATER_DEMON_MASK("Greater demon mask", ItemID.GREATER_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3),
|
||||
BLACK_DEMON_MASK("Black demon mask", ItemID.BLACK_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3),
|
||||
JUNGLE_DEMON_MASK("Jungle demon mask", ItemID.JUNGLE_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3),
|
||||
OLD_DEMON_MASK("Old demon mask", ItemID.OLD_DEMON_MASK, "Clue Scroll (Master)", "Demon Masks", 3),
|
||||
ARCEUUS_HOOD("Arceuus house hood", ItemID.ARCEUUS_HOOD, "Clue Scroll (Master)", "House Hoods", 4),
|
||||
HOSIDIUS_HOOD("Hosidius house hood", ItemID.HOSIDIUS_HOOD, "Clue Scroll (Master)", "House Hoods", 4),
|
||||
LOVAKENGJ_HOOD("Lovakengj house hood", ItemID.LOVAKENGJ_HOOD, "Clue Scroll (Master)", "House Hoods", 4),
|
||||
PISCARILIUS_HOOD("Piscarilius house hood", ItemID.PISCARILIUS_HOOD, "Clue Scroll (Master)", "House Hoods", 4),
|
||||
SHAYZIEN_HOUSE_HOOD("Shayzien house hood", ItemID.SHAYZIEN_HOOD, "Clue Scroll (Master)", "House Hoods", 4),
|
||||
SAMURAI_KASA("Samurai kasa", ItemID.SAMURAI_KASA, "Clue Scroll (Master)", "Samurai Outfit", 5),
|
||||
SAMURAI_SHIRT("Samurai shirt", ItemID.SAMURAI_SHIRT, "Clue Scroll (Master)", "Samurai Outfit", 5),
|
||||
SAMURAI_GREAVES("Samurai greaves", ItemID.SAMURAI_GREAVES, "Clue Scroll (Master)", "Samurai Outfit", 5),
|
||||
SAMURAI_GLOVES("Samurai gloves", ItemID.SAMURAI_GLOVES, "Clue Scroll (Master)", "Samurai Outfit", 5),
|
||||
SAMURAI_BOOTS("Samurai boots", ItemID.SAMURAI_BOOTS, "Clue Scroll (Master)", "Samurai Outfit", 5),
|
||||
MUMMYS_HEAD("Mummy's head", ItemID.MUMMYS_HEAD, "Clue Scroll (Master)", "Mummy Outfit", 6),
|
||||
MUMMYS_BODY("Mummy's body", ItemID.MUMMYS_BODY, "Clue Scroll (Master)", "Mummy Outfit", 6),
|
||||
MUMMYS_LEGS("Mummy's legs", ItemID.MUMMYS_LEGS, "Clue Scroll (Master)", "Mummy Outfit", 6),
|
||||
MUMMYS_HANDS("Mummy's hands", ItemID.MUMMYS_HANDS, "Clue Scroll (Master)", "Mummy Outfit", 6),
|
||||
MUMMYS_FEET("Mummy's feet", ItemID.MUMMYS_FEET, "Clue Scroll (Master)", "Mummy Outfit", 6),
|
||||
ANKOU_MASK("Ankou mask", ItemID.ANKOU_MASK, "Clue Scroll (Master)", "Ankou Outfit", 7),
|
||||
ANKOU_TOP("Ankou top", ItemID.ANKOU_TOP, "Clue Scroll (Master)", "Ankou Outfit", 7),
|
||||
ANKOUS_LEGGINGS("Ankou's leggings", ItemID.ANKOUS_LEGGINGS, "Clue Scroll (Master)", "Ankou Outfit", 7),
|
||||
ANKOU_GLOVES("Ankou gloves", ItemID.ANKOU_GLOVES, "Clue Scroll (Master)", "Ankou Outfit", 7),
|
||||
ANKOU_SOCKS("Ankou socks", ItemID.ANKOU_SOCKS, "Clue Scroll (Master)", "Ankou Outfit", 7),
|
||||
HOOD_OF_DARKNESS("Hood of darkness", ItemID.HOOD_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8),
|
||||
ROBE_TOP_OF_DARKNESS("Robe top of darkness", ItemID.ROBE_TOP_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8),
|
||||
ROBE_BOTTOM_OF_DARKNESS("Robe bottom of darkness", ItemID.ROBE_BOTTOM_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8),
|
||||
BOOTS_OF_DARKNESS("Boots of darkness", ItemID.BOOTS_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8),
|
||||
GLOVES_OF_DARKNESS("Gloves of darkness", ItemID.GLOVES_OF_DARKNESS, "Clue Scroll (Master)", "Robes of Darkness", 8),
|
||||
RING_OF_COINS("Ring of coins", ItemID.RING_OF_COINS, "Clue Scroll (Master)", "Other", 9),
|
||||
LEFT_EYE_PATCH("Left eye patch", ItemID.LEFT_EYE_PATCH, "Clue Scroll (Master)", "Other", 9),
|
||||
OBSIDIAN_CAPE_R("Obsidian cape (r)", ItemID.OBSIDIAN_CAPE_R, "Clue Scroll (Master)", "Other", 9),
|
||||
FANCY_TIARA("Fancy tiara", ItemID.FANCY_TIARA, "Clue Scroll (Master)", "Other", 9),
|
||||
HALF_MOON_SPECTACLES("Half moon spectacles", ItemID.HALF_MOON_SPECTACLES, "Clue Scroll (Master)", "Other", 9),
|
||||
ALE_OF_THE_GODS("Ale of the gods", ItemID.ALE_OF_THE_GODS, "Clue Scroll (Master)", "Other 2", 10),
|
||||
BUCKET_HELM_G("Bucket helm (g)", ItemID.BUCKET_HELM_G, "Clue Scroll (Master)", "Other 2", 10),
|
||||
BOWL_WIG("Bowl wig", ItemID.BOWL_WIG, "Clue Scroll (Master)", "Other 2", 10),
|
||||
BLOODHOUND("Bloodhound", ItemID.BLOODHOUND, "Clue Scroll (Master)", "Other 2", 10),
|
||||
|
||||
HERBI("Herbi", ItemID.HERBI, "Herbiboar", "Pet", -1);
|
||||
|
||||
// Shared Unique Items
|
||||
UniqueItem(String n, int id, String... activities)
|
||||
{
|
||||
this.name = n;
|
||||
this.itemID = id;
|
||||
this.activities = activities;
|
||||
this.setName = "Shared";
|
||||
this.position = -1;
|
||||
}
|
||||
|
||||
// Non-Shared Unique Items
|
||||
UniqueItem(String n, int id, String a, String set, int position)
|
||||
{
|
||||
this.name = n;
|
||||
this.itemID = id;
|
||||
this.activities = new String[]{a};
|
||||
this.setName = set;
|
||||
this.position = position;
|
||||
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final int itemID;
|
||||
private final String[] activities;
|
||||
private final String setName;
|
||||
private final int position;
|
||||
|
||||
// Get a specific UniqueItem by Name
|
||||
// Unused ATM
|
||||
private static final Map<String, UniqueItem> byName = buildNameMap();
|
||||
public static UniqueItem getByName(String name)
|
||||
{
|
||||
return byName.get(name.toUpperCase());
|
||||
}
|
||||
private static Map<String, UniqueItem> buildNameMap()
|
||||
{
|
||||
Map<String, UniqueItem> byName = new HashMap<>();
|
||||
for (UniqueItem item : values())
|
||||
{
|
||||
byName.put(item.getName().toUpperCase(), item);
|
||||
}
|
||||
|
||||
return byName;
|
||||
}
|
||||
|
||||
// Returns an array of UniqueItems by an individual `activities` name
|
||||
private static final Map<String, ArrayList<UniqueItem>> byActivityName = buildActivityMap();
|
||||
public static ArrayList<UniqueItem> getByActivityName(String name)
|
||||
{
|
||||
return byActivityName.get(name.toUpperCase());
|
||||
}
|
||||
private static Map<String, ArrayList<UniqueItem>> buildActivityMap()
|
||||
{
|
||||
Map<String, ArrayList<UniqueItem>> byName = new HashMap<>();
|
||||
for (UniqueItem item : values())
|
||||
{
|
||||
String[] activities = item.getActivities();
|
||||
for (String activity : activities)
|
||||
{
|
||||
byName.computeIfAbsent(activity.toUpperCase(), e -> new ArrayList<UniqueItem>()).add(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return byName;
|
||||
}
|
||||
|
||||
// Return an array of UniqueItems by `setName`
|
||||
// Unused ATM
|
||||
private static final Map<String, ArrayList<UniqueItem>> bySetName = buildSetMap();
|
||||
public static ArrayList<UniqueItem> getBySetName(String name)
|
||||
{
|
||||
return bySetName.get(name.toUpperCase());
|
||||
}
|
||||
private static Map<String, ArrayList<UniqueItem>> buildSetMap()
|
||||
{
|
||||
Map<String, ArrayList<UniqueItem>> byName = new HashMap<>();
|
||||
for (UniqueItem item : values())
|
||||
{
|
||||
byName.computeIfAbsent(item.getSetName().toUpperCase(), e -> new ArrayList<>()).add(item);
|
||||
}
|
||||
|
||||
return byName;
|
||||
}
|
||||
|
||||
// Takes a list of UniqueItems and maps them by Position to ensure adding in predefined order
|
||||
public static Map<Integer, Collection<UniqueItemPrepared>> createPositionSetMap(Collection<UniqueItemPrepared> items)
|
||||
{
|
||||
Map<Integer, Collection<UniqueItemPrepared>> setNames = new HashMap<>();
|
||||
for (UniqueItemPrepared item : items)
|
||||
{
|
||||
setNames.computeIfAbsent(item.getUniqueItem().getPosition(), e -> new ArrayList<>()).add(item);
|
||||
}
|
||||
|
||||
// Sort them by Key
|
||||
return setNames.entrySet().stream()
|
||||
.sorted(Map.Entry.comparingByKey())
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
public class UniqueItemPrepared
|
||||
{
|
||||
private int linkedID;
|
||||
private int price;
|
||||
private UniqueItem uniqueItem;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data.events;
|
||||
|
||||
public class LootTrackerNameChange
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.data.events;
|
||||
|
||||
import lombok.Data;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom;
|
||||
|
||||
@Data
|
||||
public class LootTrackerRecordStored
|
||||
{
|
||||
private final LootRecordCustom record;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <www.github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.GridLayout;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.ui.components.shadowlabel.JShadowedLabel;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
|
||||
@Getter
|
||||
class ItemPanel extends JPanel
|
||||
{
|
||||
private static final GridBagLayout LAYOUT = new GridBagLayout();
|
||||
private static final Dimension PANEL_SIZE = new Dimension(215, 50);
|
||||
|
||||
private static final Border PANEL_BORDER = BorderFactory.createMatteBorder(3, 0, 3, 0, ColorScheme.DARK_GRAY_COLOR);
|
||||
private static final Color PANEL_BACKGROUND_COLOR = ColorScheme.DARKER_GRAY_COLOR;
|
||||
|
||||
private static final Border CONTAINER_BORDER = BorderFactory.createMatteBorder(4, 15, 4, 15, PANEL_BACKGROUND_COLOR);
|
||||
|
||||
private LootTrackerItemEntry record;
|
||||
|
||||
ItemPanel(LootTrackerItemEntry record, ItemManager itemManager)
|
||||
{
|
||||
this.record = record;
|
||||
this.setLayout(LAYOUT);
|
||||
this.setBorder(PANEL_BORDER);
|
||||
this.setBackground(PANEL_BACKGROUND_COLOR);
|
||||
this.setPreferredSize(PANEL_SIZE);
|
||||
|
||||
// Item Image Icon
|
||||
JLabel icon = new JLabel();
|
||||
itemManager.getImage(record.getId(), record.getQuantity(), (record.isStackable() || record.getQuantity() > 1)).addTo(icon);
|
||||
icon.setHorizontalAlignment(JLabel.CENTER);
|
||||
|
||||
// Container for Info
|
||||
JPanel uiInfo = new JPanel(new GridLayout(2, 1));
|
||||
uiInfo.setBorder(new EmptyBorder(0, 5, 0, 0));
|
||||
uiInfo.setBackground(PANEL_BACKGROUND_COLOR);
|
||||
|
||||
JShadowedLabel labelName = new JShadowedLabel(this.record.getName());
|
||||
labelName.setForeground(Color.WHITE);
|
||||
colorLabel(labelName, this.record.getPrice());
|
||||
labelName.setVerticalAlignment(SwingUtilities.BOTTOM);
|
||||
|
||||
String gpLabel = StackFormatter.quantityToStackSize(this.record.getTotal()) + " gp";
|
||||
|
||||
if (this.record.getHaTotal() > 0 && this.record.getHaPrice() > 1)
|
||||
{
|
||||
gpLabel += " (HA: " + StackFormatter.quantityToStackSize(this.record.getHaTotal()) + " gp)";
|
||||
}
|
||||
|
||||
JShadowedLabel labelValue = new JShadowedLabel(gpLabel);
|
||||
labelValue.setFont(FontManager.getRunescapeSmallFont());
|
||||
colorLabel(labelValue, this.record.getTotal());
|
||||
labelValue.setVerticalAlignment(SwingUtilities.TOP);
|
||||
|
||||
uiInfo.add(labelName);
|
||||
uiInfo.add(labelValue);
|
||||
|
||||
// Create and append elements to container panel
|
||||
JPanel panel = createPanel();
|
||||
panel.add(icon, BorderLayout.LINE_START);
|
||||
panel.add(uiInfo, BorderLayout.CENTER);
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 1;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
|
||||
this.add(panel, c);
|
||||
this.setToolTipText(UniqueItemPanel.tooltipText(this.record.getPrice(), this.record.getHaPrice(), this.record.getQuantity(), this.record.getName()));
|
||||
}
|
||||
|
||||
static JPanel createPanel()
|
||||
{
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new BorderLayout());
|
||||
panel.setBorder(CONTAINER_BORDER);
|
||||
panel.setBackground(PANEL_BACKGROUND_COLOR);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
// Color label to match RuneScape coloring
|
||||
private void colorLabel(JLabel label, long val)
|
||||
{
|
||||
Color labelColor = (val >= 10000000) ? Color.GREEN : (val >= 100000) ? Color.WHITE : Color.YELLOW;
|
||||
label.setForeground(labelColor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.ui;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
|
||||
class LootGrid extends JPanel
|
||||
{
|
||||
private static final int ITEMS_PER_ROW = 5;
|
||||
private static final Dimension ITEM_SIZE = new Dimension(40, 40);
|
||||
private final LootTrackerItemEntry[] itemsToDisplay;
|
||||
private ItemManager itemManager;
|
||||
|
||||
LootGrid(LootTrackerItemEntry[] itemsToDisplay, ItemManager itemManager)
|
||||
{
|
||||
this.itemsToDisplay = itemsToDisplay;
|
||||
this.itemManager = itemManager;
|
||||
|
||||
setBorder(new EmptyBorder(5, 0, 5, 0));
|
||||
|
||||
buildItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates stacked items from the item list, calculates total price and then
|
||||
* displays all the items in the UI.
|
||||
*/
|
||||
private void buildItems()
|
||||
{
|
||||
ArrayList<LootTrackerItemEntry> items = LootTrackerBox.dedupeClues(Arrays.asList(itemsToDisplay));
|
||||
|
||||
// Calculates how many rows need to be display to fit all items
|
||||
final int rowSize = LootTrackerBox.rowSize(items.size());
|
||||
|
||||
removeAll();
|
||||
setLayout(new GridLayout(rowSize, ITEMS_PER_ROW, 1, 1));
|
||||
|
||||
for (int i = 0; i < rowSize * ITEMS_PER_ROW; i++)
|
||||
{
|
||||
final JPanel slot = new JPanel();
|
||||
slot.setLayout(new GridLayout(1, 1, 0, 0));
|
||||
slot.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
slot.setPreferredSize(ITEM_SIZE);
|
||||
if (i < items.size())
|
||||
{
|
||||
final LootTrackerItemEntry item = items.get(i);
|
||||
if (item == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
final JLabel itemLabel = new JLabel();
|
||||
itemLabel.setToolTipText(buildToolTip(item));
|
||||
itemLabel.setVerticalAlignment(SwingConstants.CENTER);
|
||||
itemLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1).addTo(itemLabel);
|
||||
slot.add(itemLabel);
|
||||
}
|
||||
|
||||
add(slot);
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
private static String buildToolTip(LootTrackerItemEntry item)
|
||||
{
|
||||
final String name = item.getName();
|
||||
final int quantity = item.getQuantity();
|
||||
final long price = item.getPrice();
|
||||
|
||||
return "<html>" + name + " x " + StackFormatter.formatNumber(quantity)
|
||||
+ "<br/>Price: " + StackFormatter.quantityToStackSize(price)
|
||||
+ "<br/>Total: " + StackFormatter.quantityToStackSize(quantity * price) + "</html";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.ui;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.stonedloottracker.ItemSortTypes;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.UniqueItemPrepared;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
|
||||
@Slf4j
|
||||
class LootPanel extends JPanel
|
||||
{
|
||||
private Collection<LootRecordCustom> records;
|
||||
private Map<Integer, Collection<UniqueItemPrepared>> uniqueMap;
|
||||
private boolean hideUniques;
|
||||
private ItemSortTypes sortType;
|
||||
private boolean itemBreakdown;
|
||||
private ItemManager itemManager;
|
||||
// Consolidate LTItemEntries stored by ItemID
|
||||
private Map<Integer, LootTrackerItemEntry> consolidated;
|
||||
|
||||
@Getter
|
||||
private boolean playbackPlaying = false;
|
||||
private boolean cancelPlayback = false;
|
||||
|
||||
LootPanel(Collection<LootRecordCustom> records, Map<Integer, Collection<UniqueItemPrepared>> uniqueMap, boolean hideUnqiues, ItemSortTypes sort, boolean itemBreakdown, ItemManager itemManager)
|
||||
{
|
||||
this.records = (records == null ? new ArrayList<>() : records);
|
||||
this.uniqueMap = (uniqueMap == null ? new HashMap<>() : uniqueMap);
|
||||
this.hideUniques = hideUnqiues;
|
||||
this.sortType = sort;
|
||||
this.itemBreakdown = itemBreakdown;
|
||||
this.itemManager = itemManager;
|
||||
|
||||
setLayout(new GridBagLayout());
|
||||
setBorder(new EmptyBorder(0, 10, 0, 10));
|
||||
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||
|
||||
createConsolidatedArray(this.records);
|
||||
createPanel(this.records);
|
||||
}
|
||||
|
||||
private void createConsolidatedArray(Collection<LootRecordCustom> records)
|
||||
{
|
||||
// Consolidate all LootTrackerItemEntrys from each record for combined loot totals
|
||||
// Sort them based on the config setting.
|
||||
this.consolidated = LootRecordCustom.consolidateLootTrackerItemEntries(records)
|
||||
.entrySet().stream()
|
||||
.sorted((lt1, lt2) ->
|
||||
{
|
||||
LootTrackerItemEntry o1 = lt1.getValue();
|
||||
LootTrackerItemEntry o2 = lt2.getValue();
|
||||
switch (sortType)
|
||||
{
|
||||
case ITEM_ID:
|
||||
return o1.getId() - o2.getId();
|
||||
case PRICE:
|
||||
if (o1.getPrice() != o2.getPrice())
|
||||
{
|
||||
return o1.getPrice() > o2.getPrice() ? -1 : 1;
|
||||
}
|
||||
break;
|
||||
case VALUE:
|
||||
if (o1.getTotal() != o2.getTotal())
|
||||
{
|
||||
return o1.getTotal() > o2.getTotal() ? -1 : 1;
|
||||
}
|
||||
break;
|
||||
case ALPHABETICAL:
|
||||
// Handled below
|
||||
break;
|
||||
default:
|
||||
log.warn("Sort Type not being handled correctly, defaulting to alphabetical.");
|
||||
break;
|
||||
}
|
||||
|
||||
// Default to alphabetical
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
})
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
|
||||
}
|
||||
|
||||
private void createPanel(Collection<LootRecordCustom> records)
|
||||
{
|
||||
GridBagConstraints c = SelectionPanel.constrains();
|
||||
|
||||
// Create necessary helpers for the unique toggles
|
||||
final Map<UniqueItemPrepared, Integer> uniqueQtys = new HashMap<>();
|
||||
final Set<Integer> uniqueIds = new HashSet<>();
|
||||
|
||||
long totalValue = 0;
|
||||
long totalHaValue = 0;
|
||||
|
||||
// Loop over all UniqueItems and check how many the player has received as a drop for each
|
||||
// Also add all Item IDs for uniques to a Set for easy hiding later on.
|
||||
for (Collection<UniqueItemPrepared> items : this.uniqueMap.values())
|
||||
{
|
||||
for (UniqueItemPrepared item : items)
|
||||
{
|
||||
int id = item.getUniqueItem().getItemID();
|
||||
int linkedId = item.getLinkedID();
|
||||
uniqueIds.add(id);
|
||||
uniqueIds.add(linkedId);
|
||||
|
||||
LootTrackerItemEntry entry = this.consolidated.get(id);
|
||||
LootTrackerItemEntry notedEntry = this.consolidated.get(linkedId);
|
||||
int qty = (entry == null ? 0 : entry.getQuantity()) + (notedEntry == null ? 0 : notedEntry.getQuantity());
|
||||
if (qty > 0)
|
||||
{
|
||||
totalValue += itemManager.getItemPrice(id);
|
||||
totalHaValue += itemManager.getAlchValue(id);
|
||||
|
||||
uniqueQtys.put(item, qty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attach all the Unique Items first
|
||||
this.uniqueMap.forEach((setPosition, set) ->
|
||||
{
|
||||
UniqueItemPanel p = new UniqueItemPanel(set, uniqueQtys, this.itemManager);
|
||||
this.add(p, c);
|
||||
c.gridy++;
|
||||
|
||||
});
|
||||
|
||||
// Attach Kill Count Panel(s)
|
||||
if (records.size() > 0)
|
||||
{
|
||||
int amount = records.size();
|
||||
LootRecordCustom entry = Iterators.get(records.iterator(), (amount - 1));
|
||||
if (entry.getKillCount() != -1)
|
||||
{
|
||||
TextPanel p = new TextPanel("Current Killcount:", entry.getKillCount());
|
||||
this.add(p, c);
|
||||
c.gridy++;
|
||||
}
|
||||
TextPanel p2 = new TextPanel("Kills Logged:", amount);
|
||||
this.add(p2, c);
|
||||
c.gridy++;
|
||||
}
|
||||
|
||||
int totalValueIndex = c.gridy;
|
||||
c.gridy += 2;
|
||||
|
||||
|
||||
Collection<LootTrackerItemEntry> itemsToDisplay = new ArrayList<>();
|
||||
ArrayList<LootTrackerItemEntry> items = LootTrackerBox.dedupeClues(new ArrayList<>(consolidated.values()));
|
||||
for (LootTrackerItemEntry item : items)
|
||||
{
|
||||
totalValue += item.getTotal();
|
||||
totalHaValue += item.getHaTotal();
|
||||
|
||||
if (hideUniques && uniqueIds.contains(item.getId()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemBreakdown)
|
||||
{
|
||||
ItemPanel p = new ItemPanel(item, itemManager);
|
||||
this.add(p, c);
|
||||
c.gridy++;
|
||||
}
|
||||
else
|
||||
{
|
||||
itemsToDisplay.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (itemsToDisplay.size() > 0)
|
||||
{
|
||||
LootGrid grid = new LootGrid(itemsToDisplay.toArray(new LootTrackerItemEntry[0]), itemManager);
|
||||
this.add(grid, c);
|
||||
c.gridy++;
|
||||
}
|
||||
|
||||
// Only add the total value element if it has something useful to display
|
||||
if (totalValue > 0)
|
||||
{
|
||||
c.gridy = totalValueIndex;
|
||||
TextPanel totalPanel = new TextPanel("Total Value:", totalValue);
|
||||
this.add(totalPanel, c);
|
||||
}
|
||||
|
||||
if (totalHaValue > 0)
|
||||
{
|
||||
c.gridy = totalValueIndex + 1;
|
||||
TextPanel totalHaPanel = new TextPanel("Total HA Value:", totalHaValue);
|
||||
this.add(totalHaPanel, c);
|
||||
}
|
||||
}
|
||||
|
||||
//void addedRecord(LootRecordCustom record)
|
||||
void addedRecord()
|
||||
{
|
||||
//records.add(record);
|
||||
// TODO: Smarter update system so it only repaints necessary Item and Text Panels
|
||||
this.removeAll();
|
||||
|
||||
this.createConsolidatedArray(this.records);
|
||||
this.createPanel(this.records);
|
||||
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
void playback()
|
||||
{
|
||||
playbackPlaying = true;
|
||||
|
||||
if (this.records.size() > 0)
|
||||
{
|
||||
Collection<LootRecordCustom> recs = new ArrayList<>();
|
||||
for (LootRecordCustom r : this.records)
|
||||
{
|
||||
recs.add(r);
|
||||
|
||||
SwingUtilities.invokeLater(() -> refreshPlayback(recs));
|
||||
|
||||
try
|
||||
{
|
||||
if (cancelPlayback)
|
||||
{
|
||||
playbackPlaying = false;
|
||||
cancelPlayback = false;
|
||||
SwingUtilities.invokeLater(() -> refreshPlayback(this.records));
|
||||
break;
|
||||
}
|
||||
Thread.sleep(250);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
playbackPlaying = false;
|
||||
}
|
||||
|
||||
void cancelPlayback()
|
||||
{
|
||||
// Only cancel if actually playing
|
||||
cancelPlayback = playbackPlaying;
|
||||
}
|
||||
|
||||
private void refreshPlayback(Collection<LootRecordCustom> recs)
|
||||
{
|
||||
this.removeAll();
|
||||
|
||||
this.createConsolidatedArray(recs);
|
||||
this.createPanel(recs);
|
||||
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Psikoi <https://github.com/psikoi>
|
||||
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package net.runelite.client.plugins.stonedloottracker.ui;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.GridLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootTrackerItemEntry;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Getter
|
||||
class LootTrackerBox extends JPanel
|
||||
{
|
||||
private static final int ITEMS_PER_ROW = 5;
|
||||
private final JPanel itemContainer = new JPanel();
|
||||
private final JLabel priceLabel = new JLabel();
|
||||
private final JLabel subTitleLabel = new JLabel();
|
||||
private final ItemManager itemManager;
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private final String id;
|
||||
|
||||
@Getter
|
||||
private final List<LootRecordCustom> records = new ArrayList<>();
|
||||
|
||||
private long totalPrice;
|
||||
private long totalHaPrice;
|
||||
|
||||
LootTrackerBox(final ItemManager itemManager, final String id, @Nullable final String subtitle, LootRecordCustom record)
|
||||
{
|
||||
this.id = id;
|
||||
this.itemManager = itemManager;
|
||||
this.records.add(record);
|
||||
|
||||
setLayout(new BorderLayout(0, 1));
|
||||
setBorder(new EmptyBorder(5, 0, 0, 0));
|
||||
|
||||
final JPanel logTitle = new JPanel(new BorderLayout(5, 0));
|
||||
logTitle.setBorder(new EmptyBorder(7, 7, 7, 7));
|
||||
logTitle.setBackground(ColorScheme.DARKER_GRAY_COLOR.darker());
|
||||
|
||||
final JLabel titleLabel = new JLabel(Text.removeTags(id));
|
||||
titleLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||
titleLabel.setForeground(Color.WHITE);
|
||||
|
||||
logTitle.add(titleLabel, BorderLayout.WEST);
|
||||
|
||||
subTitleLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||
subTitleLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
logTitle.add(subTitleLabel, BorderLayout.CENTER);
|
||||
|
||||
if (!Strings.isNullOrEmpty(subtitle))
|
||||
{
|
||||
subTitleLabel.setText(subtitle);
|
||||
}
|
||||
|
||||
priceLabel.setFont(FontManager.getRunescapeSmallFont());
|
||||
priceLabel.setForeground(ColorScheme.LIGHT_GRAY_COLOR);
|
||||
logTitle.add(priceLabel, BorderLayout.EAST);
|
||||
|
||||
add(logTitle, BorderLayout.NORTH);
|
||||
add(itemContainer, BorderLayout.CENTER);
|
||||
|
||||
buildItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates stacked items from the item list, calculates total price and then
|
||||
* displays all the items in the UI.
|
||||
*/
|
||||
private void buildItems()
|
||||
{
|
||||
final List<LootTrackerItemEntry> allItems = new ArrayList<>();
|
||||
final List<LootTrackerItemEntry> items = new ArrayList<>();
|
||||
totalPrice = 0;
|
||||
totalHaPrice = 0;
|
||||
|
||||
for (LootRecordCustom record : records)
|
||||
{
|
||||
allItems.addAll(record.getDrops());
|
||||
}
|
||||
|
||||
for (final LootTrackerItemEntry entry : dedupeClues(allItems))
|
||||
{
|
||||
totalPrice += (entry.getPrice() * entry.getQuantity());
|
||||
totalHaPrice += (entry.getHaPrice() * entry.getQuantity());
|
||||
|
||||
int quantity = 0;
|
||||
for (final LootTrackerItemEntry i : items)
|
||||
{
|
||||
if (i.getId() == entry.getId())
|
||||
{
|
||||
quantity = i.getQuantity();
|
||||
items.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (quantity > 0)
|
||||
{
|
||||
int newQuantity = entry.getQuantity() + quantity;
|
||||
long pricePerItem = entry.getPrice();
|
||||
long haPricePerItem = entry.getHaPrice();
|
||||
|
||||
items.add(new LootTrackerItemEntry(entry.getName(), entry.getId(), newQuantity, pricePerItem, haPricePerItem, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
items.sort((i1, i2) -> Long.compare(i2.getPrice(), i1.getPrice()));
|
||||
|
||||
// Calculates how many rows need to be display to fit all items
|
||||
final int rowSize = rowSize(items.size());
|
||||
|
||||
resetContainer(itemContainer, rowSize);
|
||||
|
||||
for (int i = 0; i < rowSize * ITEMS_PER_ROW; i++)
|
||||
{
|
||||
final JPanel slotContainer = new JPanel();
|
||||
slotContainer.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
|
||||
if (i < items.size())
|
||||
{
|
||||
final LootTrackerItemEntry item = items.get(i);
|
||||
final JLabel imageLabel = buildimageLabel(itemManager, item);
|
||||
slotContainer.add(imageLabel);
|
||||
}
|
||||
|
||||
itemContainer.add(slotContainer);
|
||||
}
|
||||
|
||||
itemContainer.repaint();
|
||||
|
||||
priceLabel.setText(StackFormatter.quantityToStackSize(totalPrice) + " gp (HA: " + StackFormatter.quantityToStackSize(totalHaPrice) + ")");
|
||||
priceLabel.setToolTipText(StackFormatter.formatNumber(totalPrice) + " gp (HA: " + StackFormatter.formatNumber(totalHaPrice) + ")");
|
||||
if (records.size() > 1)
|
||||
{
|
||||
subTitleLabel.setText("x " + records.size());
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
static ArrayList<LootTrackerItemEntry> dedupeClues(List<LootTrackerItemEntry> items)
|
||||
{
|
||||
final ArrayList<LootTrackerItemEntry> newItems = new ArrayList<>();
|
||||
|
||||
int eliteClues = 0;
|
||||
int hardClues = 0;
|
||||
int mediumClues = 0;
|
||||
int easyClues = 0;
|
||||
int beginnerClues = 0;
|
||||
|
||||
LootTrackerItemEntry eliteClue = null;
|
||||
LootTrackerItemEntry hardClue = null;
|
||||
LootTrackerItemEntry mediumClue = null;
|
||||
LootTrackerItemEntry easyClue = null;
|
||||
LootTrackerItemEntry beginnerClue = null;
|
||||
|
||||
for (LootTrackerItemEntry lootEntry : items)
|
||||
{
|
||||
if (lootEntry == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
String name = lootEntry.getName();
|
||||
|
||||
if (lootEntry.getName().contains("Clue scroll ("))
|
||||
{
|
||||
if (name.contains("elite"))
|
||||
{
|
||||
eliteClues += lootEntry.getQuantity();
|
||||
eliteClue = lootEntry;
|
||||
}
|
||||
else if (name.contains("hard"))
|
||||
{
|
||||
hardClues += lootEntry.getQuantity();
|
||||
hardClue = lootEntry;
|
||||
}
|
||||
else if (name.contains("medium"))
|
||||
{
|
||||
mediumClues += lootEntry.getQuantity();
|
||||
mediumClue = lootEntry;
|
||||
}
|
||||
else if (name.contains("easy"))
|
||||
{
|
||||
easyClues += lootEntry.getQuantity();
|
||||
easyClue = lootEntry;
|
||||
}
|
||||
else if (name.contains("beginner"))
|
||||
{
|
||||
beginnerClues += lootEntry.getQuantity();
|
||||
beginnerClue = lootEntry;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
newItems.add(lootEntry);
|
||||
}
|
||||
|
||||
LootTrackerItemEntry[] clueArray = {beginnerClue, easyClue, mediumClue, hardClue, eliteClue};
|
||||
int[] clueAmountArray = {beginnerClues, easyClues, mediumClues, hardClues, eliteClues};
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (clueAmountArray[i] > 0)
|
||||
{
|
||||
newItems.add(createNewLootEntry(Objects.requireNonNull(clueArray[i]), clueAmountArray[i]));
|
||||
}
|
||||
}
|
||||
|
||||
return newItems;
|
||||
}
|
||||
|
||||
private static LootTrackerItemEntry createNewLootEntry(LootTrackerItemEntry item, int amount)
|
||||
{
|
||||
return new LootTrackerItemEntry(
|
||||
item.getName(),
|
||||
item.getId(),
|
||||
amount,
|
||||
item.getPrice(),
|
||||
item.getHaPrice(),
|
||||
item.isStackable()
|
||||
);
|
||||
}
|
||||
|
||||
static int rowSize(int items)
|
||||
{
|
||||
return ((items % ITEMS_PER_ROW == 0) ? 0 : 1) + items / ITEMS_PER_ROW;
|
||||
}
|
||||
|
||||
private static void resetContainer(JPanel itemContainer, int rowSize)
|
||||
{
|
||||
itemContainer.removeAll();
|
||||
itemContainer.setLayout(new GridLayout(rowSize, ITEMS_PER_ROW, 1, 1));
|
||||
}
|
||||
|
||||
private static JLabel buildimageLabel(ItemManager itemManager, LootTrackerItemEntry item)
|
||||
{
|
||||
final JLabel imageLabel = new JLabel();
|
||||
imageLabel.setToolTipText(UniqueItemPanel.tooltipText(item.getPrice(), item.getHaPrice(), item.getQuantity(), item.getName()));
|
||||
imageLabel.setVerticalAlignment(SwingConstants.CENTER);
|
||||
imageLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
itemManager.getImage(item.getId(), item.getQuantity(), item.getQuantity() > 1).addTo(imageLabel);
|
||||
|
||||
return imageLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.MatteBorder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.stonedloottracker.StonedLootTrackerPlugin;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.LootRecordCustom;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.UniqueItem;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.UniqueItemPrepared;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.PluginPanel;
|
||||
import net.runelite.client.ui.components.PluginErrorPanel;
|
||||
|
||||
@Slf4j
|
||||
public class LootTrackerPanel extends PluginPanel
|
||||
{
|
||||
private static final BufferedImage ICON_DELETE;
|
||||
private static final BufferedImage ICON_REFRESH;
|
||||
private static final BufferedImage ICON_BACK;
|
||||
private static final BufferedImage ICON_REPLAY;
|
||||
|
||||
private final static Color BACKGROUND_COLOR = ColorScheme.DARK_GRAY_COLOR;
|
||||
private final static Color BUTTON_HOVER_COLOR = ColorScheme.DARKER_GRAY_HOVER_COLOR;
|
||||
|
||||
static
|
||||
{
|
||||
BufferedImage i1;
|
||||
BufferedImage i2;
|
||||
BufferedImage i3;
|
||||
BufferedImage i4;
|
||||
try
|
||||
{
|
||||
synchronized (ImageIO.class)
|
||||
{
|
||||
i1 = ImageIO.read(StonedLootTrackerPlugin.class.getResourceAsStream("delete-white.png"));
|
||||
i2 = ImageIO.read(StonedLootTrackerPlugin.class.getResourceAsStream("refresh-white.png"));
|
||||
i3 = ImageIO.read(StonedLootTrackerPlugin.class.getResourceAsStream("back-arrow-white.png"));
|
||||
i4 = ImageIO.read(StonedLootTrackerPlugin.class.getResourceAsStream("replay-white.png"));
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
ICON_DELETE = i1;
|
||||
ICON_REFRESH = i2;
|
||||
ICON_BACK = i3;
|
||||
ICON_REPLAY = i4;
|
||||
}
|
||||
|
||||
// NPC name for current view or null if on selection screen
|
||||
private String currentView = null;
|
||||
private LootPanel lootPanel;
|
||||
|
||||
private final ItemManager itemManager;
|
||||
private final StonedLootTrackerPlugin plugin;
|
||||
|
||||
public LootTrackerPanel(final ItemManager itemManager, StonedLootTrackerPlugin plugin)
|
||||
{
|
||||
super(false);
|
||||
this.itemManager = itemManager;
|
||||
this.plugin = plugin;
|
||||
|
||||
this.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
showSelectionView();
|
||||
}
|
||||
|
||||
// Loot Selection view
|
||||
private void showSelectionView()
|
||||
{
|
||||
this.removeAll();
|
||||
currentView = null;
|
||||
lootPanel = null;
|
||||
|
||||
PluginErrorPanel errorPanel = new PluginErrorPanel();
|
||||
errorPanel.setBorder(new EmptyBorder(10, 25, 10, 25));
|
||||
errorPanel.setContent("Stoned Loot Tracker", "Please select the Activity, Player, or NPC you wish to view loot for");
|
||||
|
||||
SelectionPanel selection = new SelectionPanel(plugin.config.bossButtons(), plugin.getNames(), this, itemManager);
|
||||
|
||||
this.add(errorPanel, BorderLayout.NORTH);
|
||||
this.add(wrapContainer(selection), BorderLayout.CENTER);
|
||||
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
// Loot breakdown view
|
||||
void showLootView(String name)
|
||||
{
|
||||
this.removeAll();
|
||||
currentView = name;
|
||||
|
||||
Collection<LootRecordCustom> data = plugin.getDataByName(name);
|
||||
|
||||
// Grab all Uniques for this NPC/Activity
|
||||
Collection<UniqueItemPrepared> uniques = plugin.getUniques(name);
|
||||
if (uniques == null)
|
||||
{
|
||||
uniques = new ArrayList<>();
|
||||
}
|
||||
|
||||
JPanel title = createLootViewTitle(name);
|
||||
lootPanel = new LootPanel(data, UniqueItem.createPositionSetMap(uniques), plugin.config.hideUniques(), plugin.config.itemSortType(), plugin.config.itemBreakdown(), itemManager);
|
||||
|
||||
this.add(title, BorderLayout.NORTH);
|
||||
this.add(wrapContainer(lootPanel), BorderLayout.CENTER);
|
||||
|
||||
this.revalidate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
private LootTrackerBox createLootTrackerBox(LootRecordCustom r)
|
||||
{
|
||||
final String subTitle = r.getLevel() > -1 ? "(lvl-" + r.getLevel() + ")" : "";
|
||||
return new LootTrackerBox(itemManager, r.getName(), subTitle, r);
|
||||
}
|
||||
|
||||
// Title element for Loot breakdown view
|
||||
private JPanel createLootViewTitle(String name)
|
||||
{
|
||||
JPanel title = new JPanel();
|
||||
title.setBorder(new CompoundBorder(
|
||||
new EmptyBorder(10, 8, 8, 8),
|
||||
new MatteBorder(0, 0, 1, 0, Color.GRAY)
|
||||
));
|
||||
title.setLayout(new BorderLayout());
|
||||
title.setBackground(BACKGROUND_COLOR);
|
||||
|
||||
JPanel first = new JPanel();
|
||||
first.setBackground(BACKGROUND_COLOR);
|
||||
|
||||
// Back Button
|
||||
JLabel back = createIconLabel(ICON_BACK);
|
||||
back.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
showSelectionView();
|
||||
}
|
||||
});
|
||||
|
||||
// Plugin Name
|
||||
JLabel text = new JLabel(name);
|
||||
text.setForeground(Color.WHITE);
|
||||
|
||||
first.add(back);
|
||||
first.add(text);
|
||||
|
||||
JPanel second = new JPanel();
|
||||
second.setBackground(BACKGROUND_COLOR);
|
||||
|
||||
// Refresh Data button
|
||||
JLabel refresh = createIconLabel(ICON_REFRESH);
|
||||
refresh.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
refreshLootView(name);
|
||||
}
|
||||
});
|
||||
refresh.setToolTipText("Refresh panel");
|
||||
|
||||
// Clear data button
|
||||
JLabel clear = createIconLabel(ICON_DELETE);
|
||||
clear.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
clearData(name);
|
||||
}
|
||||
});
|
||||
clear.setToolTipText("Clear stored data");
|
||||
|
||||
// Clear data button
|
||||
JLabel replay = createIconLabel(ICON_REPLAY);
|
||||
replay.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
playbackLoot();
|
||||
}
|
||||
});
|
||||
replay.setToolTipText("Replay Loot");
|
||||
|
||||
second.add(refresh);
|
||||
second.add(clear);
|
||||
second.add(replay);
|
||||
|
||||
title.add(first, BorderLayout.WEST);
|
||||
title.add(second, BorderLayout.EAST);
|
||||
|
||||
return title;
|
||||
}
|
||||
|
||||
private JLabel createIconLabel(BufferedImage icon)
|
||||
{
|
||||
JLabel label = new JLabel();
|
||||
label.setIcon(new ImageIcon(icon));
|
||||
label.setOpaque(true);
|
||||
label.setBackground(BACKGROUND_COLOR);
|
||||
|
||||
label.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
label.setBackground(BUTTON_HOVER_COLOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
label.setBackground(BACKGROUND_COLOR);
|
||||
}
|
||||
});
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
// Wrap the panel inside a scroll pane
|
||||
private JScrollPane wrapContainer(JPanel container)
|
||||
{
|
||||
JPanel wrapped = new JPanel(new BorderLayout());
|
||||
wrapped.add(container, BorderLayout.NORTH);
|
||||
wrapped.setBackground(BACKGROUND_COLOR);
|
||||
|
||||
JScrollPane scroller = new JScrollPane(wrapped);
|
||||
scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
scroller.getVerticalScrollBar().setPreferredSize(new Dimension(8, 0));
|
||||
scroller.setBackground(BACKGROUND_COLOR);
|
||||
|
||||
return scroller;
|
||||
}
|
||||
|
||||
// Clear stored data and return to selection screen
|
||||
private void clearData(String name)
|
||||
{
|
||||
// Confirm delete action
|
||||
int delete = JOptionPane.showConfirmDialog(this.getRootPane(), "<html>Are you sure you want to clear all data for this tab?<br/>There is no way to undo this action.</html>", "Warning", JOptionPane.YES_NO_OPTION);
|
||||
if (delete == JOptionPane.YES_OPTION)
|
||||
{
|
||||
plugin.clearStoredDataByName(name);
|
||||
|
||||
// Return to selection screen
|
||||
showSelectionView();
|
||||
}
|
||||
}
|
||||
|
||||
public void addLog(LootRecordCustom r)
|
||||
{
|
||||
if (currentView == null)
|
||||
{
|
||||
showLootView(r.getName());
|
||||
}
|
||||
else if (currentView.equals(r.getName()))
|
||||
{
|
||||
//lootPanel.addedRecord(r);
|
||||
lootPanel.addedRecord();
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh panel when writer playerFolder is updated
|
||||
public void updateNames()
|
||||
{
|
||||
if (currentView == null)
|
||||
{
|
||||
showSelectionView();
|
||||
}
|
||||
else
|
||||
{
|
||||
showLootView(currentView);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh panel when config options are changed
|
||||
public void refreshUI()
|
||||
{
|
||||
log.debug("Refreshing UI");
|
||||
if (currentView == null)
|
||||
{
|
||||
showSelectionView();
|
||||
}
|
||||
else
|
||||
{
|
||||
showLootView(currentView);
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshLootView(String name)
|
||||
{
|
||||
plugin.refreshDataByName(name);
|
||||
showLootView(name); // Recreate the entire panel
|
||||
}
|
||||
|
||||
private void playbackLoot()
|
||||
{
|
||||
if (lootPanel == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (lootPanel.isPlaybackPlaying())
|
||||
{
|
||||
lootPanel.cancelPlayback();
|
||||
return;
|
||||
}
|
||||
|
||||
ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();
|
||||
if (currentView != null)
|
||||
{
|
||||
ex.schedule(lootPanel::playback, 0, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Image;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import net.runelite.client.game.AsyncBufferedImage;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.BossTab;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.components.materialtabs.MaterialTab;
|
||||
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
||||
|
||||
public class SelectionPanel extends JPanel
|
||||
{
|
||||
private TreeSet<String> names;
|
||||
private LootTrackerPanel parent;
|
||||
private ItemManager itemManager;
|
||||
|
||||
private final static Color BACKGROUND_COLOR = ColorScheme.DARK_GRAY_COLOR;
|
||||
private final static Color BUTTON_COLOR = ColorScheme.DARKER_GRAY_COLOR;
|
||||
private final static Color BUTTON_HOVER_COLOR = ColorScheme.DARKER_GRAY_HOVER_COLOR;
|
||||
|
||||
private boolean configToggle;
|
||||
|
||||
SelectionPanel(boolean configToggle, TreeSet<String> names, LootTrackerPanel parent, ItemManager itemManager)
|
||||
{
|
||||
this.names = names == null ? new TreeSet<>() : names;
|
||||
this.parent = parent;
|
||||
this.itemManager = itemManager;
|
||||
this.configToggle = configToggle;
|
||||
|
||||
this.setLayout(new GridBagLayout());
|
||||
this.setBackground(BACKGROUND_COLOR);
|
||||
|
||||
createPanel();
|
||||
}
|
||||
|
||||
private void createPanel()
|
||||
{
|
||||
GridBagConstraints c = constrains();
|
||||
c.insets = new Insets(5, 0, 0, 0);
|
||||
|
||||
// Add the bosses tabs, by category, to tabGroup
|
||||
if (configToggle)
|
||||
{
|
||||
Set<String> categories = BossTab.categories;
|
||||
JPanel container = new JPanel(new GridBagLayout());
|
||||
container.setBorder(new EmptyBorder(0, 0, 10, 0));
|
||||
int oldc = c.gridy;
|
||||
c.gridy = 0;
|
||||
for (String categoryName : categories)
|
||||
{
|
||||
container.add(createTabCategory(categoryName), c);
|
||||
c.gridy++;
|
||||
}
|
||||
c.gridy = oldc;
|
||||
this.add(container, c);
|
||||
c.gridy++;
|
||||
}
|
||||
|
||||
// Add all other names
|
||||
for (String name : this.names)
|
||||
{
|
||||
if (!configToggle || BossTab.getByName(name) == null)
|
||||
{
|
||||
this.add(createNamePanel(name), c);
|
||||
c.gridy++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JPanel createNamePanel(String name)
|
||||
{
|
||||
JPanel p = new JPanel();
|
||||
p.add(new JLabel(name));
|
||||
p.setBackground(BUTTON_COLOR);
|
||||
p.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
p.setBackground(BUTTON_HOVER_COLOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
p.setBackground(BUTTON_COLOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> parent.showLootView(name));
|
||||
}
|
||||
});
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static GridBagConstraints constrains()
|
||||
{
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
// Creates all tabs for a specific category
|
||||
private JPanel createTabCategory(String categoryName)
|
||||
{
|
||||
JPanel container = new JPanel();
|
||||
container.setLayout(new GridBagLayout());
|
||||
container.setBorder(new EmptyBorder(0, 5, 0, 5));
|
||||
|
||||
GridBagConstraints c = constrains();
|
||||
|
||||
MaterialTabGroup thisTabGroup = new MaterialTabGroup();
|
||||
thisTabGroup.setLayout(new GridLayout(0, 4, 7, 7));
|
||||
thisTabGroup.setBorder(new EmptyBorder(4, 0, 0, 0));
|
||||
|
||||
JLabel name = new JLabel(categoryName);
|
||||
name.setBorder(new EmptyBorder(8, 0, 0, 0));
|
||||
name.setForeground(Color.WHITE);
|
||||
name.setVerticalAlignment(SwingConstants.CENTER);
|
||||
|
||||
ArrayList<BossTab> categoryTabs = BossTab.getByCategoryName(categoryName);
|
||||
for (BossTab tab : categoryTabs)
|
||||
{
|
||||
// Create tab (with hover effects/text)
|
||||
MaterialTab materialTab = new MaterialTab("", thisTabGroup, null);
|
||||
materialTab.setName(tab.getName());
|
||||
materialTab.setToolTipText(tab.getName());
|
||||
//materialTab.setSelectedBorder(new EmptyBorder(0, 0, 0, 0));
|
||||
materialTab.addMouseListener(new MouseAdapter()
|
||||
{
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e)
|
||||
{
|
||||
materialTab.setBackground(BUTTON_HOVER_COLOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e)
|
||||
{
|
||||
materialTab.setBackground(BUTTON_COLOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e)
|
||||
{
|
||||
SwingUtilities.invokeLater(() -> parent.showLootView(tab.getName()));
|
||||
}
|
||||
});
|
||||
|
||||
// Attach Icon to the Tab
|
||||
AsyncBufferedImage image = itemManager.getImage(tab.getItemID());
|
||||
Runnable resize = () ->
|
||||
{
|
||||
materialTab.setIcon(new ImageIcon(image.getScaledInstance(35, 35, Image.SCALE_SMOOTH)));
|
||||
materialTab.setOpaque(true);
|
||||
materialTab.setBackground(BUTTON_COLOR);
|
||||
materialTab.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
materialTab.setVerticalAlignment(SwingConstants.CENTER);
|
||||
materialTab.setPreferredSize(new Dimension(35, 35));
|
||||
};
|
||||
image.onChanged(resize);
|
||||
resize.run();
|
||||
|
||||
thisTabGroup.addTab(materialTab);
|
||||
}
|
||||
|
||||
container.add(name, c);
|
||||
c.gridy++;
|
||||
container.add(thisTabGroup, c);
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <www.github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
|
||||
@Getter
|
||||
class TextPanel extends JPanel
|
||||
{
|
||||
private static final GridBagLayout LAYOUT = new GridBagLayout();
|
||||
|
||||
private static final Border PANEL_BORDER = BorderFactory.createMatteBorder(3, 0, 3, 0, ColorScheme.DARK_GRAY_COLOR);
|
||||
private static final Color PANEL_BACKGROUND_COLOR = ColorScheme.DARKER_GRAY_COLOR;
|
||||
|
||||
private static final Border CONTAINER_BORDER = BorderFactory.createMatteBorder(0, 15, 0, 15, PANEL_BACKGROUND_COLOR);
|
||||
|
||||
// Long value should be for Total Value
|
||||
TextPanel(String text, long totalValue)
|
||||
{
|
||||
this.setLayout(LAYOUT);
|
||||
this.setBorder(PANEL_BORDER);
|
||||
this.setBackground(PANEL_BACKGROUND_COLOR);
|
||||
|
||||
JLabel totalText = new JLabel(text, SwingConstants.LEFT);
|
||||
totalText.setForeground(Color.WHITE);
|
||||
|
||||
// Item Values (Colored off Total Value of item)
|
||||
JLabel total = new JLabel(StackFormatter.quantityToStackSize(totalValue) + " gp", SwingConstants.LEFT);
|
||||
total.setBorder(new EmptyBorder(0, 5, 0, 0));
|
||||
colorLabel(total, totalValue);
|
||||
|
||||
JPanel panel = ItemPanel.createPanel();
|
||||
|
||||
panel.add(totalText, BorderLayout.LINE_START);
|
||||
panel.add(total, BorderLayout.CENTER);
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 1;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.ipady = 20;
|
||||
|
||||
panel.setToolTipText(StackFormatter.formatNumber(totalValue));
|
||||
|
||||
this.add(panel, c);
|
||||
}
|
||||
|
||||
TextPanel(String text, int value)
|
||||
{
|
||||
this.setLayout(LAYOUT);
|
||||
this.setBorder(PANEL_BORDER);
|
||||
this.setBackground(PANEL_BACKGROUND_COLOR);
|
||||
|
||||
JLabel textLabel = new JLabel(text, SwingConstants.LEFT);
|
||||
textLabel.setForeground(Color.WHITE);
|
||||
|
||||
JLabel valueLabel = new JLabel(String.valueOf(value), SwingConstants.LEFT);
|
||||
valueLabel.setBorder(new EmptyBorder(0, 5, 0, 0));
|
||||
|
||||
JPanel panel = ItemPanel.createPanel();
|
||||
panel.add(textLabel, BorderLayout.LINE_START);
|
||||
panel.add(valueLabel, BorderLayout.CENTER);
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 1;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.ipady = 20;
|
||||
|
||||
this.add(panel, c);
|
||||
}
|
||||
|
||||
// Color label to match RuneScape coloring
|
||||
private void colorLabel(JLabel label, long val)
|
||||
{
|
||||
Color labelColor = (val >= 10000000) ? Color.GREEN : (val >= 100000) ? Color.WHITE : Color.YELLOW;
|
||||
label.setForeground(labelColor);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2018, TheStonedTurtle <www.github.com/TheStonedTurtle>
|
||||
* 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.stonedloottracker.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import lombok.Getter;
|
||||
import net.runelite.client.game.AsyncBufferedImage;
|
||||
import net.runelite.client.game.ItemManager;
|
||||
import net.runelite.client.plugins.stonedloottracker.data.UniqueItemPrepared;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.util.ImageUtil;
|
||||
import net.runelite.client.util.StackFormatter;
|
||||
|
||||
@Getter
|
||||
class UniqueItemPanel extends JPanel
|
||||
{
|
||||
private ItemManager itemManager;
|
||||
|
||||
private final float alphaMissing = 0.35f;
|
||||
private final float alphaHas = 1.0f;
|
||||
|
||||
private static final Dimension panelSize = new Dimension(215, 50);
|
||||
private static final Border panelBorder = new EmptyBorder(3, 0, 3, 0);
|
||||
private static final Color panelBackgroundColor = ColorScheme.DARK_GRAY_COLOR;
|
||||
|
||||
UniqueItemPanel(Collection<UniqueItemPrepared> items, Map<UniqueItemPrepared, Integer> uniqueMap, ItemManager itemManager)
|
||||
{
|
||||
this.itemManager = itemManager;
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.setLayout(new GridBagLayout());
|
||||
panel.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||
panel.setBorder(new EmptyBorder(3, 0, 3, 0));
|
||||
|
||||
this.setLayout(new BorderLayout());
|
||||
this.setBorder(panelBorder);
|
||||
this.setBackground(panelBackgroundColor);
|
||||
this.setPreferredSize(panelSize);
|
||||
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.fill = GridBagConstraints.BOTH;
|
||||
c.weightx = 1;
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
c.ipady = 5;
|
||||
|
||||
// Add each Unique Item icon to the panel
|
||||
for (UniqueItemPrepared l : items)
|
||||
{
|
||||
final int id = l.getUniqueItem().getItemID();
|
||||
final int quantity = uniqueMap.getOrDefault(l, 0);
|
||||
final float alpha = (quantity > 0 ? alphaHas : alphaMissing);
|
||||
AsyncBufferedImage image = itemManager.getImage(l.getUniqueItem().getItemID(), quantity, quantity > 1);
|
||||
BufferedImage opaque = ImageUtil.alphaOffset(image, alpha);
|
||||
|
||||
final long price = itemManager.getItemPrice(id);
|
||||
final long haPrice = itemManager.getAlchValue(id);
|
||||
|
||||
// Attach Image to Label and append label to Panel
|
||||
ImageIcon o = new ImageIcon(opaque);
|
||||
JLabel icon = new JLabel(o);
|
||||
panel.add(icon, c);
|
||||
c.gridx++;
|
||||
|
||||
// in case the image is blank we will refresh it upon load
|
||||
// Should only trigger if image hasn't been added
|
||||
image.onChanged(() -> SwingUtilities.invokeLater(() -> refreshImage(icon, image, alpha)));
|
||||
|
||||
icon.setToolTipText(tooltipText(price, haPrice, quantity, l.getUniqueItem().getName()));
|
||||
}
|
||||
|
||||
this.add(panel, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
static String tooltipText(long price, long haPrice, int quantity, String name)
|
||||
{
|
||||
String tooltipText = "<html>" + name;
|
||||
if (quantity > 1)
|
||||
{
|
||||
tooltipText += "<br/>Price: " + StackFormatter.quantityToStackSize(price);
|
||||
|
||||
if (haPrice > 0)
|
||||
{
|
||||
tooltipText += " (HA: " + StackFormatter.quantityToStackSize(haPrice) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
if (quantity > 0)
|
||||
{
|
||||
tooltipText += "<br/>Total: " + StackFormatter.quantityToStackSize(quantity * price);
|
||||
|
||||
if (haPrice > 0)
|
||||
{
|
||||
tooltipText += " (HA: " + StackFormatter.quantityToStackSize(quantity * haPrice) + ")";
|
||||
}
|
||||
}
|
||||
tooltipText += "</html";
|
||||
|
||||
return tooltipText;
|
||||
}
|
||||
|
||||
// Used to refresh the item icon if the image was still loading when attempting to create it earlier
|
||||
private void refreshImage(JLabel label, AsyncBufferedImage image, float finalAlpha)
|
||||
{
|
||||
BufferedImage opaque = ImageUtil.alphaOffset(image, finalAlpha);
|
||||
ImageIcon o = new ImageIcon(opaque);
|
||||
|
||||
label.setIcon(o);
|
||||
label.revalidate();
|
||||
label.repaint();
|
||||
}
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.plugins.Plugin;
|
||||
import net.runelite.client.plugins.PluginDescriptor;
|
||||
import net.runelite.client.plugins.PluginType;
|
||||
import net.runelite.client.plugins.zulrah.overlays.ZulrahCurrentPhaseOverlay;
|
||||
import net.runelite.client.plugins.zulrah.overlays.ZulrahNextPhaseOverlay;
|
||||
import net.runelite.client.plugins.zulrah.overlays.ZulrahOverlay;
|
||||
@@ -55,7 +56,8 @@ import net.runelite.client.ui.overlay.OverlayManager;
|
||||
@PluginDescriptor(
|
||||
name = "Zulrah",
|
||||
description = "Overlays to assist with killing Zulrah",
|
||||
tags = {"zulrah", "boss", "helper"}
|
||||
tags = {"zulrah", "boss", "helper"},
|
||||
type = PluginType.PVM
|
||||
)
|
||||
|
||||
@Slf4j
|
||||
|
||||
Reference in New Issue
Block a user