Repository: runelite/runelite
Pull request #18239 (2024-09-06 03:42:34)

Add blurite bar to item identification
Added blurite bar into item identification

YvesW: If you're adding this, you probably also want to add e.g. lunar bar and lovakite bar.
Kashif300: > If you're adding this, you probably also want to add e.g. lunar bar and lovakite bar.
Done


Patch:
diff --git a/cache/pom.xml b/cache/pom.xml
index 76aa604a4..09a5e7f23 100644
--- a/cache/pom.xml
+++ b/cache/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>net.runelite</groupId>
 		<artifactId>runelite-parent</artifactId>
-		<version>1.10.37-SNAPSHOT</version>
+		<version>1.10.38-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>cache</artifactId>
diff --git a/pom.xml b/pom.xml
index a9def056e..8c16fb61a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,7 +28,7 @@
 
 	<groupId>net.runelite</groupId>
 	<artifactId>runelite-parent</artifactId>
-	<version>1.10.37-SNAPSHOT</version>
+	<version>1.10.38-SNAPSHOT</version>
 	<packaging>pom</packaging>
 
 	<name>RuneLite</name>
@@ -47,7 +47,7 @@
 		<checkstyle.skip>true</checkstyle.skip>
 		<glslang.path></glslang.path>
 
-		<rs.version>224</rs.version>
+		<rs.version>225</rs.version>
 	</properties>
 
 	<licenses>
diff --git a/runelite-api/pom.xml b/runelite-api/pom.xml
index 9386c6751..18de6e451 100644
--- a/runelite-api/pom.xml
+++ b/runelite-api/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>net.runelite</groupId>
 		<artifactId>runelite-parent</artifactId>
-		<version>1.10.37-SNAPSHOT</version>
+		<version>1.10.38-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>runelite-api</artifactId>
@@ -122,6 +122,7 @@
 								<exclude>net/runelite/api/ParamID.class</exclude>
 								<exclude>net/runelite/api/ScriptID.class</exclude>
 								<exclude>net/runelite/api/SettingID.class</exclude>
+								<exclude>net/runelite/api/SkullIcon.class</exclude>
 								<exclude>net/runelite/api/SoundEffectID.class</exclude>
 								<exclude>net/runelite/api/SoundEffectVolume.class</exclude>
 								<exclude>net/runelite/api/SpriteID.class</exclude>
diff --git a/runelite-api/src/main/java/net/runelite/api/ItemID.java b/runelite-api/src/main/java/net/runelite/api/ItemID.java
index e601f0e72..4fc1a6a3a 100644
--- a/runelite-api/src/main/java/net/runelite/api/ItemID.java
+++ b/runelite-api/src/main/java/net/runelite/api/ItemID.java
@@ -14185,5 +14185,18 @@ public final class ItemID
 	public static final int EXTENDED_ANTIVENOM1 = 29833;
 	public static final int NID = 29836;
 	public static final int RAX = 29838;
+	public static final int ECLIPSE_MOON_CHESTPLATE_29840 = 29840;
+	public static final int ECLIPSE_MOON_TASSETS_29841 = 29841;
+	public static final int ECLIPSE_MOON_HELM_29842 = 29842;
+	public static final int BLUE_MOON_CHESTPLATE_29843 = 29843;
+	public static final int BLUE_MOON_TASSETS_29844 = 29844;
+	public static final int BLUE_MOON_HELM_29845 = 29845;
+	public static final int BLOOD_MOON_CHESTPLATE_29846 = 29846;
+	public static final int BLOOD_MOON_TASSETS_29847 = 29847;
+	public static final int BLOOD_MOON_HELM_29848 = 29848;
+	public static final int BLUE_MOON_SPEAR_29849 = 29849;
+	public static final int DUAL_MACUAHUITL_29850 = 29850;
+	public static final int ECLIPSE_ATLATL_29851 = 29851;
+	public static final int ATLATL_DART_29852 = 29852;
 	/* This file is automatically generated. Do not edit. */
 }
diff --git a/runelite-api/src/main/java/net/runelite/api/Player.java b/runelite-api/src/main/java/net/runelite/api/Player.java
index 7837a405c..7a87b47b4 100644
--- a/runelite-api/src/main/java/net/runelite/api/Player.java
+++ b/runelite-api/src/main/java/net/runelite/api/Player.java
@@ -25,7 +25,7 @@
 package net.runelite.api;
 
 import java.awt.Polygon;
-import javax.annotation.Nullable;
+import org.intellij.lang.annotations.MagicConstant;
 
 /**
  * Represents a player entity in the game.
@@ -94,10 +94,17 @@ public interface Player extends Actor
 
 	/**
 	 * Gets the displayed skull icon of the player.
-	 * Only works on the local player.
 	 *
-	 * @return the skull icon
+	 * @return the id skull icon, or -1 if unskulled.
+	 * @see SkullIcon
 	 */
-	@Nullable
-	SkullIcon getSkullIcon();
+	@MagicConstant(valuesFromClass = SkullIcon.class)
+	int getSkullIcon();
+
+	/**
+	 * Sets the displayed skull icon of the player.
+	 * @param skullIcon The id of the skull icon, or -1 to remove the skull icon.
+	 * @see SkullIcon
+	 */
+	void setSkullIcon(@MagicConstant(valuesFromClass = SkullIcon.class) int skullIcon);
 }
diff --git a/runelite-api/src/main/java/net/runelite/api/SkullIcon.java b/runelite-api/src/main/java/net/runelite/api/SkullIcon.java
index f16cbc2ef..baa111489 100644
--- a/runelite-api/src/main/java/net/runelite/api/SkullIcon.java
+++ b/runelite-api/src/main/java/net/runelite/api/SkullIcon.java
@@ -28,34 +28,76 @@ package net.runelite.api;
 /**
  * An enumeration of PK skulls.
  */
