mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 01:23:51 +00:00
Restructure inventory UI, add vendor selling, camera intro on all spawns, and quest log
Split inventory into bags-only (B key) and character screen (C key). Vendor window auto-opens bags with sell prices on hover and right-click to sell. Add camera intro pan on all login/spawn/teleport/hearthstone events and idle orbit after 2 minutes. Add quest log UI, SMSG_MONSTER_MOVE handling, deferred creature spawn queue, and creature fade-in/movement interpolation for online mode.
This commit is contained in:
parent
bb4c2c25f7
commit
71c3d2ea77
21 changed files with 1092 additions and 149 deletions
|
|
@ -294,6 +294,11 @@ public:
|
|||
using CreatureDespawnCallback = std::function<void(uint64_t guid)>;
|
||||
void setCreatureDespawnCallback(CreatureDespawnCallback cb) { creatureDespawnCallback_ = std::move(cb); }
|
||||
|
||||
// Creature move callback (online mode - triggered by SMSG_MONSTER_MOVE)
|
||||
// Parameters: guid, x, y, z (canonical), duration_ms (0 = instant)
|
||||
using CreatureMoveCallback = std::function<void(uint64_t guid, float x, float y, float z, uint32_t durationMs)>;
|
||||
void setCreatureMoveCallback(CreatureMoveCallback cb) { creatureMoveCallback_ = std::move(cb); }
|
||||
|
||||
// Cooldowns
|
||||
float getSpellCooldown(uint32_t spellId) const;
|
||||
|
||||
|
|
@ -330,17 +335,33 @@ public:
|
|||
bool isQuestDetailsOpen() const { return questDetailsOpen; }
|
||||
const QuestDetailsData& getQuestDetails() const { return currentQuestDetails; }
|
||||
|
||||
// Quest log
|
||||
struct QuestLogEntry {
|
||||
uint32_t questId = 0;
|
||||
std::string title;
|
||||
std::string objectives;
|
||||
bool complete = false;
|
||||
};
|
||||
const std::vector<QuestLogEntry>& getQuestLog() const { return questLog_; }
|
||||
void abandonQuest(uint32_t questId);
|
||||
|
||||
// Vendor
|
||||
void openVendor(uint64_t npcGuid);
|
||||
void closeVendor();
|
||||
void buyItem(uint64_t vendorGuid, uint32_t itemId, uint32_t slot, uint8_t count);
|
||||
void sellItem(uint64_t vendorGuid, uint64_t itemGuid, uint8_t count);
|
||||
void sellItemBySlot(int backpackIndex);
|
||||
bool isVendorWindowOpen() const { return vendorWindowOpen; }
|
||||
const ListInventoryData& getVendorItems() const { return currentVendorItems; }
|
||||
const ItemQueryResponseData* getItemInfo(uint32_t itemId) const {
|
||||
auto it = itemInfoCache_.find(itemId);
|
||||
return (it != itemInfoCache_.end()) ? &it->second : nullptr;
|
||||
}
|
||||
uint64_t getBackpackItemGuid(int index) const {
|
||||
if (index < 0 || index >= static_cast<int>(backpackSlotGuids_.size())) return 0;
|
||||
return backpackSlotGuids_[index];
|
||||
}
|
||||
uint64_t getVendorGuid() const { return currentVendorItems.vendorGuid; }
|
||||
|
||||
/**
|
||||
* Set callbacks
|
||||
|
|
@ -464,6 +485,9 @@ private:
|
|||
// ---- XP handler ----
|
||||
void handleXpGain(network::Packet& packet);
|
||||
|
||||
// ---- Creature movement handler ----
|
||||
void handleMonsterMove(network::Packet& packet);
|
||||
|
||||
// ---- Phase 5 handlers ----
|
||||
void handleLootResponse(network::Packet& packet);
|
||||
void handleLootReleaseResponse(network::Packet& packet);
|
||||
|
|
@ -580,6 +604,7 @@ private:
|
|||
WorldEntryCallback worldEntryCallback_;
|
||||
CreatureSpawnCallback creatureSpawnCallback_;
|
||||
CreatureDespawnCallback creatureDespawnCallback_;
|
||||
CreatureMoveCallback creatureMoveCallback_;
|
||||
std::vector<uint32_t> knownSpells;
|
||||
std::unordered_map<uint32_t, float> spellCooldowns; // spellId -> remaining seconds
|
||||
uint8_t castCount = 0;
|
||||
|
|
@ -616,6 +641,9 @@ private:
|
|||
bool questDetailsOpen = false;
|
||||
QuestDetailsData currentQuestDetails;
|
||||
|
||||
// Quest log
|
||||
std::vector<QuestLogEntry> questLog_;
|
||||
|
||||
// Vendor
|
||||
bool vendorWindowOpen = false;
|
||||
ListInventoryData currentVendorItems;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ enum class Opcode : uint16_t {
|
|||
// ---- XP ----
|
||||
SMSG_LOG_XPGAIN = 0x1D0,
|
||||
|
||||
// ---- Creature Movement ----
|
||||
SMSG_MONSTER_MOVE = 0x0DD,
|
||||
|
||||
// ---- Phase 2: Combat Core ----
|
||||
CMSG_ATTACKSWING = 0x141,
|
||||
CMSG_ATTACKSTOP = 0x142,
|
||||
|
|
@ -146,6 +149,7 @@ enum class Opcode : uint16_t {
|
|||
SMSG_QUESTGIVER_OFFER_REWARD = 0x18D,
|
||||
CMSG_QUESTGIVER_CHOOSE_REWARD = 0x18E,
|
||||
SMSG_QUESTGIVER_QUEST_COMPLETE = 0x191,
|
||||
CMSG_QUESTLOG_REMOVE_QUEST = 0x194,
|
||||
|
||||
// ---- Phase 5: Vendor ----
|
||||
CMSG_LIST_INVENTORY = 0x19E,
|
||||
|
|
|
|||
|
|
@ -740,6 +740,7 @@ struct ItemQueryResponseData {
|
|||
int32_t agility = 0;
|
||||
int32_t intellect = 0;
|
||||
int32_t spirit = 0;
|
||||
uint32_t sellPrice = 0;
|
||||
std::string subclassName;
|
||||
bool valid = false;
|
||||
};
|
||||
|
|
@ -754,6 +755,25 @@ public:
|
|||
// Phase 2: Combat Core
|
||||
// ============================================================
|
||||
|
||||
/** SMSG_MONSTER_MOVE data */
|
||||
struct MonsterMoveData {
|
||||
uint64_t guid = 0;
|
||||
float x = 0, y = 0, z = 0; // Current position (server coords)
|
||||
uint8_t moveType = 0; // 0=Normal, 1=Stop, 2=FacingSpot, 3=FacingTarget, 4=FacingAngle
|
||||
float facingAngle = 0;
|
||||
uint64_t facingTarget = 0;
|
||||
uint32_t splineFlags = 0;
|
||||
uint32_t duration = 0;
|
||||
// Destination (final point of the spline, server coords)
|
||||
float destX = 0, destY = 0, destZ = 0;
|
||||
bool hasDest = false;
|
||||
};
|
||||
|
||||
class MonsterMoveParser {
|
||||
public:
|
||||
static bool parse(network::Packet& packet, MonsterMoveData& data);
|
||||
};
|
||||
|
||||
/** CMSG_ATTACKSWING packet builder */
|
||||
class AttackSwingPacket {
|
||||
public:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue