mirror of
https://github.com/2006-Scape/2006Scape.git
synced 2026-07-02 16:49:03 +00:00
Added NPC kill counts with message display (#644)
* Added kill counts with message display * Fixed barrows chest count * Preserve insertion order of NPC IDs for Constants * Added KC command and interfaces * Added more robustness to KC command * Added alias and documentation to new commands * Added more aliases for new commands * Merged slayer KC interface names * Preserve slayerkc nameToKills insertion order and formatting fix * Updated comment * Added missing boss NPC id * Moved giant mole up in set * Emptied out quest interface properly for kc * Fixed whitespace * Fixed formatting * Hide boss KC messages by default
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
package com.rs2;
|
||||
|
||||
import com.rs2.game.content.StaticNpcList;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
public class Constants {
|
||||
|
||||
@@ -105,4 +110,89 @@ public class Constants {
|
||||
CRAFTING = 12, SMITHING = 13, MINING = 14, HERBLORE = 15,
|
||||
AGILITY = 16, THIEVING = 17, SLAYER = 18, FARMING = 19,
|
||||
RUNECRAFTING = 20;
|
||||
|
||||
public static final LinkedHashSet<Integer> BOSS_NPC_IDS = new LinkedHashSet<>(Arrays.asList(
|
||||
StaticNpcList.CHAOS_ELEMENTAL,
|
||||
StaticNpcList.DAGANNOTH_REX,
|
||||
StaticNpcList.DAGANNOTH_PRIME,
|
||||
StaticNpcList.DAGANNOTH_SUPREME,
|
||||
StaticNpcList.GIANT_MOLE,
|
||||
StaticNpcList.KING_BLACK_DRAGON,
|
||||
StaticNpcList.KALPHITE_QUEEN,
|
||||
StaticNpcList.TZTOKJAD
|
||||
));
|
||||
|
||||
public static final LinkedHashSet<Integer> SLAYER_NPC_IDS = new LinkedHashSet<>(Arrays.asList(
|
||||
StaticNpcList.CRAWLING_HAND,
|
||||
StaticNpcList.CRAWLING_HAND_1649,
|
||||
StaticNpcList.CRAWLING_HAND_1650,
|
||||
StaticNpcList.CRAWLING_HAND_1651,
|
||||
StaticNpcList.CRAWLING_HAND_1652,
|
||||
StaticNpcList.CRAWLING_HAND_1653,
|
||||
StaticNpcList.CRAWLING_HAND_1654,
|
||||
StaticNpcList.CRAWLING_HAND_1655,
|
||||
StaticNpcList.CRAWLING_HAND_1656,
|
||||
StaticNpcList.CRAWLING_HAND_1657,
|
||||
StaticNpcList.CAVE_BUG,
|
||||
StaticNpcList.CAVE_CRAWLER,
|
||||
StaticNpcList.CAVE_CRAWLER_1601,
|
||||
StaticNpcList.CAVE_CRAWLER_1602,
|
||||
StaticNpcList.CAVE_CRAWLER_1603,
|
||||
StaticNpcList.BANSHEE,
|
||||
StaticNpcList.CAVE_SLIME,
|
||||
StaticNpcList.ROCKSLUG,
|
||||
StaticNpcList.ROCKSLUG_1623,
|
||||
StaticNpcList.DESERT_LIZARD,
|
||||
StaticNpcList.DESERT_LIZARD_2805,
|
||||
StaticNpcList.DESERT_LIZARD_2806,
|
||||
StaticNpcList.COCKATRICE,
|
||||
StaticNpcList.COCKATRICE_1621,
|
||||
StaticNpcList.PYREFIEND,
|
||||
StaticNpcList.PYREFIEND_1634,
|
||||
StaticNpcList.PYREFIEND_1635,
|
||||
StaticNpcList.PYREFIEND_1636,
|
||||
StaticNpcList.MOGRE,
|
||||
StaticNpcList.HARPIE_BUG_SWARM,
|
||||
StaticNpcList.WALL_BEAST,
|
||||
StaticNpcList.KILLERWATT,
|
||||
StaticNpcList.KILLERWATT_3202,
|
||||
StaticNpcList.BASILISK,
|
||||
StaticNpcList.BASILISK_1617,
|
||||
StaticNpcList.FEVER_SPIDER,
|
||||
StaticNpcList.INFERNAL_MAGE,
|
||||
StaticNpcList.INFERNAL_MAGE_1644,
|
||||
StaticNpcList.INFERNAL_MAGE_1645,
|
||||
StaticNpcList.INFERNAL_MAGE_1646,
|
||||
StaticNpcList.INFERNAL_MAGE_1647,
|
||||
StaticNpcList.JELLY,
|
||||
StaticNpcList.JELLY_1638,
|
||||
StaticNpcList.JELLY_1639,
|
||||
StaticNpcList.JELLY_1640,
|
||||
StaticNpcList.JELLY_1641,
|
||||
StaticNpcList.JELLY_1642,
|
||||
StaticNpcList.TUROTH,
|
||||
StaticNpcList.TUROTH_1627,
|
||||
StaticNpcList.TUROTH_1628,
|
||||
StaticNpcList.TUROTH_1629,
|
||||
StaticNpcList.TUROTH_1630,
|
||||
StaticNpcList.TUROTH_1631,
|
||||
StaticNpcList.TUROTH_1632,
|
||||
StaticNpcList.ABERRANT_SPECTER,
|
||||
StaticNpcList.ABERRANT_SPECTER_1605,
|
||||
StaticNpcList.ABERRANT_SPECTER_1606,
|
||||
StaticNpcList.ABERRANT_SPECTER_1607,
|
||||
StaticNpcList.DUST_DEVIL,
|
||||
StaticNpcList.KURASK,
|
||||
StaticNpcList.KURASK_1609,
|
||||
StaticNpcList.SKELETAL_WYVERN,
|
||||
StaticNpcList.SKELETAL_WYVERN_3069,
|
||||
StaticNpcList.SKELETAL_WYVERN_3070,
|
||||
StaticNpcList.SKELETAL_WYVERN_3071,
|
||||
StaticNpcList.GARGOYLE,
|
||||
StaticNpcList.GARGOYLE_1611,
|
||||
StaticNpcList.NECHRYAEL,
|
||||
StaticNpcList.ABYSSAL_DEMON,
|
||||
StaticNpcList.DARK_BEAST,
|
||||
StaticNpcList.SMOKEDEVIL
|
||||
));
|
||||
}
|
||||
@@ -230,6 +230,10 @@ public class Barrows {
|
||||
}
|
||||
if (c.barrowsKillCount > 5 && checkBarrows()) {
|
||||
if (c.getItemAssistant().freeSlots() >= 4) {
|
||||
c.incrementNpcKillCount(100000, 1);
|
||||
if (c.displayBossKcMessages || c.displayRegularKcMessages) {
|
||||
c.getPacketSender().sendMessage("Your Barrows Chest count is now: " + c.getNpcKillCount(100000));
|
||||
}
|
||||
reward();
|
||||
resetBarrows();
|
||||
} else {
|
||||
|
||||
@@ -66,6 +66,10 @@ public class Npc {
|
||||
updateRequired = true;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return NpcHandler.getNpcListName(this.npcType);
|
||||
}
|
||||
|
||||
public void shearSheep(Player player, int itemNeeded, int itemGiven, int animation, final int currentId, final int newId, int transformTime) {
|
||||
if (!player.getItemAssistant().playerHasItem(itemNeeded)) {
|
||||
player.getPacketSender().sendMessage("You need " + DeprecatedItems.getItemName(itemNeeded).toLowerCase() + " to do that.");
|
||||
|
||||
@@ -333,28 +333,34 @@ public class NpcHandler {
|
||||
npcs[slot] = newNPC;
|
||||
}
|
||||
|
||||
private void killedBarrow(int i) {
|
||||
private boolean killedBarrow(int i) {
|
||||
boolean barrows = false;
|
||||
Player c = (Client) PlayerHandler.players[npcs[i].killedBy];
|
||||
if (c != null) {
|
||||
for (int o = 0; o < c.barrowsNpcs.length; o++) {
|
||||
if (npcs[i].npcType == c.barrowsNpcs[o][0]) {
|
||||
c.barrowsNpcs[o][1] = 2; // 2 for dead
|
||||
c.barrowsKillCount++;
|
||||
barrows = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return barrows;
|
||||
}
|
||||
|
||||
private void killedCrypt(int i) {
|
||||
private boolean killedCrypt(int i) {
|
||||
boolean crypt = false;
|
||||
Player c = (Client) PlayerHandler.players[npcs[i].killedBy];
|
||||
if (c != null) {
|
||||
for (int o = 0; o < c.barrowCrypt.length; o++) {
|
||||
if (npcs[i].npcType == c.barrowCrypt[o][0]) {
|
||||
c.barrowsKillCount++;
|
||||
c.getPacketSender().sendString("" + c.barrowsKillCount, 4536);
|
||||
crypt = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return crypt;
|
||||
}
|
||||
|
||||
public void newNPC(int npcType, int x, int y, int heightLevel,
|
||||
@@ -747,10 +753,16 @@ public class NpcHandler {
|
||||
npcs[i].animUpdateRequired = true;
|
||||
npcs[i].freezeTimer = 0;
|
||||
npcs[i].applyDead = true;
|
||||
killedBarrow(i);
|
||||
killedCrypt(i);
|
||||
boolean barrows = killedBarrow(i);
|
||||
boolean crypt = killedCrypt(i);
|
||||
npcs[i].actionTimer = 4; // delete time
|
||||
resetPlayersInCombat(i);
|
||||
if (!crypt && !barrows && c != null) {
|
||||
c.incrementNpcKillCount(npcs[i].npcType, 1);
|
||||
if (c.displayRegularKcMessages || (c.displayBossKcMessages && Constants.BOSS_NPC_IDS.contains(npcs[i].npcType)) || (c.displaySlayerKcMessages && Constants.SLAYER_NPC_IDS.contains(npcs[i].npcType))) {
|
||||
c.getPacketSender().sendMessage("Your " + npcs[i].name() + " kill count is now: " + c.getNpcKillCount(npcs[i].npcType));
|
||||
}
|
||||
}
|
||||
} else if (npcs[i].actionTimer == 0
|
||||
&& npcs[i].applyDead
|
||||
&& npcs[i].needRespawn == false) {
|
||||
|
||||
@@ -144,6 +144,24 @@ public abstract class Player {
|
||||
private GateHandler gateHandler = new GateHandler();
|
||||
private SingleGates singleGates = new SingleGates();
|
||||
private DoubleGates doubleGates = new DoubleGates();
|
||||
|
||||
private Map<Integer, Integer> npcKillCounts = new HashMap<>();
|
||||
public boolean displayBossKcMessages = false;
|
||||
public boolean displaySlayerKcMessages = false;
|
||||
public boolean displayRegularKcMessages = false;
|
||||
|
||||
public int getNpcKillCount(int npcId) {
|
||||
return npcKillCounts.getOrDefault(npcId, 0);
|
||||
}
|
||||
|
||||
public Map<Integer, Integer> getNpcKillCounts() {
|
||||
return npcKillCounts;
|
||||
}
|
||||
|
||||
public void incrementNpcKillCount(int npcId, int count) {
|
||||
npcKillCounts.put(npcId, npcKillCounts.getOrDefault(npcId, 0) + count);
|
||||
}
|
||||
|
||||
public int lastMainFrameInterface = -1; //Possibly used in future to prevent packet exploits
|
||||
|
||||
public int getXPRate() { return xpRate; }
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
|
||||
import com.rs2.util.Misc;
|
||||
|
||||
@@ -439,6 +440,15 @@ public class PlayerSave {
|
||||
case "discord-user-id":
|
||||
player.discordCode = token2;
|
||||
break;
|
||||
case "display-boss-kc-messages":
|
||||
player.displayBossKcMessages = Boolean.parseBoolean(token2);
|
||||
break;
|
||||
case "display-slayer-kc-messages":
|
||||
player.displaySlayerKcMessages = Boolean.parseBoolean(token2);
|
||||
break;
|
||||
case "display-regular-kc-messages":
|
||||
player.displayRegularKcMessages = Boolean.parseBoolean(token2);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
@@ -480,6 +490,16 @@ public class PlayerSave {
|
||||
if (token.equals("character-ignore")) {
|
||||
player.ignores[Integer.parseInt(token3[0])] = Long.parseLong(token3[1]);
|
||||
}
|
||||
case 10:
|
||||
if (token.startsWith("npcid-")) {
|
||||
try {
|
||||
int npcId = Integer.parseInt(token.substring(6));
|
||||
int killCount = Integer.parseInt(token2);
|
||||
player.incrementNpcKillCount(npcId, killCount);
|
||||
} catch (NumberFormatException e) {
|
||||
System.out.println("Error parsing NPC kill count for " + token);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -511,6 +531,9 @@ public class PlayerSave {
|
||||
case "[IGNORES]":
|
||||
ReadMode = 9;
|
||||
break;
|
||||
case "[NPC-KILLS]":
|
||||
ReadMode = 10;
|
||||
break;
|
||||
case "[EOF]":
|
||||
try {
|
||||
characterfile.close();
|
||||
@@ -833,6 +856,12 @@ public class PlayerSave {
|
||||
characterfile.newLine();
|
||||
characterfile.write("discord-user-id = " + player.discordCode);
|
||||
characterfile.newLine();
|
||||
characterfile.write("display-boss-kc-messages = " + player.displayBossKcMessages);
|
||||
characterfile.newLine();
|
||||
characterfile.write("display-slayer-kc-messages = " + player.displaySlayerKcMessages);
|
||||
characterfile.newLine();
|
||||
characterfile.write("display-regular-kc-messages = " + player.displayRegularKcMessages);
|
||||
characterfile.newLine();
|
||||
characterfile.newLine();
|
||||
|
||||
/* EQUIPMENT */
|
||||
@@ -905,6 +934,14 @@ public class PlayerSave {
|
||||
}
|
||||
characterfile.newLine();
|
||||
|
||||
characterfile.write("[NPC-KILLS]");
|
||||
characterfile.newLine();
|
||||
for (Map.Entry<Integer, Integer> entry : player.getNpcKillCounts().entrySet()) {
|
||||
characterfile.write("npcid-" + entry.getKey() + " = " + entry.getValue());
|
||||
characterfile.newLine();
|
||||
}
|
||||
characterfile.newLine();
|
||||
|
||||
/* EOF */
|
||||
characterfile.write("[EOF]");
|
||||
characterfile.newLine();
|
||||
|
||||
@@ -2,12 +2,13 @@ package com.rs2.net.packets.impl;
|
||||
|
||||
import static com.rs2.util.GameLogger.writeLog;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.*;
|
||||
|
||||
import com.rs2.Connection;
|
||||
import com.rs2.Constants;
|
||||
import com.rs2.GameEngine;
|
||||
import com.rs2.game.bots.BotHandler;
|
||||
import com.rs2.game.npcs.NPCDefinition;
|
||||
import com.rs2.game.npcs.NpcHandler;
|
||||
import com.rs2.game.players.*;
|
||||
import com.rs2.game.players.antimacro.AntiSpam;
|
||||
@@ -229,6 +230,135 @@ public class Commands implements PacketType {
|
||||
case "prayer":
|
||||
player.getPacketSender().sendMessage(String.format("Prayer points: %d", player.playerLevel[Constants.PRAYER]));
|
||||
break;
|
||||
case "togglenpckillmsgs":
|
||||
case "togglenpckillmsg":
|
||||
case "togglenpckcmsgs":
|
||||
case "togglenpckcmsg":
|
||||
player.displayRegularKcMessages = !player.displayRegularKcMessages;
|
||||
player.getPacketSender().sendMessage("You now have regular NPC kill count messages: " + (player.displayRegularKcMessages ? "enabled" : "disabled"));
|
||||
break;
|
||||
case "togglebosskillmsgs":
|
||||
case "togglebosskillmsg":
|
||||
case "togglebossksmsgs":
|
||||
case "togglebossksmsg":
|
||||
player.displayBossKcMessages = !player.displayBossKcMessages;
|
||||
player.getPacketSender().sendMessage("You now have boss NPC kill count messages: " + (player.displayBossKcMessages ? "enabled" : "disabled"));
|
||||
break;
|
||||
case "toggleslayerkillmsgs":
|
||||
case "toggleslayerkillmsg":
|
||||
case "toggleslayerkcmsgs":
|
||||
case "toggleslayerkcmsg":
|
||||
player.displaySlayerKcMessages = !player.displaySlayerKcMessages;
|
||||
player.getPacketSender().sendMessage("You now have slayer NPC kill count messages: " + (player.displaySlayerKcMessages ? "enabled" : "disabled"));
|
||||
break;
|
||||
case "kc":
|
||||
case "kills":
|
||||
case "checknpckill":
|
||||
case "checknpckills":
|
||||
if (arguments.length > 0) {
|
||||
// Combine all arguments into a single string, assuming space-separated
|
||||
String npcNameInput = String.join(" ", arguments).toLowerCase();
|
||||
try {
|
||||
// Try to parse as an ID
|
||||
int npcId = Integer.parseInt(arguments[0]);
|
||||
int killCount = player.getNpcKillCounts().getOrDefault(npcId, 0);
|
||||
String npcName = NPCDefinition.forId(npcId).getName();
|
||||
player.getPacketSender().sendMessage("Kill count for " + npcName + ": " + killCount);
|
||||
} catch (NumberFormatException e) {
|
||||
// If not an ID, treat as a name
|
||||
List<NPCDefinition> matchingDefs = new ArrayList<>();
|
||||
for (int id = 0; id <= 3789; id++) {
|
||||
try {
|
||||
NPCDefinition def = NPCDefinition.forId(id);
|
||||
if (def.getName().toLowerCase().startsWith(npcNameInput)) {
|
||||
matchingDefs.add(def);
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
System.err.println("Exception during kc command: " + exception.getMessage());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matchingDefs.isEmpty()) {
|
||||
player.getPacketSender().sendMessage("No NPCs found with the name: " + npcNameInput);
|
||||
} else {
|
||||
boolean empty = true;
|
||||
for (NPCDefinition def : matchingDefs) {
|
||||
int killCount = player.getNpcKillCounts().getOrDefault(def.getId(), 0);
|
||||
if (killCount > 0) {
|
||||
empty = false;
|
||||
player.getPacketSender().sendMessage("Kill count for " + def.getName() + " (ID: " + def.getId() + "): " + killCount);
|
||||
}
|
||||
}
|
||||
if (empty) {
|
||||
player.getPacketSender().sendMessage("Kill count for " + npcNameInput + ": 0");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.getPacketSender().sendMessage("Please provide an NPC ID or name.");
|
||||
}
|
||||
break;
|
||||
case "bosskillcounts":
|
||||
case "bosskillcount":
|
||||
case "bosskc":
|
||||
case "kcboss":
|
||||
// Clear all lines
|
||||
for (int i = 8144; i < 8196; i++) {
|
||||
player.getPacketSender().sendString("", i);
|
||||
}
|
||||
for (int i = 12174; i < (12174 + 50); i++) {
|
||||
player.getPacketSender().sendString("", i);
|
||||
}
|
||||
for (int i = 14945; i < (14945 + 100); i++) {
|
||||
player.getPacketSender().sendString("", i);
|
||||
}
|
||||
|
||||
player.getPacketSender().sendString("@dre@Boss Kill Counts", 8144);
|
||||
int bossLineId = 8147; // Starting line for display
|
||||
player.getPacketSender().sendString("Barrows Chests: " + player.getNpcKillCounts().getOrDefault(100000, 0), bossLineId++);
|
||||
for (Integer bossId : Constants.BOSS_NPC_IDS) {
|
||||
int killCount = player.getNpcKillCounts().getOrDefault(bossId, 0);
|
||||
String npcName = NPCDefinition.forId(bossId).getName();
|
||||
player.getPacketSender().sendString(npcName + ": " + killCount, bossLineId++);
|
||||
}
|
||||
|
||||
player.getPacketSender().showInterface(8134);
|
||||
break;
|
||||
case "slayerkillcounts":
|
||||
case "slayerkillcount":
|
||||
case "slayerkc":
|
||||
case "kcslayer":
|
||||
// Clear all lines
|
||||
for (int i = 8144; i < 8196; i++) {
|
||||
player.getPacketSender().sendString("", i);
|
||||
}
|
||||
for (int i = 12174; i < (12174 + 50); i++) {
|
||||
player.getPacketSender().sendString("", i);
|
||||
}
|
||||
for (int i = 14945; i < (14945 + 100); i++) {
|
||||
player.getPacketSender().sendString("", i);
|
||||
}
|
||||
|
||||
player.getPacketSender().sendString("@dre@Slayer Kill Counts", 8144);
|
||||
int slayerLineId = 8147; // Starting line for display
|
||||
|
||||
// LinkedHashMap to store cumulative kills by NPC name
|
||||
LinkedHashMap<String, Integer> nameToKills = new LinkedHashMap<>();
|
||||
|
||||
// Populate the HashMap
|
||||
for (Integer npcId : Constants.SLAYER_NPC_IDS) {
|
||||
String npcName = NPCDefinition.forId(npcId).getName();
|
||||
int killCount = player.getNpcKillCounts().getOrDefault(npcId, 0);
|
||||
nameToKills.put(npcName, nameToKills.getOrDefault(npcName, 0) + killCount);
|
||||
}
|
||||
|
||||
// Display the results
|
||||
for (Map.Entry<String, Integer> entry : nameToKills.entrySet()) {
|
||||
player.getPacketSender().sendString(entry.getKey() + ": " + entry.getValue(), slayerLineId++);
|
||||
}
|
||||
|
||||
player.getPacketSender().showInterface(8134);
|
||||
break;
|
||||
case "snow":
|
||||
Calendar date = new GregorianCalendar();
|
||||
if ((date.get(Calendar.MONTH) + 1) == 12 && !player.inWild()) {
|
||||
@@ -325,6 +455,24 @@ public class Commands implements PacketType {
|
||||
"::withdrawshop(::wshop)",
|
||||
"Withdraw profits from player owned shop",
|
||||
"",
|
||||
"::togglenpckillmsgs(::togglenpckcmsgs)",
|
||||
"Toggle regular NPC kill count message display","",
|
||||
"",
|
||||
"::togglebosskillmsgs(::togglebosskcmsgs)",
|
||||
"Toggle regular Boss kill count message display","",
|
||||
"",
|
||||
"::toggleslayerkillmsgs(::toggleslayerkcmsgs)",
|
||||
"Toggle regular Slayer kill count message display",
|
||||
"",
|
||||
"::kc(::checknpckills)",
|
||||
"Search for your NPC kills for an NPC name or ID",
|
||||
"",
|
||||
"::bosskc(::toggleslayerkcmsgs)",
|
||||
"View your boss kills",
|
||||
"",
|
||||
"::slayerkc(::toggleslayerkcmsgs)",
|
||||
"View your slayer kills",
|
||||
"",
|
||||
"::snow",
|
||||
"Add some snow in your mainscreen(works only in december)",
|
||||
(Constants.VARIABLE_XP_RATE ? "\\n" + "::xprate\\n" + "Opens dialogue for the player to set/increase their XP rate." : ""),
|
||||
|
||||
Reference in New Issue
Block a user