Add /roll and friend management commands

Roll Command:
- Add /roll, /random, /rnd commands for random number generation
- Support multiple formats: /roll, /roll 100, /roll 1-100, /roll 10 50
- Broadcasts rolls to party/raid with "[Name] rolls X (min-max)" format
- Cap max roll at 10,000 to prevent abuse
- Use MSG_RANDOM_ROLL (0x1FB) bidirectional opcode

Friend Commands:
- Add /friend add <name>, /addfriend <name> to add friends
- Add /friend remove <name>, /removefriend <name> to remove friends
- Support aliases: /delfriend, /remfriend
- Maintain local friends cache mapping names to GUIDs for lookups
- Display status messages for all friend actions:
  - Friend added/removed confirmations
  - Friend online/offline notifications
  - Error messages (not found, already friends, list full, ignoring)

Social Opcodes:
- Add CMSG_ADD_FRIEND (0x69) and SMSG_FRIEND_STATUS (0x68)
- Add CMSG_DEL_FRIEND (0x6A) for friend removal
- Add CMSG_SET_CONTACT_NOTES (0x6B) for friend notes (future use)
- Add CMSG_ADD_IGNORE (0x6C) and CMSG_DEL_IGNORE (0x6D) (future use)

Implementation:
- Add RandomRollPacket builder and RandomRollParser for roll data
- Add AddFriendPacket and DelFriendPacket builders
- Add FriendStatusParser to handle server friend status updates
- Add friendsCache map to store friend name-to-GUID mappings
- Add handleRandomRoll() and handleFriendStatus() packet handlers
- Comprehensive slash command parsing with multiple formats and aliases
This commit is contained in:
kelsi davis 2026-02-07 12:51:30 -08:00
parent f9c4cbddee
commit 6f45c6ab69
6 changed files with 427 additions and 0 deletions

View file

@ -210,6 +210,14 @@ public:
void requestPlayedTime();
void queryWho(const std::string& playerName = "");
// Social commands
void addFriend(const std::string& playerName, const std::string& note = "");
void removeFriend(const std::string& playerName);
void setFriendNote(const std::string& playerName, const std::string& note);
// Random roll
void randomRoll(uint32_t minRoll = 1, uint32_t maxRoll = 100);
// ---- Phase 1: Name queries ----
void queryPlayerName(uint64_t guid);
void queryCreatureInfo(uint32_t entry, uint64_t guid);
@ -513,6 +521,10 @@ private:
void handlePlayedTime(network::Packet& packet);
void handleWho(network::Packet& packet);
// ---- Social handlers ----
void handleFriendStatus(network::Packet& packet);
void handleRandomRoll(network::Packet& packet);
void addCombatText(CombatTextEntry::Type type, int32_t amount, uint32_t spellId, bool isPlayerSource);
void addSystemChatMessage(const std::string& message);
@ -592,6 +604,9 @@ private:
std::unordered_map<uint32_t, CreatureQueryResponseData> creatureInfoCache;
std::unordered_set<uint32_t> pendingCreatureQueries;
// ---- Friend list cache ----
std::unordered_map<std::string, uint64_t> friendsCache; // name -> guid
// ---- Online item tracking ----
struct OnlineItemInfo {
uint32_t entry = 0;

View file

@ -63,6 +63,17 @@ enum class Opcode : uint16_t {
CMSG_QUERY_TIME = 0x1CE,
SMSG_QUERY_TIME_RESPONSE = 0x1CF,
// ---- Social Commands ----
SMSG_FRIEND_STATUS = 0x068,
CMSG_ADD_FRIEND = 0x069,
CMSG_DEL_FRIEND = 0x06A,
CMSG_SET_CONTACT_NOTES = 0x06B,
CMSG_ADD_IGNORE = 0x06C,
CMSG_DEL_IGNORE = 0x06D,
// ---- Random Roll ----
MSG_RANDOM_ROLL = 0x1FB,
// ---- Phase 1: Foundation (Targeting, Queries) ----
CMSG_SET_SELECTION = 0x13D,
CMSG_NAME_QUERY = 0x050,

View file

@ -700,6 +700,67 @@ public:
uint32_t zones = 0);
};
// ============================================================
// Social Commands
// ============================================================
/** CMSG_ADD_FRIEND packet builder */
class AddFriendPacket {
public:
static network::Packet build(const std::string& playerName, const std::string& note = "");
};
/** CMSG_DEL_FRIEND packet builder */
class DelFriendPacket {
public:
static network::Packet build(uint64_t friendGuid);
};
/** CMSG_SET_CONTACT_NOTES packet builder */
class SetContactNotesPacket {
public:
static network::Packet build(uint64_t friendGuid, const std::string& note);
};
/** SMSG_FRIEND_STATUS data */
struct FriendStatusData {
uint8_t status = 0; // 0 = offline, 1 = online, etc.
uint64_t guid = 0;
std::string note;
uint8_t chatFlag = 0;
};
/** SMSG_FRIEND_STATUS parser */
class FriendStatusParser {
public:
static bool parse(network::Packet& packet, FriendStatusData& data);
};
// ============================================================
// Random Roll
// ============================================================
/** CMSG_RANDOM_ROLL packet builder */
class RandomRollPacket {
public:
static network::Packet build(uint32_t minRoll, uint32_t maxRoll);
};
/** SMSG_RANDOM_ROLL data */
struct RandomRollData {
uint64_t rollerGuid = 0;
uint64_t targetGuid = 0; // 0 for party roll
uint32_t minRoll = 0;
uint32_t maxRoll = 0;
uint32_t result = 0;
};
/** SMSG_RANDOM_ROLL parser */
class RandomRollParser {
public:
static bool parse(network::Packet& packet, RandomRollData& data);
};
// ============================================================
// Phase 1: Foundation — Targeting, Name Queries
// ============================================================