diff --git a/include/game/spell_defines.hpp b/include/game/spell_defines.hpp index ffaf6bb2..10c4a5cd 100644 --- a/include/game/spell_defines.hpp +++ b/include/game/spell_defines.hpp @@ -74,6 +74,7 @@ struct CombatLogEntry { int32_t amount = 0; uint32_t spellId = 0; bool isPlayerSource = false; + uint8_t powerType = 0; // For ENERGIZE/DRAIN: power type; for ENVIRONMENTAL: env damage type time_t timestamp = 0; // Wall-clock time (std::time(nullptr)) std::string sourceName; // Resolved display name of attacker/caster std::string targetName; // Resolved display name of victim/target diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index b1ae2ece..21c146d2 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -4259,17 +4259,17 @@ void GameHandler::handlePacket(network::Packet& packet) { } case Opcode::SMSG_ENVIRONMENTAL_DAMAGE_LOG: { // uint64 victimGuid + uint8 envDmgType + uint32 damage + uint32 absorbed + uint32 resisted - // envDmgType: 1=Exhausted(fatigue), 2=Drowning, 3=Fall, 4=Lava, 5=Slime, 6=Fire + // envDmgType: 0=Exhausted(fatigue), 1=Drowning, 2=Fall, 3=Lava, 4=Slime, 5=Fire if (packet.getSize() - packet.getReadPos() < 21) { packet.setReadPos(packet.getSize()); break; } uint64_t victimGuid = packet.readUInt64(); - /*uint8_t envType =*/ packet.readUInt8(); + uint8_t envType = packet.readUInt8(); uint32_t dmg = packet.readUInt32(); uint32_t envAbs = packet.readUInt32(); uint32_t envRes = packet.readUInt32(); if (victimGuid == playerGuid) { - // Environmental damage: no caster GUID, victim = player + // Environmental damage: pass envType via powerType field for display differentiation if (dmg > 0) - addCombatText(CombatTextEntry::ENVIRONMENTAL, static_cast(dmg), 0, false, 0, 0, victimGuid); + addCombatText(CombatTextEntry::ENVIRONMENTAL, static_cast(dmg), 0, false, envType, 0, victimGuid); if (envAbs > 0) addCombatText(CombatTextEntry::ABSORB, static_cast(envAbs), 0, false, 0, 0, victimGuid); if (envRes > 0) @@ -15160,6 +15160,7 @@ void GameHandler::addCombatText(CombatTextEntry::Type type, int32_t amount, uint log.amount = amount; log.spellId = spellId; log.isPlayerSource = isPlayerSource; + log.powerType = powerType; log.timestamp = std::time(nullptr); // If the caller provided an explicit destination GUID but left source GUID as 0, // preserve "unknown/no source" (e.g. environmental damage) instead of diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index 2dfb55b0..315c15e2 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -8467,10 +8467,21 @@ void GameScreen::renderCombatText(game::GameHandler& gameHandler) { snprintf(text, sizeof(text), "+%d", entry.amount); color = ImVec4(0.4f, 1.0f, 0.5f, alpha); break; - case game::CombatTextEntry::ENVIRONMENTAL: - snprintf(text, sizeof(text), "-%d", entry.amount); + case game::CombatTextEntry::ENVIRONMENTAL: { + const char* envLabel = ""; + switch (entry.powerType) { + case 0: envLabel = "Fatigue "; break; + case 1: envLabel = "Drowning "; break; + case 2: envLabel = ""; break; // Fall: just show the number (WoW convention) + case 3: envLabel = "Lava "; break; + case 4: envLabel = "Slime "; break; + case 5: envLabel = "Fire "; break; + default: envLabel = ""; break; + } + snprintf(text, sizeof(text), "%s-%d", envLabel, entry.amount); color = ImVec4(0.9f, 0.5f, 0.2f, alpha); // Orange for environmental break; + } case game::CombatTextEntry::ENERGIZE: snprintf(text, sizeof(text), "+%d", entry.amount); switch (entry.powerType) { @@ -20538,10 +20549,20 @@ void GameScreen::renderCombatLog(game::GameHandler& gameHandler) { snprintf(desc, sizeof(desc), "%s reflects %s's attack", tgt, src); color = ImVec4(0.8f, 0.7f, 1.0f, 1.0f); break; - case T::ENVIRONMENTAL: - snprintf(desc, sizeof(desc), "Environmental damage: %d", e.amount); + case T::ENVIRONMENTAL: { + const char* envName = "Environmental"; + switch (e.powerType) { + case 0: envName = "Fatigue"; break; + case 1: envName = "Drowning"; break; + case 2: envName = "Falling"; break; + case 3: envName = "Lava"; break; + case 4: envName = "Slime"; break; + case 5: envName = "Fire"; break; + } + snprintf(desc, sizeof(desc), "%s damage: %d", envName, e.amount); color = ImVec4(1.0f, 0.5f, 0.2f, 1.0f); break; + } case T::ENERGIZE: if (spell) snprintf(desc, sizeof(desc), "%s gains %d power (%s)", tgt, e.amount, spell);