Implement mailbox interaction and expansion-aware mail system

Fix mailbox right-click (transposed CMSG_GAMEOBJECT_USE opcode, missing
mail opcodes in Turtle WoW JSON, decorative GO type filtering). Add
expansion-aware mail packet handling via PacketParsers: Classic format
(single item, no msgSize prefix, Vanilla field order) vs WotLK format
(attachment arrays, enchant slots). Fix CMSG_MAIL_TAKE_ITEM and
CMSG_MAIL_DELETE for Vanilla (no trailing fields). Add pulsing "New
Mail" indicator below minimap, SMSG_RECEIVED_MAIL and
MSG_QUERY_NEXT_MAIL_TIME handlers, and async sender name backfill.
This commit is contained in:
Kelsi 2026-02-16 18:46:44 -08:00
parent bbcc18aa22
commit 1cfe186c62
8 changed files with 421 additions and 126 deletions

View file

@ -1199,8 +1199,14 @@ void GameScreen::processTargetInput(game::GameHandler& gameHandler) {
heightOffset = 0.3f;
}
} else if (t == game::ObjectType::GAMEOBJECT) {
hitRadius = 1.2f;
heightOffset = 0.8f;
// Check GO type — skip non-interactable decorations
auto go = std::static_pointer_cast<game::GameObject>(entity);
auto* goInfo = gameHandler.getCachedGameObjectInfo(go->getEntry());
uint32_t goType = goInfo ? goInfo->type : 0;
// Type 5 = GENERIC (decorations), skip
if (goType == 5) continue;
hitRadius = 2.5f;
heightOffset = 1.2f;
}
hitCenter = core::coords::canonicalToRender(glm::vec3(entity->getX(), entity->getY(), entity->getZ()));
hitCenter.z += heightOffset;
@ -1262,8 +1268,14 @@ void GameScreen::processTargetInput(game::GameHandler& gameHandler) {
heightOffset = 0.3f;
}
} else if (t == game::ObjectType::GAMEOBJECT) {
hitRadius = 1.2f;
heightOffset = 0.8f;
// Check GO type — skip non-interactable decorations
auto go = std::static_pointer_cast<game::GameObject>(entity);
auto* goInfo = gameHandler.getCachedGameObjectInfo(go->getEntry());
uint32_t goType = goInfo ? goInfo->type : 0;
// Type 5 = GENERIC (decorations), skip
if (goType == 5) continue;
hitRadius = 2.5f;
heightOffset = 1.2f;
}
hitCenter = core::coords::canonicalToRender(
glm::vec3(entity->getX(), entity->getY(), entity->getZ()));
@ -5728,6 +5740,23 @@ void GameScreen::renderMinimapMarkers(game::GameHandler& gameHandler) {
ImGui::PopStyleVar(2);
}
ImGui::End();
// "New Mail" indicator below the minimap
if (gameHandler.hasNewMail()) {
float indicatorX = centerX - mapRadius;
float indicatorY = centerY + mapRadius + 4.0f;
ImGui::SetNextWindowPos(ImVec2(indicatorX, indicatorY), ImGuiCond_Always);
ImGui::SetNextWindowSize(ImVec2(mapRadius * 2.0f, 22), ImGuiCond_Always);
ImGuiWindowFlags mailFlags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoInputs;
if (ImGui::Begin("##NewMailIndicator", nullptr, mailFlags)) {
// Pulsing effect
float pulse = 0.7f + 0.3f * std::sin(static_cast<float>(ImGui::GetTime()) * 3.0f);
ImGui::TextColored(ImVec4(1.0f, 0.85f, 0.0f, pulse), "New Mail!");
}
ImGui::End();
}
}
std::string GameScreen::getSettingsPath() {