diff --git a/include/game/spell_defines.hpp b/include/game/spell_defines.hpp index 874533f0..a57650e9 100644 --- a/include/game/spell_defines.hpp +++ b/include/game/spell_defines.hpp @@ -76,7 +76,7 @@ struct SpellCooldownEntry { /** * Get human-readable spell cast failure reason (WoW 3.3.5a SpellCastResult) */ -inline const char* getSpellCastResultString(uint8_t result) { +inline const char* getSpellCastResultString(uint8_t result, int powerType = -1) { // AzerothCore 3.3.5a SpellCastResult enum (SharedDefines.h) switch (result) { case 0: return nullptr; // SUCCESS — not a failure @@ -91,7 +91,7 @@ inline const char* getSpellCastResultString(uint8_t result) { case 9: return "Aura bounced"; case 10: return "Autotrack interrupted"; case 11: return "Bad implicit targets"; - case 12: return "Bad targets"; + case 12: return "Invalid target"; case 13: return "Can't be charmed"; case 14: return "Can't be disenchanted"; case 15: return "Can't be disenchanted (skill)"; @@ -126,11 +126,11 @@ inline const char* getSpellCastResultString(uint8_t result) { case 44: return "Item not found"; case 45: return "Item not ready"; case 46: return "Level requirement"; - case 47: return "Line of sight"; + case 47: return "Target not in line of sight"; case 48: return "Target too low level"; case 49: return "Low cast level"; case 50: return "Mainhand empty"; - case 51: return "Moving"; + case 51: return "Can't do that while moving"; case 52: return "Need ammo"; case 53: return "Need ammo pouch"; case 54: return "Need exotic ammo"; @@ -140,7 +140,7 @@ inline const char* getSpellCastResultString(uint8_t result) { case 58: return "Not fishable"; case 59: return "Not flying"; case 60: return "Not here"; - case 61: return "Not in front"; + case 61: return "Target needs to be in front of you"; case 62: return "Not in control"; case 63: return "Not known"; case 64: return "Not mounted"; @@ -157,14 +157,21 @@ inline const char* getSpellCastResultString(uint8_t result) { case 75: return "No ammo"; case 76: return "No charges remain"; case 77: return "No champion"; - case 78: return "No combo points"; + case 78: return "Not enough combo points"; case 79: return "No dueling"; case 80: return "No endurance"; case 81: return "No fish"; case 82: return "No items while shapeshifted"; case 83: return "No mounts allowed here"; case 84: return "No pet"; - case 85: return "Not enough mana"; + case 85: + switch (powerType) { + case 1: return "Not enough rage"; + case 2: return "Not enough focus"; + case 3: return "Not enough energy"; + case 6: return "Not enough runic power"; + default: return "Not enough mana"; + } case 86: return "Nothing to dispel"; case 87: return "Nothing to steal"; case 88: return "Only above water"; @@ -182,8 +189,8 @@ inline const char* getSpellCastResultString(uint8_t result) { case 100: return "Reagents required"; case 101: return "Requires area"; case 102: return "Requires spell focus"; - case 103: return "Rooted"; - case 104: return "Silenced"; + case 103: return "Can't do that while rooted"; + case 104: return "Can't do that while silenced"; case 105: return "Spell in progress"; case 106: return "Spell learned"; case 107: return "Spell unavailable"; diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index 9ea5c811..ef137ef1 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -4147,9 +4147,9 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { constexpr uint32_t UNIT_DYNFLAG_LOOTABLE = 0x0001; bool unitInitiallyDead = false; const uint16_t ufHealth = fieldIndex(UF::UNIT_FIELD_HEALTH); - const uint16_t ufPower = fieldIndex(UF::UNIT_FIELD_POWER1); + const uint16_t ufPowerBase = fieldIndex(UF::UNIT_FIELD_POWER1); const uint16_t ufMaxHealth = fieldIndex(UF::UNIT_FIELD_MAXHEALTH); - const uint16_t ufMaxPower = fieldIndex(UF::UNIT_FIELD_MAXPOWER1); + const uint16_t ufMaxPowerBase = fieldIndex(UF::UNIT_FIELD_MAXPOWER1); const uint16_t ufLevel = fieldIndex(UF::UNIT_FIELD_LEVEL); const uint16_t ufFaction = fieldIndex(UF::UNIT_FIELD_FACTIONTEMPLATE); const uint16_t ufFlags = fieldIndex(UF::UNIT_FIELD_FLAGS); @@ -4157,6 +4157,7 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { const uint16_t ufDisplayId = fieldIndex(UF::UNIT_FIELD_DISPLAYID); const uint16_t ufMountDisplayId = fieldIndex(UF::UNIT_FIELD_MOUNTDISPLAYID); const uint16_t ufNpcFlags = fieldIndex(UF::UNIT_NPC_FLAGS); + const uint16_t ufBytes0 = fieldIndex(UF::UNIT_FIELD_BYTES_0); for (const auto& [key, val] : block.fields) { if (key == ufHealth) { unit->setHealth(val); @@ -4167,9 +4168,14 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { playerDead_ = true; LOG_INFO("Player logged in dead"); } - } else if (key == ufPower) { unit->setPower(val); } - else if (key == ufMaxHealth) { unit->setMaxHealth(val); } - else if (key == ufMaxPower) { unit->setMaxPower(val); } + } else if (key == ufBytes0) { + unit->setPowerType(static_cast((val >> 24) & 0xFF)); + } else if (key >= ufPowerBase && key < ufPowerBase + 7) { + unit->setPowerByType(static_cast(key - ufPowerBase), val); + } else if (key == ufMaxHealth) { unit->setMaxHealth(val); } + else if (key >= ufMaxPowerBase && key < ufMaxPowerBase + 7) { + unit->setMaxPowerByType(static_cast(key - ufMaxPowerBase), val); + } else if (key == ufFaction) { unit->setFactionTemplate(val); } else if (key == ufFlags) { unit->setUnitFlags(val); } else if (key == ufDynFlags) { @@ -4505,9 +4511,9 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { bool npcDeathNotified = false; bool npcRespawnNotified = false; const uint16_t ufHealth = fieldIndex(UF::UNIT_FIELD_HEALTH); - const uint16_t ufPower = fieldIndex(UF::UNIT_FIELD_POWER1); + const uint16_t ufPowerBase = fieldIndex(UF::UNIT_FIELD_POWER1); const uint16_t ufMaxHealth = fieldIndex(UF::UNIT_FIELD_MAXHEALTH); - const uint16_t ufMaxPower = fieldIndex(UF::UNIT_FIELD_MAXPOWER1); + const uint16_t ufMaxPowerBase = fieldIndex(UF::UNIT_FIELD_MAXPOWER1); const uint16_t ufLevel = fieldIndex(UF::UNIT_FIELD_LEVEL); const uint16_t ufFaction = fieldIndex(UF::UNIT_FIELD_FACTIONTEMPLATE); const uint16_t ufFlags = fieldIndex(UF::UNIT_FIELD_FLAGS); @@ -4515,6 +4521,7 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { const uint16_t ufDisplayId = fieldIndex(UF::UNIT_FIELD_DISPLAYID); const uint16_t ufMountDisplayId = fieldIndex(UF::UNIT_FIELD_MOUNTDISPLAYID); const uint16_t ufNpcFlags = fieldIndex(UF::UNIT_NPC_FLAGS); + const uint16_t ufBytes0 = fieldIndex(UF::UNIT_FIELD_BYTES_0); for (const auto& [key, val] : block.fields) { if (key == ufHealth) { uint32_t oldHealth = unit->getHealth(); @@ -4548,9 +4555,14 @@ void GameHandler::handleUpdateObject(network::Packet& packet) { npcRespawnNotified = true; } } - } else if (key == ufPower) { unit->setPower(val); } - else if (key == ufMaxHealth) { unit->setMaxHealth(val); } - else if (key == ufMaxPower) { unit->setMaxPower(val); } + } else if (key == ufBytes0) { + unit->setPowerType(static_cast((val >> 24) & 0xFF)); + } else if (key >= ufPowerBase && key < ufPowerBase + 7) { + unit->setPowerByType(static_cast(key - ufPowerBase), val); + } else if (key == ufMaxHealth) { unit->setMaxHealth(val); } + else if (key >= ufMaxPowerBase && key < ufMaxPowerBase + 7) { + unit->setMaxPowerByType(static_cast(key - ufMaxPowerBase), val); + } else if (key == ufFlags) { unit->setUnitFlags(val); } else if (key == ufDynFlags) { uint32_t oldDyn = unit->getDynamicFlags(); @@ -8109,7 +8121,12 @@ void GameHandler::handleCastFailed(network::Packet& packet) { castTimeRemaining = 0.0f; // Add system message about failed cast with readable reason - const char* reason = getSpellCastResultString(data.result); + int powerType = -1; + auto playerEntity = entityManager.getEntity(playerGuid); + if (auto playerUnit = std::dynamic_pointer_cast(playerEntity)) { + powerType = playerUnit->getPowerType(); + } + const char* reason = getSpellCastResultString(data.result, powerType); MessageChatData msg; msg.type = ChatType::SYSTEM; msg.language = ChatLanguage::UNIVERSAL; diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index fe3ca219..e4b7c140 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -1054,55 +1054,27 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) { } if (msg.type == game::ChatType::SYSTEM) { - if (!tsPrefix.empty()) { - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6f, 0.6f, 0.6f, 1.0f)); - ImGui::TextWrapped("%s", tsPrefix.c_str()); - ImGui::PopStyleColor(); - ImGui::SameLine(0, 0); - } - renderTextWithLinks(processedMessage, color); + renderTextWithLinks(tsPrefix + processedMessage, color); } else if (msg.type == game::ChatType::TEXT_EMOTE) { - if (!tsPrefix.empty()) { - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.6f, 0.6f, 0.6f, 1.0f)); - ImGui::TextWrapped("%s", tsPrefix.c_str()); - ImGui::PopStyleColor(); - ImGui::SameLine(0, 0); - } - renderTextWithLinks(processedMessage, color); + renderTextWithLinks(tsPrefix + processedMessage, color); } else if (!msg.senderName.empty()) { if (msg.type == game::ChatType::MONSTER_SAY || msg.type == game::ChatType::MONSTER_YELL) { - std::string prefix = tsPrefix + msg.senderName + " says: "; - ImGui::PushStyleColor(ImGuiCol_Text, color); - ImGui::TextWrapped("%s", prefix.c_str()); - ImGui::PopStyleColor(); - ImGui::SameLine(0, 0); - renderTextWithLinks(processedMessage, color); + std::string fullMsg = tsPrefix + msg.senderName + " says: " + processedMessage; + renderTextWithLinks(fullMsg, color); } else if (msg.type == game::ChatType::CHANNEL && !msg.channelName.empty()) { int chIdx = gameHandler.getChannelIndex(msg.channelName); std::string chDisplay = chIdx > 0 ? "[" + std::to_string(chIdx) + ". " + msg.channelName + "]" : "[" + msg.channelName + "]"; - std::string prefix = tsPrefix + chDisplay + " [" + msg.senderName + "]: "; - ImGui::PushStyleColor(ImGuiCol_Text, color); - ImGui::TextWrapped("%s", prefix.c_str()); - ImGui::PopStyleColor(); - ImGui::SameLine(0, 0); - renderTextWithLinks(processedMessage, color); + std::string fullMsg = tsPrefix + chDisplay + " [" + msg.senderName + "]: " + processedMessage; + renderTextWithLinks(fullMsg, color); } else { - std::string prefix = tsPrefix + "[" + std::string(getChatTypeName(msg.type)) + "] " + msg.senderName + ": "; - ImGui::PushStyleColor(ImGuiCol_Text, color); - ImGui::TextWrapped("%s", prefix.c_str()); - ImGui::PopStyleColor(); - ImGui::SameLine(0, 0); - renderTextWithLinks(processedMessage, color); + std::string fullMsg = tsPrefix + "[" + std::string(getChatTypeName(msg.type)) + "] " + msg.senderName + ": " + processedMessage; + renderTextWithLinks(fullMsg, color); } } else { - std::string prefix = tsPrefix + "[" + std::string(getChatTypeName(msg.type)) + "] "; - ImGui::PushStyleColor(ImGuiCol_Text, color); - ImGui::TextWrapped("%s", prefix.c_str()); - ImGui::PopStyleColor(); - ImGui::SameLine(0, 0); - renderTextWithLinks(processedMessage, color); + std::string fullMsg = tsPrefix + "[" + std::string(getChatTypeName(msg.type)) + "] " + processedMessage; + renderTextWithLinks(fullMsg, color); } }