fix: inspect (packed GUID), follow (client-side auto-walk); add loot/raid commands

Inspect: CMSG_INSPECT was writing full uint64 GUID instead of packed GUID.
Server silently rejected the malformed packet. Fixed both InspectPacket and
QueryInspectAchievementsPacket to use writePackedGuid().

Follow: was a no-op (only stored GUID). Added client-side auto-follow system:
camera controller walks toward followed entity, faces target, cancels on
WASD/mouse input, stops within 3 units, cancels at 40+ units distance.

Party commands:
- /lootmethod (ffa/roundrobin/master/group/nbg) sends CMSG_LOOT_METHOD
- /lootthreshold (0-5 or quality name) sets minimum loot quality
- /raidconvert converts party to raid (leader only)

Equipment diagnostic logging still active for debugging naked players.
This commit is contained in:
Kelsi 2026-03-27 17:54:56 -07:00
parent 16fc3ebfdf
commit b366773f29
8 changed files with 264 additions and 8 deletions

View file

@ -1122,6 +1122,10 @@ public:
using CameraShakeCallback = std::function<void(float magnitude, float frequency, float duration)>;
void setCameraShakeCallback(CameraShakeCallback cb) { cameraShakeCallback_ = std::move(cb); }
// Auto-follow callback: pass render-space position pointer to start, nullptr to cancel.
using AutoFollowCallback = std::function<void(const glm::vec3* renderPos)>;
void setAutoFollowCallback(AutoFollowCallback cb) { autoFollowCallback_ = std::move(cb); }
// Unstuck callback (resets player Z to floor height)
using UnstuckCallback = std::function<void()>;
void setUnstuckCallback(UnstuckCallback cb) { unstuckCallback_ = std::move(cb); }
@ -1352,6 +1356,8 @@ public:
void acceptGroupInvite();
void declineGroupInvite();
void leaveGroup();
void convertToRaid();
void sendSetLootMethod(uint32_t method, uint32_t threshold, uint64_t masterLooterGuid);
bool isInGroup() const { return !partyData.isEmpty(); }
const GroupListData& getPartyData() const { return partyData; }
const std::vector<ContactEntry>& getContacts() const { return contacts_; }
@ -2812,6 +2818,7 @@ private:
// ---- Follow state ----
uint64_t followTargetGuid_ = 0;
glm::vec3 followRenderPos_{0.0f}; // Render-space position of followed entity (updated each frame)
// ---- AFK/DND status ----
bool afkStatus_ = false;
@ -2905,6 +2912,7 @@ private:
WorldEntryCallback worldEntryCallback_;
KnockBackCallback knockBackCallback_;
CameraShakeCallback cameraShakeCallback_;
AutoFollowCallback autoFollowCallback_;
UnstuckCallback unstuckCallback_;
UnstuckCallback unstuckGyCallback_;
UnstuckCallback unstuckHearthCallback_;

View file

@ -1315,6 +1315,23 @@ public:
static network::Packet build();
};
/** CMSG_GROUP_RAID_CONVERT packet builder */
class GroupRaidConvertPacket {
public:
static network::Packet build();
};
/** CMSG_LOOT_METHOD packet builder */
class SetLootMethodPacket {
public:
/**
* @param method 0=FFA, 1=RoundRobin, 2=MasterLoot, 3=GroupLoot, 4=NeedBeforeGreed
* @param threshold item quality threshold (0-6)
* @param masterLooterGuid GUID of master looter (only relevant for method=2)
*/
static network::Packet build(uint32_t method, uint32_t threshold, uint64_t masterLooterGuid);
};
/** MSG_RAID_TARGET_UPDATE packet builder */
class RaidTargetUpdatePacket {
public: