refactor: extract toHexString utility, more color constants, final cast cleanup

Add core::toHexString() utility in logger.hpp to replace 11 duplicate
hex-dump loops across world_packets, world_socket, and game_handler.
Add kColorBrightGreen/kColorDarkGray constants in game_screen.cpp
replacing 26 inline literals. Replace remaining ~37 C-style casts in
16 files. Normalize keybinding_manager.hpp to #pragma once.
This commit is contained in:
Kelsi 2026-03-25 12:12:03 -07:00
parent ba99d505dd
commit eea205ffc9
5 changed files with 63 additions and 96 deletions

View file

@ -7,6 +7,8 @@
#include <fstream> #include <fstream>
#include <chrono> #include <chrono>
#include <atomic> #include <atomic>
#include <cstdio>
#include <cstdint>
namespace wowee { namespace wowee {
namespace core { namespace core {
@ -144,6 +146,17 @@ private:
} \ } \
} while (0) } while (0)
inline std::string toHexString(const uint8_t* data, size_t len, bool spaces = false) {
std::string s;
s.reserve(len * (spaces ? 3 : 2));
for (size_t i = 0; i < len; ++i) {
char buf[4];
std::snprintf(buf, sizeof(buf), spaces ? "%02x " : "%02x", data[i]);
s += buf;
}
return s;
}
} // namespace core } // namespace core
} // namespace wowee } // namespace wowee

View file

@ -703,11 +703,8 @@ bool GameHandler::connect(const std::string& host,
this->realmId_ = realmId; this->realmId_ = realmId;
// Diagnostic: dump session key for AUTH_REJECT debugging // Diagnostic: dump session key for AUTH_REJECT debugging
{ LOG_INFO("GameHandler session key (", sessionKey.size(), "): ",
std::string hex; core::toHexString(sessionKey.data(), sessionKey.size()));
for (uint8_t b : sessionKey) { char buf[4]; snprintf(buf, sizeof(buf), "%02x", b); hex += buf; }
LOG_INFO("GameHandler session key (", sessionKey.size(), "): ", hex);
}
requiresWarden_ = false; requiresWarden_ = false;
wardenGateSeen_ = false; wardenGateSeen_ = false;
wardenGateElapsed_ = 0.0f; wardenGateElapsed_ = 0.0f;

View file

@ -200,15 +200,8 @@ network::Packet AuthSessionPacket::build(uint32_t build,
LOG_INFO("CMSG_AUTH_SESSION packet built: ", packet.getSize(), " bytes"); LOG_INFO("CMSG_AUTH_SESSION packet built: ", packet.getSize(), " bytes");
// Dump full packet for protocol debugging // Dump full packet for protocol debugging
const auto& data = packet.getData(); LOG_DEBUG("CMSG_AUTH_SESSION full dump:\n",
std::string hexDump; core::toHexString(packet.getData().data(), packet.getData().size(), true));
for (size_t i = 0; i < data.size(); ++i) {
char buf[4];
snprintf(buf, sizeof(buf), "%02x ", data[i]);
hexDump += buf;
if ((i + 1) % 16 == 0) hexDump += "\n";
}
LOG_DEBUG("CMSG_AUTH_SESSION full dump:\n", hexDump);
return packet; return packet;
} }
@ -249,33 +242,14 @@ std::vector<uint8_t> AuthSessionPacket::computeAuthHash(
hashInput.insert(hashInput.end(), sessionKey.begin(), sessionKey.end()); hashInput.insert(hashInput.end(), sessionKey.begin(), sessionKey.end());
// Diagnostic: dump auth hash inputs for debugging AUTH_REJECT // Diagnostic: dump auth hash inputs for debugging AUTH_REJECT
{ LOG_DEBUG("AUTH HASH: account='", accountName, "' clientSeed=0x", std::hex, clientSeed,
auto toHex = [](const uint8_t* data, size_t len) { " serverSeed=0x", serverSeed, std::dec);
std::string s; LOG_DEBUG("AUTH HASH: sessionKey=", core::toHexString(sessionKey.data(), sessionKey.size()));
for (size_t i = 0; i < len; ++i) { LOG_DEBUG("AUTH HASH: input(", hashInput.size(), ")=", core::toHexString(hashInput.data(), hashInput.size()));
char buf[4]; snprintf(buf, sizeof(buf), "%02x", data[i]); s += buf;
}
return s;
};
LOG_DEBUG("AUTH HASH: account='", accountName, "' clientSeed=0x", std::hex, clientSeed,
" serverSeed=0x", serverSeed, std::dec);
LOG_DEBUG("AUTH HASH: sessionKey=", toHex(sessionKey.data(), sessionKey.size()));
LOG_DEBUG("AUTH HASH: input(", hashInput.size(), ")=", toHex(hashInput.data(), hashInput.size()));
}
// Compute SHA1 hash // Compute SHA1 hash
auto result = auth::Crypto::sha1(hashInput); auto result = auth::Crypto::sha1(hashInput);
LOG_DEBUG("AUTH HASH: digest=", core::toHexString(result.data(), result.size()));
{
auto toHex = [](const uint8_t* data, size_t len) {
std::string s;
for (size_t i = 0; i < len; ++i) {
char buf[4]; snprintf(buf, sizeof(buf), "%02x", data[i]); s += buf;
}
return s;
};
LOG_DEBUG("AUTH HASH: digest=", toHex(result.data(), result.size()));
}
return result; return result;
} }
@ -420,14 +394,8 @@ network::Packet CharCreatePacket::build(const CharCreateData& data) {
" facial=", static_cast<int>(data.facialHair)); " facial=", static_cast<int>(data.facialHair));
// Dump full packet for protocol debugging // Dump full packet for protocol debugging
const auto& pktData = packet.getData(); LOG_DEBUG("CMSG_CHAR_CREATE full dump: ",
std::string hexDump; core::toHexString(packet.getData().data(), packet.getData().size(), true));
for (size_t i = 0; i < pktData.size(); ++i) {
char buf[4];
snprintf(buf, sizeof(buf), "%02x ", pktData[i]);
hexDump += buf;
}
LOG_DEBUG("CMSG_CHAR_CREATE full dump: ", hexDump);
return packet; return packet;
} }

View file

@ -360,13 +360,8 @@ void WorldSocket::send(const Packet& packet) {
} }
if (kLogSwapItemPackets && (opcode == 0x10C || opcode == 0x10D)) { // CMSG_SWAP_ITEM / CMSG_SWAP_INV_ITEM if (kLogSwapItemPackets && (opcode == 0x10C || opcode == 0x10D)) { // CMSG_SWAP_ITEM / CMSG_SWAP_INV_ITEM
std::string hex; LOG_INFO("WS TX opcode=0x", std::hex, opcode, std::dec, " payloadLen=", payloadLen,
for (size_t i = 0; i < data.size(); i++) { " data=[", core::toHexString(data.data(), data.size(), true), "]");
char buf[4];
snprintf(buf, sizeof(buf), "%02x ", data[i]);
hex += buf;
}
LOG_INFO("WS TX opcode=0x", std::hex, opcode, std::dec, " payloadLen=", payloadLen, " data=[", hex, "]");
} }
const auto traceNow = std::chrono::steady_clock::now(); const auto traceNow = std::chrono::steady_clock::now();
@ -418,14 +413,8 @@ void WorldSocket::send(const Packet& packet) {
// Debug: dump packet bytes for AUTH_SESSION // Debug: dump packet bytes for AUTH_SESSION
if (opcode == 0x1ED) { if (opcode == 0x1ED) {
std::string hexDump = "AUTH_SESSION raw bytes: "; LOG_DEBUG("AUTH_SESSION raw bytes: ",
for (size_t i = 0; i < sendData.size(); ++i) { core::toHexString(sendData.data(), sendData.size(), true));
char buf[4];
snprintf(buf, sizeof(buf), "%02x ", sendData[i]);
hexDump += buf;
if ((i + 1) % 32 == 0) hexDump += "\n";
}
LOG_DEBUG(hexDump);
} }
if (isLoginPipelineCmsg(opcode)) { if (isLoginPipelineCmsg(opcode)) {
LOG_INFO("WS TX LOGIN opcode=0x", std::hex, opcode, std::dec, LOG_INFO("WS TX LOGIN opcode=0x", std::hex, opcode, std::dec,
@ -588,11 +577,9 @@ void WorldSocket::pumpNetworkIO() {
} }
// Hex dump received bytes for auth debugging (debug-only to avoid per-frame string work) // Hex dump received bytes for auth debugging (debug-only to avoid per-frame string work)
if (debugLog && bytesReadThisTick <= 128) { if (debugLog && bytesReadThisTick <= 128) {
std::string hex; LOG_DEBUG("World socket raw bytes: ",
for (size_t i = receiveReadOffset_; i < receiveBuffer.size(); ++i) { core::toHexString(receiveBuffer.data() + receiveReadOffset_,
char buf[4]; snprintf(buf, sizeof(buf), "%02x ", receiveBuffer[i]); hex += buf; receiveBuffer.size() - receiveReadOffset_, true));
}
LOG_DEBUG("World socket raw bytes: ", hex);
} }
tryParsePackets(); tryParsePackets();
if (debugLog && connected && bufferedBytes() > 0) { if (debugLog && connected && bufferedBytes() > 0) {

View file

@ -50,10 +50,12 @@
namespace { namespace {
// Common ImGui colors // Common ImGui colors
constexpr ImVec4 kColorRed = {1.0f, 0.3f, 0.3f, 1.0f}; constexpr ImVec4 kColorRed = {1.0f, 0.3f, 0.3f, 1.0f};
constexpr ImVec4 kColorGreen = {0.4f, 1.0f, 0.4f, 1.0f}; constexpr ImVec4 kColorGreen = {0.4f, 1.0f, 0.4f, 1.0f};
constexpr ImVec4 kColorYellow = {1.0f, 1.0f, 0.3f, 1.0f}; constexpr ImVec4 kColorBrightGreen= {0.3f, 1.0f, 0.3f, 1.0f};
constexpr ImVec4 kColorGray = {0.6f, 0.6f, 0.6f, 1.0f}; constexpr ImVec4 kColorYellow = {1.0f, 1.0f, 0.3f, 1.0f};
constexpr ImVec4 kColorGray = {0.6f, 0.6f, 0.6f, 1.0f};
constexpr ImVec4 kColorDarkGray = {0.5f, 0.5f, 0.5f, 1.0f};
// Common ImGui window flags for popup dialogs // Common ImGui window flags for popup dialogs
const ImGuiWindowFlags kDialogFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize; const ImGuiWindowFlags kDialogFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize;
@ -1146,7 +1148,7 @@ void GameScreen::renderPlayerInfo(game::GameHandler& gameHandler) {
auto state = gameHandler.getState(); auto state = gameHandler.getState();
switch (state) { switch (state) {
case game::WorldState::IN_WORLD: case game::WorldState::IN_WORLD:
ImGui::TextColored(ImVec4(0.3f, 1.0f, 0.3f, 1.0f), "In World"); ImGui::TextColored(kColorBrightGreen, "In World");
break; break;
case game::WorldState::AUTHENTICATED: case game::WorldState::AUTHENTICATED:
ImGui::TextColored(kColorYellow, "Authenticated"); ImGui::TextColored(kColorYellow, "Authenticated");
@ -1205,7 +1207,7 @@ void GameScreen::renderEntityList(game::GameHandler& gameHandler) {
ImGui::TableSetColumnIndex(1); ImGui::TableSetColumnIndex(1);
switch (entity->getType()) { switch (entity->getType()) {
case game::ObjectType::PLAYER: case game::ObjectType::PLAYER:
ImGui::TextColored(ImVec4(0.3f, 1.0f, 0.3f, 1.0f), "Player"); ImGui::TextColored(kColorBrightGreen, "Player");
break; break;
case game::ObjectType::UNIT: case game::ObjectType::UNIT:
ImGui::TextColored(kColorYellow, "Unit"); ImGui::TextColored(kColorYellow, "Unit");
@ -2587,10 +2589,10 @@ void GameScreen::renderChatWindow(game::GameHandler& gameHandler) {
switch (selectedChatType) { switch (selectedChatType) {
case 1: inputColor = kColorRed; break; // YELL - red case 1: inputColor = kColorRed; break; // YELL - red
case 2: inputColor = ImVec4(0.4f, 0.6f, 1.0f, 1.0f); break; // PARTY - blue case 2: inputColor = ImVec4(0.4f, 0.6f, 1.0f, 1.0f); break; // PARTY - blue
case 3: inputColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); break; // GUILD - green case 3: inputColor = kColorBrightGreen; break; // GUILD - green
case 4: inputColor = ImVec4(1.0f, 0.5f, 1.0f, 1.0f); break; // WHISPER - pink case 4: inputColor = ImVec4(1.0f, 0.5f, 1.0f, 1.0f); break; // WHISPER - pink
case 5: inputColor = ImVec4(1.0f, 0.5f, 0.0f, 1.0f); break; // RAID - orange case 5: inputColor = ImVec4(1.0f, 0.5f, 0.0f, 1.0f); break; // RAID - orange
case 6: inputColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); break; // OFFICER - green case 6: inputColor = kColorBrightGreen; break; // OFFICER - green
case 7: inputColor = ImVec4(1.0f, 0.5f, 0.0f, 1.0f); break; // BG - orange case 7: inputColor = ImVec4(1.0f, 0.5f, 0.0f, 1.0f); break; // BG - orange
case 8: inputColor = ImVec4(1.0f, 0.3f, 0.0f, 1.0f); break; // RAID WARNING - red-orange case 8: inputColor = ImVec4(1.0f, 0.3f, 0.0f, 1.0f); break; // RAID WARNING - red-orange
case 9: inputColor = ImVec4(0.4f, 0.6f, 1.0f, 1.0f); break; // INSTANCE - blue case 9: inputColor = ImVec4(0.4f, 0.6f, 1.0f, 1.0f); break; // INSTANCE - blue
@ -3382,7 +3384,7 @@ void GameScreen::renderPlayerFrame(game::GameHandler& gameHandler) {
const bool inCombatConfirmed = gameHandler.isInCombat(); const bool inCombatConfirmed = gameHandler.isInCombat();
const bool attackIntentOnly = gameHandler.hasAutoAttackIntent() && !inCombatConfirmed; const bool attackIntentOnly = gameHandler.hasAutoAttackIntent() && !inCombatConfirmed;
ImVec4 playerBorder = isDead ImVec4 playerBorder = isDead
? ImVec4(0.5f, 0.5f, 0.5f, 1.0f) ? kColorDarkGray
: (inCombatConfirmed : (inCombatConfirmed
? ImVec4(1.0f, 0.2f, 0.2f, 1.0f) ? ImVec4(1.0f, 0.2f, 0.2f, 1.0f)
: (attackIntentOnly : (attackIntentOnly
@ -3417,7 +3419,7 @@ void GameScreen::renderPlayerFrame(game::GameHandler& gameHandler) {
// Derive class color via shared helper // Derive class color via shared helper
ImVec4 classColor = activeChar ImVec4 classColor = activeChar
? classColorVec4(static_cast<uint8_t>(activeChar->characterClass)) ? classColorVec4(static_cast<uint8_t>(activeChar->characterClass))
: ImVec4(0.3f, 1.0f, 0.3f, 1.0f); : kColorBrightGreen;
// Name in class color — clickable for self-target, right-click for menu // Name in class color — clickable for self-target, right-click for menu
ImGui::PushStyleColor(ImGuiCol_Text, classColor); ImGui::PushStyleColor(ImGuiCol_Text, classColor);
@ -3515,7 +3517,7 @@ void GameScreen::renderPlayerFrame(game::GameHandler& gameHandler) {
float pct = static_cast<float>(playerHp) / static_cast<float>(playerMaxHp); float pct = static_cast<float>(playerHp) / static_cast<float>(playerMaxHp);
ImVec4 hpColor; ImVec4 hpColor;
if (isDead) { if (isDead) {
hpColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); hpColor = kColorDarkGray;
} else if (pct > 0.5f) { } else if (pct > 0.5f) {
hpColor = ImVec4(0.2f, 0.8f, 0.2f, 1.0f); // green hpColor = ImVec4(0.2f, 0.8f, 0.2f, 1.0f); // green
} else if (pct > 0.2f) { } else if (pct > 0.2f) {
@ -4240,11 +4242,11 @@ void GameScreen::renderTargetFrame(game::GameHandler& gameHandler) {
// Determine hostility/level color for border and name (WoW-canonical) // Determine hostility/level color for border and name (WoW-canonical)
ImVec4 hostileColor(0.7f, 0.7f, 0.7f, 1.0f); ImVec4 hostileColor(0.7f, 0.7f, 0.7f, 1.0f);
if (target->getType() == game::ObjectType::PLAYER) { if (target->getType() == game::ObjectType::PLAYER) {
hostileColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); hostileColor = kColorBrightGreen;
} else if (target->getType() == game::ObjectType::UNIT) { } else if (target->getType() == game::ObjectType::UNIT) {
auto u = std::static_pointer_cast<game::Unit>(target); auto u = std::static_pointer_cast<game::Unit>(target);
if (u->getHealth() == 0 && u->getMaxHealth() > 0) { if (u->getHealth() == 0 && u->getMaxHealth() > 0) {
hostileColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); hostileColor = kColorDarkGray;
} else if (u->isHostile()) { } else if (u->isHostile()) {
// Check tapped-by-other: grey name for mobs tagged by someone else // Check tapped-by-other: grey name for mobs tagged by someone else
uint32_t tgtDynFlags = u->getDynamicFlags(); uint32_t tgtDynFlags = u->getDynamicFlags();
@ -4269,12 +4271,12 @@ void GameScreen::renderTargetFrame(game::GameHandler& gameHandler) {
} else if (diff >= -2) { } else if (diff >= -2) {
hostileColor = ImVec4(1.0f, 1.0f, 0.1f, 1.0f); // Yellow - even hostileColor = ImVec4(1.0f, 1.0f, 0.1f, 1.0f); // Yellow - even
} else { } else {
hostileColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); // Green - easy hostileColor = kColorBrightGreen; // Green - easy
} }
} }
} // end tapped else } // end tapped else
} else { } else {
hostileColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); // Friendly hostileColor = kColorBrightGreen; // Friendly
} }
} }
@ -4682,7 +4684,7 @@ void GameScreen::renderTargetFrame(game::GameHandler& gameHandler) {
if (totGuid == gameHandler.getPlayerGuid()) { if (totGuid == gameHandler.getPlayerGuid()) {
auto playerEnt = gameHandler.getEntityManager().getEntity(totGuid); auto playerEnt = gameHandler.getEntityManager().getEntity(totGuid);
totName = playerEnt ? getEntityName(playerEnt) : "You"; totName = playerEnt ? getEntityName(playerEnt) : "You";
totColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); totColor = kColorBrightGreen;
} else if (totEnt) { } else if (totEnt) {
totName = getEntityName(totEnt); totName = getEntityName(totEnt);
uint8_t cid = entityClassId(totEnt.get()); uint8_t cid = entityClassId(totEnt.get());
@ -5191,11 +5193,11 @@ void GameScreen::renderFocusFrame(game::GameHandler& gameHandler) {
if (focus->getType() == game::ObjectType::PLAYER) { if (focus->getType() == game::ObjectType::PLAYER) {
// Use class color for player focus targets // Use class color for player focus targets
uint8_t cid = entityClassId(focus.get()); uint8_t cid = entityClassId(focus.get());
focusColor = (cid != 0) ? classColorVec4(cid) : ImVec4(0.3f, 1.0f, 0.3f, 1.0f); focusColor = (cid != 0) ? classColorVec4(cid) : kColorBrightGreen;
} else if (focus->getType() == game::ObjectType::UNIT) { } else if (focus->getType() == game::ObjectType::UNIT) {
auto u = std::static_pointer_cast<game::Unit>(focus); auto u = std::static_pointer_cast<game::Unit>(focus);
if (u->getHealth() == 0 && u->getMaxHealth() > 0) { if (u->getHealth() == 0 && u->getMaxHealth() > 0) {
focusColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); focusColor = kColorDarkGray;
} else if (u->isHostile()) { } else if (u->isHostile()) {
// Tapped-by-other: grey focus frame name // Tapped-by-other: grey focus frame name
uint32_t focDynFlags = u->getDynamicFlags(); uint32_t focDynFlags = u->getDynamicFlags();
@ -5218,11 +5220,11 @@ void GameScreen::renderFocusFrame(game::GameHandler& gameHandler) {
else if (diff >= -2) else if (diff >= -2)
focusColor = ImVec4(1.0f, 1.0f, 0.1f, 1.0f); focusColor = ImVec4(1.0f, 1.0f, 0.1f, 1.0f);
else else
focusColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); focusColor = kColorBrightGreen;
} }
} // end tapped else } // end tapped else
} else { } else {
focusColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); focusColor = kColorBrightGreen;
} }
} }
@ -5647,7 +5649,7 @@ void GameScreen::renderFocusFrame(game::GameHandler& gameHandler) {
ImVec4 fofColor(0.7f, 0.7f, 0.7f, 1.0f); ImVec4 fofColor(0.7f, 0.7f, 0.7f, 1.0f);
if (fofGuid == gameHandler.getPlayerGuid()) { if (fofGuid == gameHandler.getPlayerGuid()) {
fofName = "You"; fofName = "You";
fofColor = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); fofColor = kColorBrightGreen;
} else if (fofEnt) { } else if (fofEnt) {
fofName = getEntityName(fofEnt); fofName = getEntityName(fofEnt);
uint8_t fcid = entityClassId(fofEnt.get()); uint8_t fcid = entityClassId(fofEnt.get());
@ -8340,7 +8342,7 @@ ImVec4 GameScreen::getChatTypeColor(game::ChatType type) const {
case game::ChatType::PARTY: case game::ChatType::PARTY:
return ImVec4(0.5f, 0.5f, 1.0f, 1.0f); // Light blue return ImVec4(0.5f, 0.5f, 1.0f, 1.0f); // Light blue
case game::ChatType::GUILD: case game::ChatType::GUILD:
return ImVec4(0.3f, 1.0f, 0.3f, 1.0f); // Green return kColorBrightGreen; // Green
case game::ChatType::OFFICER: case game::ChatType::OFFICER:
return ImVec4(0.3f, 0.8f, 0.3f, 1.0f); // Dark green return ImVec4(0.3f, 0.8f, 0.3f, 1.0f); // Dark green
case game::ChatType::RAID: case game::ChatType::RAID:
@ -12721,7 +12723,7 @@ void GameScreen::renderPartyFrames(game::GameHandler& gameHandler) {
case 4: powerColor = ImVec4(0.5f, 0.9f, 0.3f, 1.0f); break; // Happiness (green) case 4: powerColor = ImVec4(0.5f, 0.9f, 0.3f, 1.0f); break; // Happiness (green)
case 6: powerColor = ImVec4(0.8f, 0.1f, 0.2f, 1.0f); break; // Runic Power (crimson) case 6: powerColor = ImVec4(0.8f, 0.1f, 0.2f, 1.0f); break; // Runic Power (crimson)
case 7: powerColor = ImVec4(0.4f, 0.1f, 0.6f, 1.0f); break; // Soul Shards (purple) case 7: powerColor = ImVec4(0.4f, 0.1f, 0.6f, 1.0f); break; // Soul Shards (purple)
default: powerColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f); break; default: powerColor = kColorDarkGray; break;
} }
ImGui::PushStyleColor(ImGuiCol_PlotHistogram, powerColor); ImGui::PushStyleColor(ImGuiCol_PlotHistogram, powerColor);
ImGui::ProgressBar(powerPct, ImVec2(-1, 8), ""); ImGui::ProgressBar(powerPct, ImVec2(-1, 8), "");
@ -14108,7 +14110,7 @@ void GameScreen::renderLootRollPopup(game::GameHandler& gameHandler) {
ImVec4(0.2f, 0.9f, 0.2f, 1.0f), // Need — green ImVec4(0.2f, 0.9f, 0.2f, 1.0f), // Need — green
ImVec4(0.3f, 0.6f, 1.0f, 1.0f), // Greed — blue ImVec4(0.3f, 0.6f, 1.0f, 1.0f), // Greed — blue
ImVec4(0.7f, 0.3f, 0.9f, 1.0f), // Disenchant — purple ImVec4(0.7f, 0.3f, 0.9f, 1.0f), // Disenchant — purple
ImVec4(0.5f, 0.5f, 0.5f, 1.0f), // Pass — gray kColorDarkGray, // Pass — gray
}; };
auto rollTypeIndex = [](uint8_t t) -> int { auto rollTypeIndex = [](uint8_t t) -> int {
if (t == 0) return 0; if (t == 0) return 0;
@ -14653,7 +14655,7 @@ void GameScreen::renderGuildRoster(game::GameHandler& gameHandler) {
for (const auto& m : sortedMembers) { for (const auto& m : sortedMembers) {
ImGui::TableNextRow(); ImGui::TableNextRow();
ImVec4 textColor = m.online ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f) ImVec4 textColor = m.online ? ImVec4(1.0f, 1.0f, 1.0f, 1.0f)
: ImVec4(0.5f, 0.5f, 0.5f, 1.0f); : kColorDarkGray;
ImVec4 nameColor = m.online ? classColorVec4(m.classId) : textColor; ImVec4 nameColor = m.online ? classColorVec4(m.classId) : textColor;
ImGui::TableNextColumn(); ImGui::TableNextColumn();
@ -14832,7 +14834,7 @@ void GameScreen::renderGuildRoster(game::GameHandler& gameHandler) {
if (!roster.motd.empty()) { if (!roster.motd.empty()) {
ImGui::TextWrapped("%s", roster.motd.c_str()); ImGui::TextWrapped("%s", roster.motd.c_str());
} else { } else {
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "(not set)"); ImGui::TextColored(kColorDarkGray, "(not set)");
} }
if (ImGui::Button("Set MOTD")) { if (ImGui::Button("Set MOTD")) {
showMotdEdit_ = true; showMotdEdit_ = true;
@ -14885,7 +14887,7 @@ void GameScreen::renderGuildRoster(game::GameHandler& gameHandler) {
ImGui::Text(" %zu. %s", i + 1, rankNames[i].c_str()); ImGui::Text(" %zu. %s", i + 1, rankNames[i].c_str());
if (!perms.empty()) { if (!perms.empty()) {
ImGui::SameLine(); ImGui::SameLine();
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "[%s]", perms.c_str()); ImGui::TextColored(kColorDarkGray, "[%s]", perms.c_str());
} }
} else { } else {
ImGui::Text(" %zu. %s", i + 1, rankNames[i].c_str()); ImGui::Text(" %zu. %s", i + 1, rankNames[i].c_str());
@ -15201,7 +15203,7 @@ void GameScreen::renderSocialFrame(game::GameHandler& gameHandler) {
const char* displayName = c.name.empty() ? "(unknown)" : c.name.c_str(); const char* displayName = c.name.empty() ? "(unknown)" : c.name.c_str();
ImVec4 nameCol = c.isOnline() ImVec4 nameCol = c.isOnline()
? classColorVec4(static_cast<uint8_t>(c.classId)) ? classColorVec4(static_cast<uint8_t>(c.classId))
: ImVec4(0.5f, 0.5f, 0.5f, 1.0f); : kColorDarkGray;
ImGui::TextColored(nameCol, "%s", displayName); ImGui::TextColored(nameCol, "%s", displayName);
if (c.isOnline() && c.level > 0) { if (c.isOnline() && c.level > 0) {
@ -24072,7 +24074,7 @@ void GameScreen::renderInstanceLockouts(game::GameHandler& gameHandler) {
static_cast<unsigned long long>(mins)); static_cast<unsigned long long>(mins));
} }
} else { } else {
ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "Expired"); ImGui::TextColored(kColorDarkGray, "Expired");
} }
// Locked / Extended status // Locked / Extended status
@ -24446,7 +24448,7 @@ void GameScreen::renderCombatLog(game::GameHandler& gameHandler) {
snprintf(desc, sizeof(desc), "%s critically heals %s for %d! (%s)", src, tgt, e.amount, spell); snprintf(desc, sizeof(desc), "%s critically heals %s for %d! (%s)", src, tgt, e.amount, spell);
else else
snprintf(desc, sizeof(desc), "%s critically heals %s for %d!", src, tgt, e.amount); snprintf(desc, sizeof(desc), "%s critically heals %s for %d!", src, tgt, e.amount);
color = ImVec4(0.3f, 1.0f, 0.3f, 1.0f); color = kColorBrightGreen;
break; break;
case T::PERIODIC_HEAL: case T::PERIODIC_HEAL:
if (spell) if (spell)