-public enum SkullIcon
+public final class SkullIcon
 {
 	/**
 	 * White skull from PVP world or wilderness
 	 */
-	SKULL,
+	public static final int SKULL = 0;
 	/**
 	 * Red skull from Tzhaar Fight Pits
 	 */
-	SKULL_FIGHT_PIT,
+	public static final int SKULL_FIGHT_PIT = 1;
 	/**
-	 * Deadman mode sprite carrying one key
+	 * White skull used on High Risk worlds
 	 */
-	DEAD_MAN_ONE,
+	public static final int SKULL_HIGH_RISK = 2;
 	/**
-	 * Deadman mode sprite carrying two keys
+	 * Forinthry surge buff in the Revenant caves
 	 */
-	DEAD_MAN_TWO,
+	public static final int FORINTHRY_SURGE = 3;
 	/**
-	 * Deadman mode sprite carrying three keys
+	 * Grey skull used on Deadman worlds
 	 */
-	DEAD_MAN_THREE,
+	public static final int SKULL_DEADMAN = 7;
 	/**
-	 * Deadman mode sprite carrying four keys
+	 * PK skull carrying one loot key
 	 */
-	DEAD_MAN_FOUR,
+	public static final int LOOT_KEYS_ONE = 8;
 	/**
-	 * Deadman mode sprite carrying five keys
+	 * PK skull carrying two loot keys
 	 */
-	DEAD_MAN_FIVE,
+	public static final int LOOT_KEYS_TWO = 9;
+	/**
+	 * PK skull carrying two loot keys
+	 */
+	public static final int LOOT_KEYS_THREE = 10;
+	/**
+	 * PK skull carrying two loot keys
+	 */
+	public static final int LOOT_KEYS_FOUR = 11;
+	/**
+	 * PK skull carrying two loot keys
+	 */
+	public static final int LOOT_KEYS_FIVE = 12;
+	/**
+	 * Forinthry surge skull used on Deadman worlds
+	 */
+	public static final int FORINTHRY_SURGE_DEADMAN = 14;
+	/**
+	 * Forinthry surge while carrying one loot key
+	 */
+	public static final int FORINTHRY_SURGE_KEYS_ONE = 15;
+	/**
+	 * Forinthry surge while carrying two loot keys
+	 */
+	public static final int FORINTHRY_SURGE_KEYS_TWO = 16;
+	/**
+	 * Forinthry surge while carrying three loot keys
+	 */
+	public static final int FORINTHRY_SURGE_KEYS_THREE = 17;
+	/**
+	 * Forinthry surge while carrying four loot keys
+	 */
+	public static final int FORINTHRY_SURGE_KEYS_FOUR = 18;
+	/**
+	 * Forinthry surge while carrying five loot keys
+	 */
+	public static final int FORINTHRY_SURGE_KEYS_FIVE = 19;
+
+	/**
+	 * The player does not have a skull.
+	 */
+	public static final int NONE = -1;
+
 }
diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetModelType.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetModelType.java
index a04c0cfda..c055052f0 100644
--- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetModelType.java
+++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetModelType.java
@@ -32,4 +32,5 @@ public final class WidgetModelType
 	public static final int LOCAL_PLAYER_CHATHEAD = 3;
 	public static final int ITEM = 4;
 	public static final int PLAYER = 5;
+	public static final int NPC_INDEX_CHATHEAD = 6;
 }
diff --git a/runelite-client/pom.xml b/runelite-client/pom.xml
index 194fae556..52a2423e4 100644
--- a/runelite-client/pom.xml
+++ b/runelite-client/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>net.runelite</groupId>
 		<artifactId>runelite-parent</artifactId>
-		<version>1.10.37-SNAPSHOT</version>
+		<version>1.10.38-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>client</artifactId>
diff --git a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java
index 875891349..e510a02ae 100644
--- a/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java
+++ b/runelite-client/src/main/java/net/runelite/client/game/AgilityShortcut.java
@@ -264,8 +264,8 @@ public enum AgilityShortcut
 	TROLL_STRONGHOLD_WALL_CLIMB(73, "Rocks", new WorldPoint(2841, 3694, 0), ROCKS_16464),
 	ARCEUUS_ESSENSE_MINE_WEST(73, "Rock Climb", new WorldPoint(1742, 3853, 0), ROCKS_27984, ROCKS_27985),
 	LAVA_DRAGON_ISLE_JUMP(74, "Stepping Stone", new WorldPoint(3200, 3807, 0), STEPPING_STONE_14918),
-	MEIYERDITCH_LAB_TUNNELS_NORTH(74, "Cave", new WorldPoint(3623, 9811, 0), CAVE_43755, CAVE_43756),
-	MEIYERDITCH_LAB_TUNNELS_SOUTH(74, "Cave", new WorldPoint(3618, 9786, 0), CAVE_43757, CAVE_43758),
+	MEIYERDITCH_LAB_TUNNELS_NORTH(74, "Cave", new WorldPoint(3623, 9747, 0), CAVE_43755, CAVE_43756),
+	MEIYERDITCH_LAB_TUNNELS_SOUTH(74, "Cave", new WorldPoint(3618, 9722, 0), CAVE_43757, CAVE_43758),
 	REVENANT_CAVES_DEMONS_JUMP(75, "Jump", new WorldPoint(3199, 10135, 0), PILLAR_31561),
 	REVENANT_CAVES_ANKOU_EAST(75, "Jump", new WorldPoint(3201, 10195, 0), PILLAR_31561),
 	REVENANT_CAVES_ANKOU_NORTH(75, "Jump", new WorldPoint(3180, 10209, 0), PILLAR_31561),
@@ -296,9 +296,9 @@ public enum AgilityShortcut
 	MOUNT_KARUULM_PIPE_NORTH(88, "Pipe", new WorldPoint(1345, 10230, 0), MYSTERIOUS_PIPE),
 	REVENANT_CAVES_CHAMBER_JUMP(89, "Jump", new WorldPoint(3240, 10144, 0), PILLAR_31561),
 	VIYELDI_ROCK_CLIMB(91, "Rocks", null, NULL_40960, NULL_40962),
-	MEIYERDITCH_LAB_ADVANCED_TUNNELS_WEST(93, "Cave", new WorldPoint(3499, 9802, 0), CAVE_43759),
-	MEIYERDITCH_LAB_ADVANCED_TUNNELS_MIDDLE(93, "Cave", new WorldPoint(3597, 9768, 0), NULL_43840),
-	MEIYERDITCH_LAB_ADVANCED_TUNNELS_EAST(93, "Cave", new WorldPoint(3604, 9772, 0), CAVE_43762, CAVE_43763),
+	MEIYERDITCH_LAB_ADVANCED_TUNNELS_WEST(93, "Cave", new WorldPoint(3499, 9738, 0), CAVE_43759),
+	MEIYERDITCH_LAB_ADVANCED_TUNNELS_MIDDLE(93, "Cave", new WorldPoint(3597, 9704, 0), NULL_43840),
+	MEIYERDITCH_LAB_ADVANCED_TUNNELS_EAST(93, "Cave", new WorldPoint(3604, 9708, 0), CAVE_43762, CAVE_43763),
 	VIYELDI_CAVES_CREVICE(96, "Crevice", null, CREVICE_53242);
 
 	/**
diff --git a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java
index f31a1d59d..352bdf190 100644
--- a/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java
+++ b/runelite-client/src/main/java/net/runelite/client/game/ItemMapping.java
@@ -295,6 +295,7 @@ public enum ItemMapping
 	ITEM_TZHAARKETOM_ORNAMENT_KIT(TZHAARKETOM_ORNAMENT_KIT, TZHAARKETOM_T),
 	ITEM_DRAGON_HUNTER_CROSSBOW(DRAGON_HUNTER_CROSSBOW, DRAGON_HUNTER_CROSSBOW_B, DRAGON_HUNTER_CROSSBOW_T),
 	ITEM_VOIDWAKER(VOIDWAKER, VOIDWAKER_DEADMAN),
+	ITEM_AMULET_OF_RANCOUR(AMULET_OF_RANCOUR, AMULET_OF_RANCOUR_S),
 
 	// Slayer helm/black mask
 	ITEM_BLACK_MASK(BLACK_MASK, true, 1L, BLACK_MASK, SLAYER_HELMET),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java
index cf48c7dd9..d44a50b62 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsConfig.java
@@ -127,7 +127,7 @@ public interface BoostsConfig extends Config
 	@ConfigItem(
 		keyName = "boostThreshold",
 		name = "Boost threshold",
-		description = "The threshold at which boosted levels will be displayed in a different color. A value of 0 will disable the feature.",
+		description = "Number of levels above your base level at which boosted levels will be displayed in a different color.",
 		position = 12
 	)
 	default int boostThreshold()
@@ -138,11 +138,11 @@ public interface BoostsConfig extends Config
 	@ConfigItem(
 		keyName = "notifyOnBoost",
 		name = "Notify on boost threshold",
-		description = "Configures whether or not a notification will be sent for boosted stats.",
+		description = "Configures whether or not a notification will be sent when boosted stats drain to the boost threshold.",
 		position = 13
 	)
 	default Notification notifyOnBoost()
 	{
-		return Notification.ON;
+		return Notification.OFF;
 	}
 }
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java
index 2f235cd16..9bef8eacd 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/boosts/BoostsPlugin.java
@@ -32,6 +32,7 @@ import java.util.Set;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
 import net.runelite.api.Client;
 import net.runelite.api.Constants;
 import static net.runelite.api.MenuAction.RUNELITE_OVERLAY_CONFIG;
@@ -42,6 +43,7 @@ import net.runelite.api.events.GameTick;
 import net.runelite.api.events.StatChanged;
 import net.runelite.client.Notifier;
 import net.runelite.client.config.ConfigManager;
+import net.runelite.client.config.Notification;
 import net.runelite.client.eventbus.Subscribe;
 import net.runelite.client.events.ConfigChanged;
 import net.runelite.client.game.SkillIconManager;
@@ -59,6 +61,7 @@ import net.runelite.client.util.ImageUtil;
 	tags = {"combat", "notifications", "skilling", "overlay"}
 )
 @Singleton
+@Slf4j
 public class BoostsPlugin extends Plugin
 {
 	private static final Set<Skill> BOOSTABLE_COMBAT_SKILLS = ImmutableSet.of(
@@ -94,6 +97,9 @@ public class BoostsPlugin extends Plugin
 	@Inject
 	private BoostsConfig config;
 
+	@Inject
+	private ConfigManager configManager;
+
 	@Inject
 	private SkillIconManager skillIconManager;
 
@@ -119,6 +125,7 @@ public class BoostsPlugin extends Plugin
 	@Override
 	protected void startUp() throws Exception
 	{
+		convertConfig();
 		OverlayMenuEntry menuEntry = new OverlayMenuEntry(RUNELITE_OVERLAY_CONFIG, OPTION_CONFIGURE, "Boosts overlay");
 
 		boostsOverlay.getMenuEntries().add(menuEntry);
@@ -169,6 +176,24 @@ public class BoostsPlugin extends Plugin
 		}
 	}
 
+	private void convertConfig()
+	{
+		String migrated = configManager.getConfiguration("boosts", "migrated");
+		if (migrated != null)
+		{
+			return;
+		}
+
+		int boostThreshold = config.boostThreshold();
+		if (boostThreshold == 0)
+		{
+			configManager.setConfiguration("boosts", "notifyOnBoost", Notification.OFF);
+			log.debug("Disabled boosts notification due to config migration");
+		}
+
+		configManager.setConfiguration("boosts", "migrated", "1");
+	}
+
 	@Subscribe
 	public void onConfigChanged(ConfigChanged event)
 	{
@@ -221,15 +246,12 @@ public class BoostsPlugin extends Plugin
 
 		int boostThreshold = config.boostThreshold();
 
-		if (boostThreshold != 0)
+		int real = client.getRealSkillLevel(skill);
+		int lastBoost = last - real;
+		int boost = cur - real;
+		if (boost <= boostThreshold && boostThreshold < lastBoost)
 		{
-			int real = client.getRealSkillLevel(skill);
-			int lastBoost = last - real;
-			int boost = cur - real;
-			if (boost <= boostThreshold && boostThreshold < lastBoost)
-			{
-				notifier.notify(config.notifyOnBoost(), skill.getName() + " level is getting low!");
-			}
+			notifier.notify(config.notifyOnBoost(), skill.getName() + " level is getting low!");
 		}
 	}
 
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java
index 6840e258e..7a5b18c6f 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/chatcommands/ChatCommandsPlugin.java
@@ -107,7 +107,7 @@ import org.apache.commons.text.WordUtils;
 @Slf4j
 public class ChatCommandsPlugin extends Plugin
 {
-	private static final Pattern KILLCOUNT_PATTERN = Pattern.compile("Your (?<pre>completion count for |subdued |completed )?(?<boss>.+?) (?<post>(?:(?:kill|harvest|lap|completion) )?(?:count )?)is: <col=ff0000>(?<kc>\\d+)</col>");
+	private static final Pattern KILLCOUNT_PATTERN = Pattern.compile("Your (?<pre>completion count for |subdued |completed )?(?<boss>.+?) (?<post>(?:(?:kill|harvest|lap|completion) )?(?:count )?)is: <col=[0-9a-f]{6}>(?<kc>[0-9,]+)</col>");
 	private static final String TEAM_SIZES = "(?<teamsize>\\d+(?:\\+|-\\d+)? players?|Solo)";
 	private static final Pattern RAIDS_PB_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + TEAM_SIZES + "</col> Duration:</col> <col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col> \\(new personal best\\)</col>");
 	private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile("<col=ef20ff>Congratulations - your raid is complete!</col><br>Team size: <col=ff0000>" + TEAM_SIZES + "</col> Duration:</col> <col=ff0000>[0-9:.]+</col> Personal best: </col><col=ff0000>(?<pb>[0-9:]+(?:\\.[0-9]+)?)</col>");
@@ -422,7 +422,7 @@ public class ChatCommandsPlugin extends Plugin
 		if (matcher.find())
 		{
 			final String boss = matcher.group("boss");
-			final int kc = Integer.parseInt(matcher.group("kc"));
+			final int kc = Integer.parseInt(matcher.group("kc").replace(",", ""));
 			final String pre = matcher.group("pre");
 			final String post = matcher.group("post");
 
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java
index 4bf645006..1b9cfed96 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java
@@ -249,6 +249,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
 
 	private int viewportOffsetX;
 	private int viewportOffsetY;
+	private int viewportWidth;
+	private int viewportHeight;
 
 	// Uniforms
 	private int uniColorBlindMode;
@@ -884,6 +886,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
 		this.cameraYaw = cameraYaw;
 		viewportOffsetX = client.getViewportXOffset();
 		viewportOffsetY = client.getViewportYOffset();
+		viewportWidth = client.getViewportWidth();
+		viewportHeight = client.getViewportHeight();
 
 		final Scene scene = client.getScene();
 		scene.setDrawDistance(getDrawDistance());
@@ -1153,9 +1157,6 @@ public class GpuPlugin extends Plugin implements DrawCallbacks
 		final int canvasHeight = client.getCanvasHeight();
 		final int canvasWidth = client.getCanvasWidth();
 
-		final int viewportHeight = client.getViewportHeight();
-		final int viewportWidth = client.getViewportWidth();
-
 		prepareInterfaceTexture(canvasWidth, canvasHeight);
 
 		// Setup FBO and anti-aliasing
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java
index 2391eb9b1..e8013933a 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/instancemap/InstanceMapOverlay.java
@@ -257,8 +257,8 @@ class InstanceMapOverlay extends Overlay
 			img = img.getSubimage(
 				TILE_SIZE * (cropChunks * 8),
 				TILE_SIZE * (cropChunks * 8),
-				(Constants.SCENE_SIZE + expandedChunks * 8) * TILE_SIZE,
-				(Constants.SCENE_SIZE + expandedChunks * 8) * TILE_SIZE
+				(Constants.SCENE_SIZE + expandedChunks * 2 * 8) * TILE_SIZE,
+				(Constants.SCENE_SIZE + expandedChunks * 2 * 8) * TILE_SIZE
 			);
 		}
 		return img;
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java
index 50172c0a8..399810405 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/itemidentification/ItemIdentification.java
@@ -243,6 +243,11 @@ enum ItemIdentification
 	ADAMANTITE_BAR(Type.BAR, "Adaman", "ADA", ItemID.ADAMANTITE_BAR),
 	RUNITE_BAR(Type.BAR, "Runite", "RUN", ItemID.RUNITE_BAR),
 
+	BLURITE_BAR(Type.BAR, "Blurite", "BLU", ItemID.BLURITE_BAR),
+	ELEMENTAL_METAL(Type.BAR, "Elemental", "ELE", ItemID.ELEMENTAL_METAL),
+	LOVAKITE_BAR(Type.BAR, "Lovakite", "LOV", ItemID.LOVAKITE_BAR),
+	LUNAR_BAR(Type.BAR, "Lunar", "LUN", ItemID.LUNAR_BAR),
+
 	//Gems
 	SAPPHIRE(Type.GEM, "Sapphir", "S", ItemID.UNCUT_SAPPHIRE, ItemID.SAPPHIRE),
 	EMERALD(Type.GEM, "Emerald", "E", ItemID.UNCUT_EMERALD, ItemID.EMERALD),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java
index 7c6a59337..ded63c188 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/screenshot/ScreenshotPlugin.java
@@ -93,10 +93,10 @@ public class ScreenshotPlugin extends Plugin
 	private static final Map<Integer, String> CHEST_LOOT_EVENTS = ImmutableMap.of(12127, "The Gauntlet");
 	private static final int GAUNTLET_REGION = 7512;
 	private static final int CORRUPTED_GAUNTLET_REGION = 7768;
-	private static final Pattern NUMBER_PATTERN = Pattern.compile("([0-9]+)");
+	private static final Pattern NUMBER_PATTERN = Pattern.compile("([,0-9]+)");
 	private static final Pattern LEVEL_UP_PATTERN = Pattern.compile(".*Your ([a-zA-Z]+) (?:level is|are)? now (\\d+)\\.");
 	private static final Pattern LEVEL_UP_MESSAGE_PATTERN = Pattern.compile("Congratulations, you've (just advanced your (?<skill>[a-zA-Z]+) level\\. You are now level (?<level>\\d+)|reached the highest possible (?<skill99>[a-zA-Z]+) level of 99)\\.");
-	private static final Pattern BOSSKILL_MESSAGE_PATTERN = Pattern.compile("Your (.+) kill count is: <col=ff0000>(\\d+)</col>.");
+	private static final Pattern BOSSKILL_MESSAGE_PATTERN = Pattern.compile("Your (.+) kill count is: <col=[0-9a-f]{6}>([0-9,]+)</col>");
 	private static final Pattern VALUABLE_DROP_PATTERN = Pattern.compile(".*Valuable drop: ([^<>]+?\\(((?:\\d+,?)+) coins\\))(?:</col>)?");
 	private static final Pattern UNTRADEABLE_DROP_PATTERN = Pattern.compile(".*Untradeable drop: ([^<>]+)(?:</col>)?");
 	private static final Pattern DUEL_END_PATTERN = Pattern.compile("You have now (won|lost) ([0-9,]+) duels?\\.");
@@ -354,7 +354,7 @@ public class ScreenshotPlugin extends Plugin
 			Matcher m = NUMBER_PATTERN.matcher(Text.removeTags(chatMessage));
 			if (m.find())
 			{
-				clueNumber = Integer.valueOf(m.group());
+				clueNumber = Integer.valueOf(m.group().replace(",", ""));
 				clueType = chatMessage.substring(chatMessage.lastIndexOf(m.group()) + m.group().length() + 1, chatMessage.indexOf("Treasure") - 1);
 				return;
 			}
@@ -366,7 +366,7 @@ public class ScreenshotPlugin extends Plugin
 			if (m.find())
 			{
 				killType = KillType.BARROWS;
-				killCountNumber = Integer.valueOf(m.group());
+				killCountNumber = Integer.valueOf(m.group().replace(",", ""));
 				return;
 			}
 		}
@@ -377,7 +377,7 @@ public class ScreenshotPlugin extends Plugin
 			if (m.find())
 			{
 				killType = KillType.COX;
-				killCountNumber = Integer.valueOf(m.group());
+				killCountNumber = Integer.valueOf(m.group().replace(",", ""));
 				return;
 			}
 		}
@@ -388,7 +388,7 @@ public class ScreenshotPlugin extends Plugin
 			if (m.find())
 			{
 				killType = KillType.COX_CM;
-				killCountNumber = Integer.valueOf(m.group());
+				killCountNumber = Integer.valueOf(m.group().replace(",", ""));
 				return;
 			}
 		}
@@ -399,7 +399,7 @@ public class ScreenshotPlugin extends Plugin
 			if (m.find())
 			{
 				killType = chatMessage.contains("Hard Mode") ? KillType.TOB_HM : (chatMessage.contains("Story Mode") ? KillType.TOB_SM : KillType.TOB);
-				killCountNumber = Integer.valueOf(m.group());
+				killCountNumber = Integer.valueOf(m.group().replace(",", ""));
 				return;
 			}
 		}
@@ -412,7 +412,7 @@ public class ScreenshotPlugin extends Plugin
 				killType = chatMessage.contains("Expert Mode") ? KillType.TOA_EXPERT_MODE :
 					chatMessage.contains("Entry Mode") ? KillType.TOA_ENTRY_MODE :
 						KillType.TOA;
-				killCountNumber = Integer.valueOf(m.group());
+				killCountNumber = Integer.valueOf(m.group().replace(",", ""));
 				return;
 			}
 		}
@@ -423,7 +423,7 @@ public class ScreenshotPlugin extends Plugin
 			if (m.find())
 			{
 				killType = KillType.MOONS_OF_PERIL;
-				killCountNumber = Integer.valueOf(m.group());
+				killCountNumber = Integer.valueOf(m.group().replace(",", ""));
 				return;
 			}
 		}
@@ -448,10 +448,10 @@ public class ScreenshotPlugin extends Plugin
 		if (config.screenshotBossKills())
 		{
 			Matcher m = BOSSKILL_MESSAGE_PATTERN.matcher(chatMessage);
-			if (m.matches())
+			if (m.find())
 			{
 				String bossName = m.group(1);
-				String bossKillcount = m.group(2);
+				String bossKillcount = m.group(2).replace(",", "");
 				String fileName = bossName + "(" + bossKillcount + ")";
 				takeScreenshot(fileName, SD_BOSS_KILLS);
 			}
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingContractManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingContractManager.java
index 53ed1cdc1..502dbfacc 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingContractManager.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingContractManager.java
@@ -35,7 +35,7 @@ import javax.inject.Inject;
 import lombok.Getter;
 import lombok.Setter;
 import net.runelite.api.Client;
-import net.runelite.api.NpcID;
+import net.runelite.api.NullNpcID;
 import net.runelite.api.coords.WorldPoint;
 import net.runelite.api.widgets.ComponentID;
 import net.runelite.api.widgets.Widget;
@@ -51,7 +51,7 @@ import net.runelite.client.util.Text;
 @Singleton
 public class FarmingContractManager
 {
-	private static final int GUILDMASTER_JANE_NPC_ID = NpcID.GUILDMASTER_JANE_8587;
+	private static final int GUILDMASTER_JANE_NPC_ID = NullNpcID.NULL_8628;
 	private static final int FARMING_GUILD_REGION_ID = 4922;
 	private static final Pattern CONTRACT_ASSIGN_PATTERN = Pattern.compile("(?:We need you to grow|Please could you grow) (?:some|a|an) ([a-zA-Z ]+)(?: for us\\?|\\.)");
 	private static final String CONTRACT_REWARDED = "You'll be wanting a reward then. Here you go.";
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java
index a9a7a0550..b3fa6a548 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/timetracking/farming/FarmingWorld.java
@@ -40,6 +40,7 @@ import java.util.TreeSet;
 import java.util.stream.Collectors;
 import lombok.Getter;
 import net.runelite.api.NpcID;
+import net.runelite.api.NullNpcID;
 import net.runelite.api.Varbits;
 import net.runelite.api.coords.WorldPoint;
 import net.runelite.client.plugins.timetracking.Tab;
@@ -82,7 +83,7 @@ class FarmingWorld
 		));
 
 		add(new FarmingRegion("Avium Savannah", 6702, true,
-			new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HARDWOOD_TREE, NpcID.MARCELLUS_12936)
+			new FarmingPatch("", Varbits.FARMING_4771, PatchImplementation.HARDWOOD_TREE, NullNpcID.NULL_13401)
 		), 6446);
 
 		add(new FarmingRegion("Brimhaven", 11058, false,
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiDpsManager.java b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiDpsManager.java
index f4fad96ba..3bbfaceb4 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiDpsManager.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/wiki/WikiDpsManager.java
@@ -53,6 +53,7 @@ import net.runelite.api.widgets.ComponentID;
 import net.runelite.api.widgets.InterfaceID;
 import net.runelite.api.widgets.JavaScriptCallback;
 import net.runelite.api.widgets.Widget;
+import net.runelite.api.widgets.WidgetPositionMode;
 import net.runelite.api.widgets.WidgetType;
 import net.runelite.api.widgets.WidgetUtil;
 import net.runelite.client.callback.ClientThread;
@@ -217,14 +218,10 @@ class WikiDpsManager
 		// we must also use absolute for all the children below,
 		// which means it's necessary to offset the values by simulating corresponding pos/size modes.
 		int padding = 8;
-		int w = setBonus.getOriginalWidth();
-		int h = setBonus.getOriginalHeight();
-		int x = setBonus.getOriginalX() + (w / 2) + (padding / 2);
-		int y = setBonus.getOriginalY();
-		if (screen == Screen.BANK_EQUIPMENT) // uses ABSOLUTE_CENTER
-		{
-			y += parent.getHeight() / 2 - setBonus.getHeight() / 2;
-		}
+		final int w = setBonus.getOriginalWidth();
+		final int h = setBonus.getOriginalHeight();
+		final int x = setBonus.getOriginalX() + (w / 2) + (padding / 2);
+		final int y = setBonus.getOriginalY();
 
 		// now shift the Set Bonus and Stat Bonus buttons over a bit to make room
 		setBonus.setOriginalX(setBonus.getOriginalX() - (w / 2) - (padding / 2))
@@ -242,16 +239,31 @@ class WikiDpsManager
 		spriteWidgets[0] = parent.createChild(-1, WidgetType.GRAPHIC)
 			.setSpriteId(refComponents[0].getSpriteId())
 			.setPos(bgX, bgY)
-			.setSize(bgWidth, bgHeight);
+			.setSize(bgWidth, bgHeight)
+			.setYPositionMode(statBonus.getYPositionMode());
 		spriteWidgets[0].revalidate();
 
-		// borders and corners all use absolute positioning which is easy
+		// borders and corners
 		for (int i = 1; i < 9; i++)
 		{
-			spriteWidgets[i] = parent.createChild(-1, WidgetType.GRAPHIC)
+			Widget c = spriteWidgets[i] = parent.createChild(-1, WidgetType.GRAPHIC)
 				.setSpriteId(refComponents[i].getSpriteId())
-				.setPos(x + refComponents[i].getOriginalX(), y + refComponents[i].getOriginalY())
 				.setSize(refComponents[i].getOriginalWidth(), refComponents[i].getOriginalHeight());
+			if (statBonus.getYPositionMode() == WidgetPositionMode.ABSOLUTE_CENTER)
+			{
+				// Convert x/y from the reference component's, whose parent is the Set Bonus layer,
+				// to our components whose parent is the bank equipment parent.
+				// For y we have to reverse the ABSOLUTE_CENTER y calculation to convert
+				// the reference component original y into an offset from where the client will
+				// compute the ABSOLUTE_CENTER y to be.
+				c.setPos(x + refComponents[i].getOriginalX(), y - (setBonus.getHeight() - refComponents[i].getHeight() + 1) / 2 + refComponents[i].getOriginalY())
+					.setYPositionMode(statBonus.getYPositionMode());
+			}
+			else
+			{
+				c.setPos(x + refComponents[i].getOriginalX(), y + refComponents[i].getOriginalY());
+			}
+
 			spriteWidgets[i].revalidate();
 		}
 
@@ -265,7 +277,8 @@ class WikiDpsManager
 			.setXTextAlignment(refComponents[9].getXTextAlignment())
 			.setYTextAlignment(refComponents[9].getYTextAlignment())
 			.setPos(x, y)
-			.setSize(w, h);
+			.setSize(w, h)
+			.setYPositionMode(statBonus.getYPositionMode());
 		text.revalidate();
 
 		// we'll give the text layer the listeners since it covers the whole area
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java
index 8f506dede..eeb350b2a 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/HunterAreaLocation.java
@@ -39,7 +39,7 @@ enum HunterAreaLocation
 	CANIFIS_HUNTER_AREA1(new WorldPoint(3553, 3438, 0), HunterCreature.SWAMP_LIZARD),
 	CANIFIS_HUNTER_AREA2(new WorldPoint(3535, 3445, 0), HunterCreature.SWAMP_LIZARD),
 	FALCONRY(new WorldPoint(2379, 3599, 0), HunterCreature.SPOTTED_KEBBIT, HunterCreature.DARK_KEBBIT,
-		HunterCreature.DASHING_KEBBIT, HunterCreature.GREATER_SIREN),
+		HunterCreature.DASHING_KEBBIT),
 	FELDIP_HUNTER_AREA(new WorldPoint(2557, 2912, 0), HunterCreature.CRIMSON_SWIFT, HunterCreature.FELDIP_WEASEL,
 		HunterCreature.TROPICAL_WAGTAIL, HunterCreature.SPINED_LARUPIA, HunterCreature.BARB_TAILED_KEBBIT,
 		HunterCreature.BLACK_WARLOCK, HunterCreature.CARNIVOROUS_CHINCHOMPA),
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RunecraftingAltarLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RunecraftingAltarLocation.java
index fe34085a9..af2903ae5 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RunecraftingAltarLocation.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/RunecraftingAltarLocation.java
@@ -44,7 +44,7 @@ enum RunecraftingAltarLocation
 	LAW_ALTAR("Law Altar", 54, new WorldPoint(2858, 3381, 0), "law_altar_icon.png"),
 	DEATH_ALTAR("Death Altar", 65, new WorldPoint(1860, 4639, 0), "death_altar_icon.png"),
 	BLOOD_ALTAR("Blood Altar", 77, new WorldPoint(1716, 3827, 0), "blood_altar_icon.png"),
-	TRUE_BLOOD_ALTAR("True Blood Altar", 77, new WorldPoint(3625, 9781, 0), "blood_altar_icon.png"),
+	TRUE_BLOOD_ALTAR("True Blood Altar", 77, new WorldPoint(3625, 9717, 0), "blood_altar_icon.png"),
 	SOUL_ALTAR("Soul Altar", 90, new WorldPoint(1814, 3856, 0), "soul_altar_icon.png"),
 	WRATH_ALTAR("Wrath Altar", 95, new WorldPoint(2446, 2825, 0), "wrath_altar_icon.png");
 
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java
index 99b36760e..df1964fd3 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/worldmap/TransportationPointLocation.java
@@ -130,21 +130,21 @@ enum TransportationPointLocation
 	FERRY_RUINS_OF_UNKAH("Ferry to Al Kharid", new WorldPoint(3145, 2843, 0), new WorldPoint(3269, 3142, 0)),
 
 	//Minecarts/Carts
-	MINE_CART_ARCEUUS("Lovakengj Minecart Network", new WorldPoint(1673, 3832, 0)),
-	MINE_CART_FARMING_GUILD("Lovakengj Minecart Network", new WorldPoint(1219, 3738, 0)),
+	MINE_CART_ARCEUUS("Lovakengj Minecart Network - Arceuus", new WorldPoint(1673, 3832, 0)),
+	MINE_CART_FARMING_GUILD("Lovakengj Minecart Network - Farming Guild", new WorldPoint(1219, 3738, 0)),
 	MINE_CART_GRANDEXCHANGE("Minecart to Keldagrim", new WorldPoint(3139, 3504, 0)),
-	MINE_CART_HOSIDIUS_SOUTH("Lovakengj Minecart Network", new WorldPoint(1805, 3480, 0)),
-	MINE_CART_HOSIDIUS_WEST("Lovakengj Minecart Network", new WorldPoint(1656, 3542, 0)),
+	MINE_CART_HOSIDIUS_SOUTH("Lovakengj Minecart Network - Hosidius South", new WorldPoint(1805, 3480, 0)),
+	MINE_CART_HOSIDIUS_WEST("Lovakengj Minecart Network - Hosidius West", new WorldPoint(1656, 3542, 0)),
 	MINE_CART_ICE_MOUNTAIN("Minecart to Keldagrim", new WorldPoint(2995, 9836, 0)),
 	MINE_CART_KELDAGRIM("Keldagrim Minecart System", new WorldPoint(2908, 10170, 0)),
-	MINE_CART_KINGSTOWN("Lovakengj Minecart Network", new WorldPoint(1697, 3658, 0)),
-	MINE_CART_KOUREND_WOODLAND("Lovakengj Minecart Network", new WorldPoint(1570, 3464, 0)),
-	MINE_CART_LOVAKENGJ("Lovakengj Minecart Network", new WorldPoint(1524, 3725, 0)),
-	MINE_CART_MOUNT_QUIDAMORTEM("Lovakengj Minecart Network", new WorldPoint(1253, 3550, 0)),
-	MINE_CART_NORTHERN_TUNDRAS("Lovakengj Minecart Network", new WorldPoint(1646, 3930, 0)),
-	MINE_CART_PORT_PISCARILIUS("Lovakengj Minecart Network", new WorldPoint(1760, 3708, 0)),
-	MINE_CART_SHAYZIEN_EAST("Lovakengj Minecart Network", new WorldPoint(1586, 3622, 0)),
-	MINE_CART_SHAYZIEN_WEST("Lovakengj Minecart Network", new WorldPoint(1413, 3579, 0)),
+	MINE_CART_KINGSTOWN("Lovakengj Minecart Network - Kingstown", new WorldPoint(1697, 3658, 0)),
+	MINE_CART_KOUREND_WOODLAND("Lovakengj Minecart Network - Kourend Woodland", new WorldPoint(1570, 3464, 0)),
+	MINE_CART_LOVAKENGJ("Lovakengj Minecart Network - Lovakengj", new WorldPoint(1524, 3725, 0)),
+	MINE_CART_MOUNT_QUIDAMORTEM("Lovakengj Minecart Network - Mount Quidamortem", new WorldPoint(1253, 3550, 0)),
+	MINE_CART_NORTHERN_TUNDRAS("Lovakengj Minecart Network - Northern Tundras", new WorldPoint(1646, 3930, 0)),
+	MINE_CART_PORT_PISCARILIUS("Lovakengj Minecart Network - Port Piscarilius", new WorldPoint(1760, 3708, 0)),
+	MINE_CART_SHAYZIEN_EAST("Lovakengj Minecart Network - Shayzien East", new WorldPoint(1586, 3622, 0)),
+	MINE_CART_SHAYZIEN_WEST("Lovakengj Minecart Network - Shayzien West", new WorldPoint(1413, 3579, 0)),
 	MINE_CART_WHITE_WOLF_MOUNTAIN("Minecart to Keldagrim", new WorldPoint(2874, 9870, 0)),
 	CART_TO_BRIMHAVEN("Cart to Brimhaven", new WorldPoint(2833, 2958, 0), new WorldPoint(2780, 3214, 0)),
 	CART_TO_SHILO("Cart to Shilo Village", new WorldPoint(2780, 3214, 0), new WorldPoint(2833, 2958, 0)),
diff --git a/runelite-client/src/main/resources/item_variations.json b/runelite-client/src/main/resources/item_variations.json
index 39242d2a8..46b72a889 100644
--- a/runelite-client/src/main/resources/item_variations.json
+++ b/runelite-client/src/main/resources/item_variations.json
@@ -11885,50 +11885,75 @@
     28975,
     29307
   ],
+  "blue moon spear": [
+    28988,
+    29849
+  ],
+  "atlatl dart": [
+    28991,
+    29852
+  ],
+  "dual macuahuitl": [
+    28997,
+    29850
+  ],
+  "eclipse atlatl": [
+    29000,
+    29851
+  ],
   "eclipse moon chestplate": [
     29004,
     29031,
-    29049
+    29049,
+    29840
   ],
   "eclipse moon tassets": [
     29007,
     29033,
-    29052
+    29052,
+    29841
   ],
   "eclipse moon helm": [
     29010,
     29035,
-    29055
+    29055,
+    29842
   ],
   "blue moon chestplate": [
     29013,
     29037,
-    29058
+    29058,
+    29843
   ],
   "blue moon tassets": [
     29016,
     29039,
-    29061
+    29061,
+    29844
   ],
   "blue moon helm": [
     29019,
     29041,
-    29064
+    29064,
+    29845
   ],
   "blood moon chestplate": [
     29022,
     29043,
-    29067
+    29067,
+    29846
   ],
   "blood moon tassets": [
     29025,
     29045,
-    29070
+    29070,
+    29847
   ],
   "blood moon helm": [
     29028,
     29047,
-    29073
+    29073,
+    29848
   ],
   "moonlight potion": [
     29080,
diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/regions/regions.txt b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/regions/regions.txt
index f1f9d7566..e607d9a73 100644
--- a/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/regions/regions.txt
+++ b/runelite-client/src/main/resources/net/runelite/client/plugins/gpu/regions/regions.txt
@@ -348,6 +348,12 @@ C 0 0 2 6
 n
 r 54 148
 
-// chasm of tears
+// lumbridge underground
 n
-r 50 148
\ No newline at end of file
+R 50 148 50 151
+r 49 149
+r 51 150
+
+// desert mining camp (the tourist trap)
+n
+r 51 147
\ No newline at end of file
diff --git a/runelite-jshell/pom.xml b/runelite-jshell/pom.xml
index 1665933b3..6ca245803 100644
--- a/runelite-jshell/pom.xml
+++ b/runelite-jshell/pom.xml
@@ -30,7 +30,7 @@
     <parent>
         <groupId>net.runelite</groupId>
         <artifactId>runelite-parent</artifactId>
-        <version>1.10.37-SNAPSHOT</version>
+        <version>1.10.38-SNAPSHOT</version>
     </parent>
 
     <artifactId>jshell</artifactId>
diff --git a/runelite-maven-plugin/pom.xml b/runelite-maven-plugin/pom.xml
index bb95b465d..3f4307435 100644
--- a/runelite-maven-plugin/pom.xml
+++ b/runelite-maven-plugin/pom.xml
@@ -29,7 +29,7 @@
 	<parent>
 		<groupId>net.runelite</groupId>
 		<artifactId>runelite-parent</artifactId>
-		<version>1.10.37-SNAPSHOT</version>
+		<version>1.10.38-SNAPSHOT</version>
 	</parent>
 
 	<artifactId>runelite-maven-plugin</artifactId>


Test patch:
diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java
index 55acf05e8..09525f3f1 100644
--- a/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java
+++ b/runelite-client/src/test/java/net/runelite/client/plugins/chatcommands/ChatCommandsPluginTest.java
@@ -920,7 +920,7 @@ public class ChatCommandsPluginTest
 	@Test
 	public void testNightmareNoPb()
 	{
-		ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Nightmare kill count is: <col=ff0000>1130</col>", null, 0);
+		ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Nightmare kill count is: <col=ff0000>1,130</col>", null, 0);
 		chatCommandsPlugin.onChatMessage(chatMessage);
 
 		chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Team size: <col=ff0000>Solo</col> Fight duration: <col=ff0000>10:47</col>. Personal best: 8:44", null, 0);
diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java
index f15980ac7..ba3b7447b 100644
--- a/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java
+++ b/runelite-client/src/test/java/net/runelite/client/plugins/screenshot/ScreenshotPluginTest.java
@@ -66,7 +66,7 @@ import org.mockito.junit.MockitoJUnitRunner;
 @RunWith(MockitoJUnitRunner.class)
 public class ScreenshotPluginTest
 {
-	private static final String CLUE_SCROLL = "<col=3300ff>You have completed 28 medium Treasure Trails</col>";
+	private static final String CLUE_SCROLL = "<col=3300ff>You have completed 2,823 medium Treasure Trails</col>";
 	private static final String BARROWS_CHEST = "Your Barrows chest count is <col=ff0000>310</col>";
 	private static final String CHAMBERS_OF_XERIC_CHEST = "Your completed Chambers of Xeric count is: <col=ff0000>489</col>.";
 	private static final String THEATRE_OF_BLOOD_CHEST = "Your completed Theatre of Blood count is: <col=ff0000>73</col>.";
@@ -144,7 +144,7 @@ public class ScreenshotPluginTest
 		screenshotPlugin.onChatMessage(chatMessageEvent);
 
 		assertEquals("medium", screenshotPlugin.getClueType());
-		assertEquals(28, screenshotPlugin.getClueNumber());
+		assertEquals(2823, screenshotPlugin.getClueNumber());
 	}
 
 	@Test
@@ -542,4 +542,15 @@ public class ScreenshotPluginTest
 
 		verify(screenshotPlugin).takeScreenshot("Loot key", "Wilderness Loot Chest");
 	}
+
+	@Test
+	public void testBossKillCount()
+	{
+		when(screenshotConfig.screenshotBossKills()).thenReturn(true);
+
+		ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your Nightmare kill count is: <col=ff0000>1,130</col>", null, 0);
+		screenshotPlugin.onChatMessage(chatMessage);
+
+		verify(screenshotPlugin).takeScreenshot("Nightmare(1130)", "Boss Kills");
+	}
 }