diff --git a/runelite-api/src/main/java/net/runelite/api/Varbits.java b/runelite-api/src/main/java/net/runelite/api/Varbits.java
index de77227613..b39df1a823 100644
--- a/runelite-api/src/main/java/net/runelite/api/Varbits.java
+++ b/runelite-api/src/main/java/net/runelite/api/Varbits.java
@@ -317,6 +317,15 @@ public final class Varbits
* Theatre of Blood 1=In Party, 2=Inside/Spectator, 3=Dead Spectating
*/
public static final int THEATRE_OF_BLOOD = 6440;
+ /**
+ * Theatre of Blood orb healths
+ * 0=hide 1-27=% of health - 27 is 100% health and 1 is 0% health, 30=dead
+ */
+ public static final int THEATRE_OF_BLOOD_ORB1 = 6442;
+ public static final int THEATRE_OF_BLOOD_ORB2 = 6443;
+ public static final int THEATRE_OF_BLOOD_ORB3 = 6444;
+ public static final int THEATRE_OF_BLOOD_ORB4 = 6445;
+ public static final int THEATRE_OF_BLOOD_ORB5 = 6446;
/**
* Nightmare Zone
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 36cc4311d9..43ab96b51c 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;
public class ChatCommandsPlugin extends Plugin
{
private static final Pattern KILLCOUNT_PATTERN = Pattern.compile("Your (?:completion count for |subdued |completed )?(.+?) (?:(?:kill|harvest|lap|completion) )?(?:count )?is:
(\\d+)");
- private static final String TEAM_SIZES = "(?:\\d+(?:\\+|-\\d+)? players|Solo)";
+ private static final String TEAM_SIZES = "(?\\d+(?:\\+|-\\d+)? players|Solo)";
private static final Pattern RAIDS_PB_PATTERN = Pattern.compile(" Congratulations - your raid is complete! Team size: " + TEAM_SIZES + " Duration: (?[0-9:]+(?:\\.[0-9]+)?) \\(new personal best\\)");
private static final Pattern RAIDS_DURATION_PATTERN = Pattern.compile(" Congratulations - your raid is complete! Team size: " + TEAM_SIZES + " Duration: [0-9:.]+ Personal best: (?[0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern KILL_DURATION_PATTERN = Pattern.compile("(?i)(?:(?:Fight |Lap |Challenge |Corrupted challenge )?duration:|Subdued in|(?[0-9:.]+\\. Personal best: (?: )?(?[0-9:]+(?:\\.[0-9]+)?)");
@@ -115,7 +115,7 @@ public class ChatCommandsPlugin extends Plugin
private static final Pattern DUEL_ARENA_WINS_PATTERN = Pattern.compile("You (were defeated|won)! You have(?: now)? won ([\\d,]+|one) duels?");
private static final Pattern DUEL_ARENA_LOSSES_PATTERN = Pattern.compile("You have(?: now)? lost ([\\d,]+|one) duels?");
private static final Pattern ADVENTURE_LOG_TITLE_PATTERN = Pattern.compile("The Exploits of (.+)");
- private static final Pattern ADVENTURE_LOG_PB_PATTERN = Pattern.compile("Fastest (?:kill|run)(?: - \\(Team size: " + TEAM_SIZES + "\\))?: ([0-9:]+(?:\\.[0-9]+)?)");
+ private static final Pattern ADVENTURE_LOG_PB_PATTERN = Pattern.compile("Fastest (?:kill|run)(?: - \\(Team size: " + TEAM_SIZES + "\\))?: (?[0-9:]+(?:\\.[0-9]+)?)");
private static final Pattern HS_PB_PATTERN = Pattern.compile("Floor (?\\d) time: (?[0-9:]+(?:\\.[0-9]+)?)(?: \\(new personal best\\)|. Personal best: (?[0-9:]+(?:\\.[0-9]+)?))" +
"(?: Overall time: (?[0-9:]+(?:\\.[0-9]+)?)(?: \\(new personal best\\)|. Personal best: (?[0-9:]+(?:\\.[0-9]+)?)))?");
private static final Pattern HS_KC_FLOOR_PATTERN = Pattern.compile("You have completed Floor (\\d) of the Hallowed Sepulchre! Total completions: ([0-9,]+)\\.");
@@ -156,6 +156,7 @@ public class ChatCommandsPlugin extends Plugin
private String lastBossKill;
private int lastBossTime = -1;
private double lastPb = -1;
+ private String lastTeamSize;
private int modIconIdx = -1;
@Inject
@@ -394,8 +395,30 @@ public class ChatCommandsPlugin extends Plugin
if (lastPb > -1)
{
log.debug("Got out-of-order personal best for {}: {}", renamedBoss, lastPb);
- setPb(renamedBoss, lastPb);
+
+ if (renamedBoss.contains("Theatre of Blood"))
+ {
+ // TOB team size isn't sent in the kill message, but can be computed from varbits
+ int tobTeamSize = tobTeamSize();
+ lastTeamSize = tobTeamSize == 1 ? "Solo" : (tobTeamSize + " player");
+ }
+
+ final double pb = getPb(renamedBoss);
+ // If a raid with a team size, only update the pb if it is lower than the existing pb
+ // so that the pb is the overall lowest of any team size
+ if (lastTeamSize == null || pb == 0 || lastPb < pb)
+ {
+ log.debug("Setting overall pb (old: {})", pb);
+ setPb(renamedBoss, lastPb);
+ }
+ if (lastTeamSize != null)
+ {
+ log.debug("Setting team size pb: {}", lastTeamSize);
+ setPb(renamedBoss + " " + lastTeamSize, lastPb);
+ }
+
lastPb = -1;
+ lastTeamSize = null;
}
else
{
@@ -554,16 +577,26 @@ public class ChatCommandsPlugin extends Plugin
double seconds = timeStringToSeconds(matcher.group("pb"));
if (lastBossKill != null)
{
- // Most bosses sent boss kill message, and then pb message, so we
+ // Most bosses send boss kill message, and then pb message, so we
// use the remembered lastBossKill
log.debug("Got personal best for {}: {}", lastBossKill, seconds);
setPb(lastBossKill, seconds);
lastPb = -1;
+ lastTeamSize = null;
}
else
{
// Some bosses send the pb message, and then the kill message!
lastPb = seconds;
+ try
+ {
+ lastTeamSize = matcher.group("teamsize");
+ }
+ catch (IllegalArgumentException ex)
+ {
+ // pattern has no team size
+ lastTeamSize = null;
+ }
}
}
@@ -654,7 +687,7 @@ public class ChatCommandsPlugin extends Plugin
Matcher matcher = ADVENTURE_LOG_PB_PATTERN.matcher(line);
if (matcher.find())
{
- double s = timeStringToSeconds(matcher.group(1));
+ double s = timeStringToSeconds(matcher.group("time"));
pb = Math.min(pb, s);
}
}
@@ -1919,15 +1952,57 @@ public class ChatCommandsPlugin extends Plugin
case "herbi":
return "Herbiboar";
- // cox
+ // Chambers of Xeric
case "cox":
case "xeric":
case "chambers":
case "olm":
case "raids":
return "Chambers of Xeric";
+ case "cox 1":
+ case "cox solo":
+ return "Chambers of Xeric Solo";
+ case "cox 2":
+ case "cox duo":
+ return "Chambers of Xeric 2 players";
+ case "cox 3":
+ return "Chambers of Xeric 3 players";
+ case "cox 4":
+ return "Chambers of Xeric 4 players";
+ case "cox 5":
+ return "Chambers of Xeric 5 players";
+ case "cox 6":
+ return "Chambers of Xeric 6 players";
+ case "cox 7":
+ return "Chambers of Xeric 7 players";
+ case "cox 8":
+ return "Chambers of Xeric 8 players";
+ case "cox 9":
+ return "Chambers of Xeric 9 players";
+ case "cox 10":
+ return "Chambers of Xeric 10 players";
+ case "cox 11-15":
+ case "cox 11":
+ case "cox 12":
+ case "cox 13":
+ case "cox 14":
+ case "cox 15":
+ return "Chambers of Xeric 11-15 players";
+ case "cox 16-23":
+ case "cox 16":
+ case "cox 17":
+ case "cox 18":
+ case "cox 19":
+ case "cox 20":
+ case "cox 21":
+ case "cox 22":
+ case "cox 23":
+ return "Chambers of Xeric 16-23 players";
+ case "cox 24":
+ case "cox 24+":
+ return "Chambers of Xeric 24+ players";
- // cox cm
+ // Chambers of Xeric Challenge Mode
case "cox cm":
case "xeric cm":
case "chambers cm":
@@ -1935,15 +2010,70 @@ public class ChatCommandsPlugin extends Plugin
case "raids cm":
case "chambers of xeric - challenge mode":
return "Chambers of Xeric Challenge Mode";
+ case "cox cm 1":
+ case "cox cm solo":
+ return "Chambers of Xeric Challenge Mode Solo";
+ case "cox cm 2":
+ case "cox cm duo":
+ return "Chambers of Xeric Challenge Mode 2 players";
+ case "cox cm 3":
+ return "Chambers of Xeric Challenge Mode 3 players";
+ case "cox cm 4":
+ return "Chambers of Xeric Challenge Mode 4 players";
+ case "cox cm 5":
+ return "Chambers of Xeric Challenge Mode 5 players";
+ case "cox cm 6":
+ return "Chambers of Xeric Challenge Mode 6 players";
+ case "cox cm 7":
+ return "Chambers of Xeric Challenge Mode 7 players";
+ case "cox cm 8":
+ return "Chambers of Xeric Challenge Mode 8 players";
+ case "cox cm 9":
+ return "Chambers of Xeric Challenge Mode 9 players";
+ case "cox cm 10":
+ return "Chambers of Xeric Challenge Mode 10 players";
+ case "cox cm 11-15":
+ case "cox cm 11":
+ case "cox cm 12":
+ case "cox cm 13":
+ case "cox cm 14":
+ case "cox cm 15":
+ return "Chambers of Xeric Challenge Mode 11-15 players";
+ case "cox cm 16-23":
+ case "cox cm 16":
+ case "cox cm 17":
+ case "cox cm 18":
+ case "cox cm 19":
+ case "cox cm 20":
+ case "cox cm 21":
+ case "cox cm 22":
+ case "cox cm 23":
+ return "Chambers of Xeric Challenge Mode 16-23 players";
+ case "cox cm 24":
+ case "cox cm 24+":
+ return "Chambers of Xeric Challenge Mode 24+ players";
- // tob
+ // Theatre of Blood
case "tob":
case "theatre":
case "verzik":
case "verzik vitur":
case "raids 2":
return "Theatre of Blood";
+ case "tob 1":
+ case "tob solo":
+ return "Theatre of Blood Solo";
+ case "tob 2":
+ case "tob duo":
+ return "Theatre of Blood 2 player";
+ case "tob 3":
+ return "Theatre of Blood 3 player";
+ case "tob 4":
+ return "Theatre of Blood 4 player";
+ case "tob 5":
+ return "Theatre of Blood 5 player";
+ // Theatre of Blood Entry Mode
case "theatre of blood: story mode":
case "tob sm":
case "tob story mode":
@@ -1954,6 +2084,7 @@ public class ChatCommandsPlugin extends Plugin
case "tob entry":
return "Theatre of Blood Entry Mode";
+ // Theatre of Blood Hard Mode
case "theatre of blood: hard mode":
case "tob cm":
case "tob hm":
@@ -1961,6 +2092,18 @@ public class ChatCommandsPlugin extends Plugin
case "tob hard":
case "hmt":
return "Theatre of Blood Hard Mode";
+ case "hmt 1":
+ case "hmt solo":
+ return "Theatre of Blood Hard Mode Solo";
+ case "hmt 2":
+ case "hmt duo":
+ return "Theatre of Blood Hard Mode 2 player";
+ case "hmt 3":
+ return "Theatre of Blood Hard Mode 3 player";
+ case "hmt 4":
+ return "Theatre of Blood Hard Mode 4 player";
+ case "hmt 5":
+ return "Theatre of Blood Hard Mode 5 player";
// The Gauntlet
case "gaunt":
@@ -2256,4 +2399,13 @@ public class ChatCommandsPlugin extends Plugin
}
return null;
}
+
+ private int tobTeamSize()
+ {
+ return Math.min(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB1), 1) +
+ Math.min(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB2), 1) +
+ Math.min(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB3), 1) +
+ Math.min(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB4), 1) +
+ Math.min(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB5), 1);
+ }
}
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 843158dd32..aef7349dbe 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
@@ -41,6 +41,7 @@ import net.runelite.api.Client;
import net.runelite.api.MessageNode;
import net.runelite.api.Player;
import net.runelite.api.ScriptID;
+import net.runelite.api.Varbits;
import net.runelite.api.events.ChatMessage;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.ScriptPostFired;
@@ -164,6 +165,9 @@ public class ChatCommandsPluginTest
@Test
public void testTheatreOfBlood()
{
+ when(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB1)).thenReturn(1);
+ when(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB2)).thenReturn(15);
+
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
"Wave 'The Final Challenge' (Normal Mode) complete! " +
"Duration: 2:42.0 " +
@@ -178,11 +182,14 @@ public class ChatCommandsPluginTest
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 17 * 60 + .2);
+ verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood 2 player", 17 * 60 + .2);
}
@Test
public void testTheatreOfBloodNoPb()
{
+ when(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB1)).thenReturn(1);
+
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
"Wave 'The Final Challenge' (Normal Mode) complete! " +
"Duration: 2:42 " +
@@ -197,11 +204,14 @@ public class ChatCommandsPluginTest
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood", 73);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood", 13 * 60 + 52.8);
+ verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood solo", 13 * 60 + 52.8);
}
@Test
public void testTheatreOfBloodEntryMode()
{
+ when(client.getVarbitValue(Varbits.THEATRE_OF_BLOOD_ORB1)).thenReturn(1);
+
ChatMessage chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
"Wave 'The Final Challenge' (Entry Mode) complete! " +
"Duration: 2:42 " +
@@ -216,6 +226,7 @@ public class ChatCommandsPluginTest
verify(configManager).setRSProfileConfiguration("killcount", "theatre of blood entry mode", 73);
verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood entry mode", 17 * 60.);
+ verify(configManager).setRSProfileConfiguration("personalbest", "theatre of blood entry mode solo", 17 * 60.);
}
@Test
@@ -556,45 +567,45 @@ public class ChatCommandsPluginTest
@Test
public void testCoXKill()
{
- ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", " Congratulations - your raid is complete! Team size: 24+ players Duration: 37:04 (new personal best)>", null, 0);
+ ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", " Congratulations - your raid is complete! Team size: 24+ players Duration: 37:04.20 (new personal best)>", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 51.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "chambers of xeric", 51);
- verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 37 * 60 + 4.0);
-
- // Precise times
- chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", " Congratulations - your raid is complete! Team size: 24+ players Duration: 37:04.20 (new personal best)>", null, 0);
- chatCommandsPlugin.onChatMessage(chatMessage);
-
- chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 51.", null, 0);
- chatCommandsPlugin.onChatMessage(chatMessage);
-
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 37 * 60 + 4.2);
+ verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric 24+ players", 37 * 60 + 4.2);
}
@Test
public void testCoXKillNoPb()
{
- ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", " Congratulations - your raid is complete! Team size: 11-15 players Duration: 23:25 Personal best: 20:19", null, 0);
+ ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", " Congratulations - your raid is complete! Team size: 11-15 players Duration: 23:25.40 Personal best: 20:19.20", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 52.", null, 0);
chatCommandsPlugin.onChatMessage(chatMessage);
verify(configManager).setRSProfileConfiguration("killcount", "chambers of xeric", 52);
- verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 20 * 60 + 19.0);
-
- // Precise times
- chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "", " Congratulations - your raid is complete! Team size: 11-15 players Duration: 23:25.40 Personal best: 20:19.20", null, 0);
- chatCommandsPlugin.onChatMessage(chatMessage);
-
- chatMessage = new ChatMessage(null, GAMEMESSAGE, "", "Your completed Chambers of Xeric count is: 52.", null, 0);
- chatCommandsPlugin.onChatMessage(chatMessage);
-
verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric", 20 * 60 + 19.2);
+ verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric 11-15 players", 20 * 60 + 19.2);
+ }
+
+ @Test
+ public void testCoxCmNoPb()
+ {
+ ChatMessage chatMessage = new ChatMessage(null, FRIENDSCHATNOTIFICATION, "",
+ " Congratulations - your raid is complete! Team size: 3 players Duration: 41:10 Personal best: 40:03", null, 0);
+ chatCommandsPlugin.onChatMessage(chatMessage);
+
+ chatMessage = new ChatMessage(null, GAMEMESSAGE, "",
+ "Your completed Chambers of Xeric Challenge Mode count is: 13.", null, 0);
+ chatCommandsPlugin.onChatMessage(chatMessage);
+
+ verify(configManager).setRSProfileConfiguration("killcount", "chambers of xeric challenge mode", 13);
+ verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode", 40 * 60 + 3.);
+ verify(configManager).setRSProfileConfiguration("personalbest", "chambers of xeric challenge mode 3 players", 40 * 60 + 3.);
}
@Test