mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 01:23:51 +00:00
Add movement packed GUID, inventory money display, and character screen buttons
Fix movement packets to include packed player GUID prefix so the server tracks position. Fix inventory money display being clipped by child panels. Add Back and Delete Character buttons to character selection screen with two-step delete confirmation.
This commit is contained in:
parent
e327344a9b
commit
20f89b2d4a
9 changed files with 156 additions and 15 deletions
|
|
@ -894,6 +894,15 @@ void GameHandler::handlePacket(network::Packet& packet) {
|
|||
handleCharCreateResponse(packet);
|
||||
break;
|
||||
|
||||
case Opcode::SMSG_CHAR_DELETE: {
|
||||
uint8_t result = packet.readUInt8();
|
||||
bool success = (result == 0x47); // CHAR_DELETE_SUCCESS
|
||||
LOG_INFO("SMSG_CHAR_DELETE result: ", (int)result, success ? " (success)" : " (failed)");
|
||||
if (success) requestCharacterList();
|
||||
if (charDeleteCallback_) charDeleteCallback_(success);
|
||||
break;
|
||||
}
|
||||
|
||||
case Opcode::SMSG_CHAR_ENUM:
|
||||
if (state == WorldState::CHAR_LIST_REQUESTED) {
|
||||
handleCharEnum(packet);
|
||||
|
|
@ -1393,6 +1402,45 @@ void GameHandler::handleCharCreateResponse(network::Packet& packet) {
|
|||
}
|
||||
}
|
||||
|
||||
void GameHandler::deleteCharacter(uint64_t characterGuid) {
|
||||
if (singlePlayerMode_) {
|
||||
// Remove from local list
|
||||
characters.erase(
|
||||
std::remove_if(characters.begin(), characters.end(),
|
||||
[characterGuid](const Character& c) { return c.guid == characterGuid; }),
|
||||
characters.end());
|
||||
// Remove from database
|
||||
auto& sp = getSinglePlayerSqlite();
|
||||
if (sp.db) {
|
||||
const char* sql = "DELETE FROM characters WHERE guid=?";
|
||||
sqlite3_stmt* stmt = nullptr;
|
||||
if (sqlite3_prepare_v2(sp.db, sql, -1, &stmt, nullptr) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(stmt, 1, static_cast<sqlite3_int64>(characterGuid));
|
||||
sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
const char* sql2 = "DELETE FROM character_inventory WHERE guid=?";
|
||||
if (sqlite3_prepare_v2(sp.db, sql2, -1, &stmt, nullptr) == SQLITE_OK) {
|
||||
sqlite3_bind_int64(stmt, 1, static_cast<sqlite3_int64>(characterGuid));
|
||||
sqlite3_step(stmt);
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
}
|
||||
if (charDeleteCallback_) charDeleteCallback_(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!socket) {
|
||||
if (charDeleteCallback_) charDeleteCallback_(false);
|
||||
return;
|
||||
}
|
||||
|
||||
network::Packet packet(static_cast<uint16_t>(Opcode::CMSG_CHAR_DELETE));
|
||||
packet.writeUInt64(characterGuid);
|
||||
socket->send(packet);
|
||||
LOG_INFO("CMSG_CHAR_DELETE sent for GUID: 0x", std::hex, characterGuid, std::dec);
|
||||
}
|
||||
|
||||
const Character* GameHandler::getActiveCharacter() const {
|
||||
if (activeCharacterGuid_ == 0) return nullptr;
|
||||
for (const auto& ch : characters) {
|
||||
|
|
@ -2262,7 +2310,7 @@ void GameHandler::sendMovement(Opcode opcode) {
|
|||
wireInfo.z = serverPos.z;
|
||||
|
||||
// Build and send movement packet
|
||||
auto packet = MovementPacket::build(opcode, wireInfo);
|
||||
auto packet = MovementPacket::build(opcode, wireInfo, playerGuid);
|
||||
socket->send(packet);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -517,16 +517,33 @@ bool PongParser::parse(network::Packet& packet, PongData& data) {
|
|||
return true;
|
||||
}
|
||||
|
||||
network::Packet MovementPacket::build(Opcode opcode, const MovementInfo& info) {
|
||||
network::Packet MovementPacket::build(Opcode opcode, const MovementInfo& info, uint64_t playerGuid) {
|
||||
network::Packet packet(static_cast<uint16_t>(opcode));
|
||||
|
||||
// Movement packet format (WoW 3.3.5a):
|
||||
// packed GUID
|
||||
// uint32 flags
|
||||
// uint16 flags2
|
||||
// uint32 time
|
||||
// float x, y, z
|
||||
// float orientation
|
||||
|
||||
// Write packed GUID
|
||||
uint8_t mask = 0;
|
||||
uint8_t guidBytes[8];
|
||||
int guidByteCount = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uint8_t byte = static_cast<uint8_t>((playerGuid >> (i * 8)) & 0xFF);
|
||||
if (byte != 0) {
|
||||
mask |= (1 << i);
|
||||
guidBytes[guidByteCount++] = byte;
|
||||
}
|
||||
}
|
||||
packet.writeUInt8(mask);
|
||||
for (int i = 0; i < guidByteCount; i++) {
|
||||
packet.writeUInt8(guidBytes[i]);
|
||||
}
|
||||
|
||||
// Write movement flags
|
||||
packet.writeUInt32(info.flags);
|
||||
packet.writeUInt16(info.flags2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue