From fe1c4c622b28e41c59d480aa748542e6bd091dc3 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Thu, 2 Apr 2026 14:47:04 -0700 Subject: [PATCH] chore: remove dead functions left behind by handler extractions 685 lines of unused code duplicated into extracted handler files (entity_controller, spell_handler, quest_handler, warden_handler, social_handler, action_bar_panel, chat_panel, window_manager) during PRs #33-#38. Build is now warning-free. --- src/game/game_handler.cpp | 490 -------------------------------------- src/ui/chat_panel.cpp | 65 ----- src/ui/combat_ui.cpp | 8 - src/ui/game_screen.cpp | 103 -------- src/ui/window_manager.cpp | 19 -- 5 files changed, 685 deletions(-) diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index ed8087b0..c4bd725a 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -94,13 +94,6 @@ bool isAuthCharPipelineOpcode(LogicalOpcode op) { namespace { -bool envFlagEnabled(const char* key, bool defaultValue = false) { - const char* raw = std::getenv(key); - if (!raw || !*raw) return defaultValue; - return !(raw[0] == '0' || raw[0] == 'f' || raw[0] == 'F' || - raw[0] == 'n' || raw[0] == 'N'); -} - int parseEnvIntClamped(const char* key, int defaultValue, int minValue, int maxValue) { const char* raw = std::getenv(key); if (!raw || !*raw) return defaultValue; @@ -126,47 +119,14 @@ float incomingPacketBudgetMs(WorldState state) { return static_cast(state == WorldState::IN_WORLD ? inWorldBudgetMs : loginBudgetMs); } -int updateObjectBlocksBudgetPerUpdate(WorldState state) { - static const int inWorldBudget = - parseEnvIntClamped("WOWEE_NET_MAX_UPDATE_OBJECT_BLOCKS", 24, 1, 2048); - static const int loginBudget = - parseEnvIntClamped("WOWEE_NET_MAX_UPDATE_OBJECT_BLOCKS_LOGIN", 128, 1, 4096); - return state == WorldState::IN_WORLD ? inWorldBudget : loginBudget; -} - float slowPacketLogThresholdMs() { static const int thresholdMs = parseEnvIntClamped("WOWEE_NET_SLOW_PACKET_LOG_MS", 10, 1, 60000); return static_cast(thresholdMs); } -float slowUpdateObjectBlockLogThresholdMs() { - static const int thresholdMs = - parseEnvIntClamped("WOWEE_NET_SLOW_UPDATE_BLOCK_LOG_MS", 10, 1, 60000); - return static_cast(thresholdMs); -} - constexpr size_t kMaxQueuedInboundPackets = 4096; -CombatTextEntry::Type combatTextTypeFromSpellMissInfo(uint8_t missInfo) { - switch (missInfo) { - case 0: return CombatTextEntry::MISS; - case 1: return CombatTextEntry::DODGE; - case 2: return CombatTextEntry::PARRY; - case 3: return CombatTextEntry::BLOCK; - case 4: return CombatTextEntry::EVADE; - case 5: return CombatTextEntry::IMMUNE; - case 6: return CombatTextEntry::DEFLECT; - case 7: return CombatTextEntry::ABSORB; - case 8: return CombatTextEntry::RESIST; - case 9: // Some cores encode SPELL_MISS_IMMUNE2 as 9. - case 10: // Others encode SPELL_MISS_IMMUNE2 as 10. - return CombatTextEntry::IMMUNE; - case 11: return CombatTextEntry::REFLECT; - default: return CombatTextEntry::MISS; - } -} - } // end anonymous namespace std::string formatCopperAmount(uint32_t amount) { @@ -192,412 +152,6 @@ std::string formatCopperAmount(uint32_t amount) { return oss.str(); } -namespace { - -std::string displaySpellName(GameHandler& handler, uint32_t spellId) { - if (spellId == 0) return {}; - const std::string& name = handler.getSpellName(spellId); - if (!name.empty()) return name; - return "spell " + std::to_string(spellId); -} - -std::string formatSpellNameList(GameHandler& handler, - const std::vector& spellIds, - size_t maxShown = 3) { - if (spellIds.empty()) return {}; - - const size_t shownCount = std::min(spellIds.size(), maxShown); - std::ostringstream oss; - for (size_t i = 0; i < shownCount; ++i) { - if (i > 0) { - if (shownCount == 2) { - oss << " and "; - } else if (i == shownCount - 1) { - oss << ", and "; - } else { - oss << ", "; - } - } - oss << displaySpellName(handler, spellIds[i]); - } - - if (spellIds.size() > shownCount) { - oss << ", and " << (spellIds.size() - shownCount) << " more"; - } - - return oss.str(); -} - -bool readCStringAt(const std::vector& data, size_t start, std::string& out, size_t& nextPos) { - out.clear(); - if (start >= data.size()) return false; - size_t i = start; - while (i < data.size()) { - uint8_t b = data[i++]; - if (b == 0) { - nextPos = i; - return true; - } - out.push_back(static_cast(b)); - } - return false; -} - -std::string asciiLower(std::string s) { - std::transform(s.begin(), s.end(), s.begin(), - [](unsigned char c) { return static_cast(std::tolower(c)); }); - return s; -} - -std::vector splitWowPath(const std::string& wowPath) { - std::vector out; - std::string cur; - for (char c : wowPath) { - if (c == '\\' || c == '/') { - if (!cur.empty()) { - out.push_back(cur); - cur.clear(); - } - continue; - } - cur.push_back(c); - } - if (!cur.empty()) out.push_back(cur); - return out; -} - -int pathCaseScore(const std::string& name) { - int score = 0; - for (unsigned char c : name) { - if (std::islower(c)) score += 2; - else if (std::isupper(c)) score -= 1; - } - return score; -} - -std::string resolveCaseInsensitiveDataPath(const std::string& dataRoot, const std::string& wowPath) { - if (dataRoot.empty() || wowPath.empty()) return std::string(); - std::filesystem::path cur(dataRoot); - std::error_code ec; - if (!std::filesystem::exists(cur, ec) || !std::filesystem::is_directory(cur, ec)) { - return std::string(); - } - - for (const std::string& segment : splitWowPath(wowPath)) { - std::string wanted = asciiLower(segment); - std::filesystem::path bestPath; - int bestScore = std::numeric_limits::min(); - bool found = false; - - for (const auto& entry : std::filesystem::directory_iterator(cur, ec)) { - if (ec) break; - std::string name = entry.path().filename().string(); - if (asciiLower(name) != wanted) continue; - int score = pathCaseScore(name); - if (!found || score > bestScore) { - found = true; - bestScore = score; - bestPath = entry.path(); - } - } - if (!found) return std::string(); - cur = bestPath; - } - - if (!std::filesystem::exists(cur, ec) || std::filesystem::is_directory(cur, ec)) { - return std::string(); - } - return cur.string(); -} - -std::vector readFileBinary(const std::string& fsPath) { - std::ifstream in(fsPath, std::ios::binary); - if (!in) return {}; - in.seekg(0, std::ios::end); - std::streamoff size = in.tellg(); - if (size <= 0) return {}; - in.seekg(0, std::ios::beg); - std::vector data(static_cast(size)); - in.read(reinterpret_cast(data.data()), size); - if (!in) return {}; - return data; -} - -bool hmacSha1Matches(const uint8_t seedBytes[4], const std::string& text, const uint8_t expected[20]) { - uint8_t out[SHA_DIGEST_LENGTH]; - unsigned int outLen = 0; - HMAC(EVP_sha1(), - seedBytes, 4, - reinterpret_cast(text.data()), - static_cast(text.size()), - out, &outLen); - return outLen == SHA_DIGEST_LENGTH && std::memcmp(out, expected, SHA_DIGEST_LENGTH) == 0; -} - -const std::unordered_map>& knownDoorHashes() { - static const std::unordered_map> k = { - {"world\\lordaeron\\stratholme\\activedoodads\\doors\\nox_door_plague.m2", - {0xB4,0x45,0x2B,0x6D,0x95,0xC9,0x8B,0x18,0x6A,0x70,0xB0,0x08,0xFA,0x07,0xBB,0xAE,0xF3,0x0D,0xF7,0xA2}}, - {"world\\kalimdor\\onyxiaslair\\doors\\onyxiasgate01.m2", - {0x75,0x19,0x5E,0x4A,0xED,0xA0,0xBC,0xAF,0x04,0x8C,0xA0,0xE3,0x4D,0x95,0xA7,0x0D,0x4F,0x53,0xC7,0x46}}, - {"world\\generic\\human\\activedoodads\\doors\\deadminedoor02.m2", - {0x3D,0xFF,0x01,0x1B,0x9A,0xB1,0x34,0xF3,0x7F,0x88,0x50,0x97,0xE6,0x95,0x35,0x1B,0x91,0x95,0x35,0x64}}, - {"world\\kalimdor\\silithus\\activedoodads\\ahnqirajdoor\\ahnqirajdoor02.m2", - {0xDB,0xD4,0xF4,0x07,0xC4,0x68,0xCC,0x36,0x13,0x4E,0x62,0x1D,0x16,0x01,0x78,0xFD,0xA4,0xD0,0xD2,0x49}}, - {"world\\kalimdor\\diremaul\\activedoodads\\doors\\diremaulsmallinstancedoor.m2", - {0x0D,0xC8,0xDB,0x46,0xC8,0x55,0x49,0xC0,0xFF,0x1A,0x60,0x0F,0x6C,0x23,0x63,0x57,0xC3,0x05,0x78,0x1A}}, - }; - return k; -} - -bool isReadableQuestText(const std::string& s, size_t minLen, size_t maxLen) { - if (s.size() < minLen || s.size() > maxLen) return false; - bool hasAlpha = false; - for (unsigned char c : s) { - if (c < 0x20 || c > 0x7E) return false; - if (std::isalpha(c)) hasAlpha = true; - } - return hasAlpha; -} - -bool isPlaceholderQuestTitle(const std::string& s) { - return s.rfind("Quest #", 0) == 0; -} - -float mergeCooldownSeconds(float current, float incoming) { - constexpr float kEpsilon = 0.05f; - if (incoming <= 0.0f) return 0.0f; - if (current <= 0.0f) return incoming; - // Cooldowns should normally tick down. If a duplicate/late packet reports a - // larger value, keep the local remaining time to avoid visible timer resets. - if (incoming > current + kEpsilon) return current; - return incoming; -} - -bool looksLikeQuestDescriptionText(const std::string& s) { - int spaces = 0; - int commas = 0; - for (unsigned char c : s) { - if (c == ' ') spaces++; - if (c == ',') commas++; - } - const int words = spaces + 1; - if (words > 8) return true; - if (commas > 0 && words > 5) return true; - if (s.find(". ") != std::string::npos) return true; - if (s.find(':') != std::string::npos && words > 5) return true; - return false; -} - -bool isStrongQuestTitle(const std::string& s) { - if (!isReadableQuestText(s, 6, 72)) return false; - if (looksLikeQuestDescriptionText(s)) return false; - unsigned char first = static_cast(s.front()); - return std::isupper(first) != 0; -} - -int scoreQuestTitle(const std::string& s) { - if (!isReadableQuestText(s, 4, 72)) return -1000; - if (looksLikeQuestDescriptionText(s)) return -1000; - int score = 0; - score += static_cast(std::min(s.size(), 32)); - unsigned char first = static_cast(s.front()); - if (std::isupper(first)) score += 20; - if (std::islower(first)) score -= 20; - if (s.find(' ') != std::string::npos) score += 8; - if (s.find('.') != std::string::npos) score -= 18; - if (s.find('!') != std::string::npos || s.find('?') != std::string::npos) score -= 6; - return score; -} - -struct QuestQueryTextCandidate { - std::string title; - std::string objectives; - int score = -1000; -}; - -QuestQueryTextCandidate pickBestQuestQueryTexts(const std::vector& data, bool classicHint) { - QuestQueryTextCandidate best; - if (data.size() <= 9) return best; - - std::vector seedOffsets; - const size_t base = 8; - const size_t classicOffset = base + 40u * 4u; - const size_t wotlkOffset = base + 55u * 4u; - if (classicHint) { - seedOffsets.push_back(classicOffset); - seedOffsets.push_back(wotlkOffset); - } else { - seedOffsets.push_back(wotlkOffset); - seedOffsets.push_back(classicOffset); - } - for (size_t off : seedOffsets) { - if (off < data.size()) { - std::string title; - size_t next = off; - if (readCStringAt(data, off, title, next)) { - QuestQueryTextCandidate c; - c.title = title; - c.score = scoreQuestTitle(title) + 20; // Prefer expected struct offsets - - std::string s2; - size_t n2 = next; - if (readCStringAt(data, next, s2, n2) && isReadableQuestText(s2, 8, 600)) { - c.objectives = s2; - } - if (c.score > best.score) best = c; - } - } - } - - // Fallback: scan packet for best printable C-string title candidate. - for (size_t start = 8; start < data.size(); ++start) { - std::string title; - size_t next = start; - if (!readCStringAt(data, start, title, next)) continue; - - QuestQueryTextCandidate c; - c.title = title; - c.score = scoreQuestTitle(title); - if (c.score < 0) continue; - - std::string s2, s3; - size_t n2 = next, n3 = next; - if (readCStringAt(data, next, s2, n2)) { - if (isReadableQuestText(s2, 8, 600)) c.objectives = s2; - else if (readCStringAt(data, n2, s3, n3) && isReadableQuestText(s3, 8, 600)) c.objectives = s3; - } - if (c.score > best.score) best = c; - } - - return best; -} - -// Parse kill/item objectives from SMSG_QUEST_QUERY_RESPONSE raw data. -// Returns true if the objective block was found and at least one entry read. -// -// Format after the fixed integer header (40*4 Classic or 55*4 WotLK bytes post questId+questMethod): -// N strings (title, objectives, details, endText; + completedText for WotLK) -// 4x { int32 npcOrGoId, uint32 count } -- entity (kill/interact) objectives -// 6x { uint32 itemId, uint32 count } -- item collect objectives -// 4x cstring -- per-objective display text -// -// We use the same fixed-offset heuristic as pickBestQuestQueryTexts and then scan past -// the string section to reach the objective data. -struct QuestQueryObjectives { - struct Kill { int32_t npcOrGoId; uint32_t required; }; - struct Item { uint32_t itemId; uint32_t required; }; - std::array kills{}; - std::array items{}; - bool valid = false; -}; - -static uint32_t readU32At(const std::vector& d, size_t pos) { - return static_cast(d[pos]) - | (static_cast(d[pos + 1]) << 8) - | (static_cast(d[pos + 2]) << 16) - | (static_cast(d[pos + 3]) << 24); -} - -// Try to parse objective block starting at `startPos` with `nStrings` strings before it. -// Returns a valid QuestQueryObjectives if the data looks plausible, otherwise invalid. -static QuestQueryObjectives tryParseQuestObjectivesAt(const std::vector& data, - size_t startPos, int nStrings) { - QuestQueryObjectives out; - size_t pos = startPos; - - // Scan past each string (null-terminated). - for (int si = 0; si < nStrings; ++si) { - while (pos < data.size() && data[pos] != 0) ++pos; - if (pos >= data.size()) return out; // truncated - ++pos; // consume null terminator - } - - // Read 4 entity objectives: int32 npcOrGoId + uint32 count each. - for (int i = 0; i < 4; ++i) { - if (pos + 8 > data.size()) return out; - out.kills[i].npcOrGoId = static_cast(readU32At(data, pos)); pos += 4; - out.kills[i].required = readU32At(data, pos); pos += 4; - } - - // Read 6 item objectives: uint32 itemId + uint32 count each. - for (int i = 0; i < 6; ++i) { - if (pos + 8 > data.size()) break; - out.items[i].itemId = readU32At(data, pos); pos += 4; - out.items[i].required = readU32At(data, pos); pos += 4; - } - - out.valid = true; - return out; -} - -QuestQueryObjectives extractQuestQueryObjectives(const std::vector& data, bool classicHint) { - if (data.size() < 16) return {}; - - // questId(4) + questMethod(4) prefix before the fixed integer header. - const size_t base = 8; - // Classic/TBC: 40 fixed uint32 fields + 4 strings before objectives. - // WotLK: 55 fixed uint32 fields + 5 strings before objectives. - const size_t classicStart = base + 40u * 4u; - const size_t wotlkStart = base + 55u * 4u; - - // Try the expected layout first, then fall back to the other. - if (classicHint) { - auto r = tryParseQuestObjectivesAt(data, classicStart, 4); - if (r.valid) return r; - return tryParseQuestObjectivesAt(data, wotlkStart, 5); - } else { - auto r = tryParseQuestObjectivesAt(data, wotlkStart, 5); - if (r.valid) return r; - return tryParseQuestObjectivesAt(data, classicStart, 4); - } -} - -// Parse quest reward fields from SMSG_QUEST_QUERY_RESPONSE fixed header. -// Classic/TBC: 40 fixed fields; WotLK: 55 fixed fields. -struct QuestQueryRewards { - int32_t rewardMoney = 0; - std::array itemId{}; - std::array itemCount{}; - std::array choiceItemId{}; - std::array choiceItemCount{}; - bool valid = false; -}; - -static QuestQueryRewards tryParseQuestRewards(const std::vector& data, - bool classicLayout) { - const size_t base = 8; // after questId(4) + questMethod(4) - const size_t fieldCount = classicLayout ? 40u : 55u; - const size_t headerEnd = base + fieldCount * 4u; - if (data.size() < headerEnd) return {}; - - // Field indices (0-based) for each expansion: - // Classic/TBC: rewardMoney=[14], rewardItemId[4]=[20..23], rewardItemCount[4]=[24..27], - // rewardChoiceItemId[6]=[28..33], rewardChoiceItemCount[6]=[34..39] - // WotLK: rewardMoney=[17], rewardItemId[4]=[30..33], rewardItemCount[4]=[34..37], - // rewardChoiceItemId[6]=[38..43], rewardChoiceItemCount[6]=[44..49] - const size_t moneyField = classicLayout ? 14u : 17u; - const size_t itemIdField = classicLayout ? 20u : 30u; - const size_t itemCountField = classicLayout ? 24u : 34u; - const size_t choiceIdField = classicLayout ? 28u : 38u; - const size_t choiceCntField = classicLayout ? 34u : 44u; - - QuestQueryRewards out; - out.rewardMoney = static_cast(readU32At(data, base + moneyField * 4u)); - for (size_t i = 0; i < 4; ++i) { - out.itemId[i] = readU32At(data, base + (itemIdField + i) * 4u); - out.itemCount[i] = readU32At(data, base + (itemCountField + i) * 4u); - } - for (size_t i = 0; i < 6; ++i) { - out.choiceItemId[i] = readU32At(data, base + (choiceIdField + i) * 4u); - out.choiceItemCount[i] = readU32At(data, base + (choiceCntField + i) * 4u); - } - out.valid = true; - return out; -} - -} // namespace - template void GameHandler::withSoundManager(ManagerGetter getter, Callback cb) { if (auto* ac = services_.audioCoordinator) { @@ -5751,40 +5305,6 @@ void GameHandler::acceptBattlefield(uint32_t queueSlot) { // LFG / Dungeon Finder handlers (WotLK 3.3.5a) // --------------------------------------------------------------------------- -static const char* lfgJoinResultString(uint8_t result) { - switch (result) { - case 0: return nullptr; // success - case 1: return "Role check failed."; - case 2: return "No LFG slots available for your group."; - case 3: return "No LFG object found."; - case 4: return "No slots available (player)."; - case 5: return "No slots available (party)."; - case 6: return "Dungeon requirements not met by all members."; - case 7: return "Party members are from different realms."; - case 8: return "Not all members are present."; - case 9: return "Get info timeout."; - case 10: return "Invalid dungeon slot."; - case 11: return "You are marked as a deserter."; - case 12: return "A party member is marked as a deserter."; - case 13: return "You are on a random dungeon cooldown."; - case 14: return "A party member is on a random dungeon cooldown."; - case 16: return "No spec/role available."; - default: return "Cannot join dungeon finder."; - } -} - -static const char* lfgTeleportDeniedString(uint8_t reason) { - switch (reason) { - case 0: return "You are not in a LFG group."; - case 1: return "You are not in the dungeon."; - case 2: return "You have a summon pending."; - case 3: return "You are dead."; - case 4: return "You have Deserter."; - case 5: return "You do not meet the requirements."; - default: return "Teleport to dungeon denied."; - } -} - // --------------------------------------------------------------------------- // LFG outgoing packets // --------------------------------------------------------------------------- @@ -5922,16 +5442,6 @@ float GameHandler::getSpellCooldown(uint32_t spellId) const { return 0; } -static audio::SpellSoundManager::MagicSchool schoolMaskToMagicSchool(uint32_t mask) { - if (mask & 0x04) return audio::SpellSoundManager::MagicSchool::FIRE; - if (mask & 0x10) return audio::SpellSoundManager::MagicSchool::FROST; - if (mask & 0x02) return audio::SpellSoundManager::MagicSchool::HOLY; - if (mask & 0x08) return audio::SpellSoundManager::MagicSchool::NATURE; - if (mask & 0x20) return audio::SpellSoundManager::MagicSchool::SHADOW; - if (mask & 0x40) return audio::SpellSoundManager::MagicSchool::ARCANE; - return audio::SpellSoundManager::MagicSchool::ARCANE; -} - // ============================================================ // Talents // ============================================================ diff --git a/src/ui/chat_panel.cpp b/src/ui/chat_panel.cpp index 67fd4fc4..49d37249 100644 --- a/src/ui/chat_panel.cpp +++ b/src/ui/chat_panel.cpp @@ -53,23 +53,6 @@ namespace { return s.substr(first, last - first + 1); } - // Format a duration in seconds as compact text: "2h", "3:05", "42" - void fmtDurationCompact(char* buf, size_t sz, int secs) { - if (secs >= 3600) snprintf(buf, sz, "%dh", secs / 3600); - else if (secs >= 60) snprintf(buf, sz, "%d:%02d", secs / 60, secs % 60); - else snprintf(buf, sz, "%d", secs); - } - - // Render "Remaining: Xs" or "Remaining: Xm Ys" in a tooltip (light gray) - void renderAuraRemaining(int remainMs) { - if (remainMs <= 0) return; - int s = remainMs / 1000; - char buf[32]; - if (s < 60) snprintf(buf, sizeof(buf), "Remaining: %ds", s); - else snprintf(buf, sizeof(buf), "Remaining: %dm %ds", s / 60, s % 60); - ImGui::TextColored(kLightGray, "%s", buf); - } - std::string toLower(std::string s) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); @@ -187,12 +170,10 @@ bool ChatPanel::shouldShowMessage(const game::MessageChatData& msg, int tabIndex // Forward declaration — defined below -static std::string firstMacroCommand(const std::string& macroText); static std::vector allMacroCommands(const std::string& macroText); static std::string evaluateMacroConditionals(const std::string& rawArg, game::GameHandler& gameHandler, uint64_t& targetOverride); -static std::string getMacroShowtooltipArg(const std::string& macroText); void ChatPanel::render(game::GameHandler& gameHandler, InventoryScreen& inventoryScreen, @@ -1708,22 +1689,6 @@ void ChatPanel::render(game::GameHandler& gameHandler, } -static std::string firstMacroCommand(const std::string& macroText) { - size_t pos = 0; - while (pos <= macroText.size()) { - size_t nl = macroText.find('\n', pos); - std::string line = (nl != std::string::npos) ? macroText.substr(pos, nl - pos) : macroText.substr(pos); - if (!line.empty() && line.back() == '\r') line.pop_back(); - size_t start = line.find_first_not_of(" \t"); - if (start != std::string::npos) line = line.substr(start); - if (!line.empty() && line.front() != '#') - return line; - if (nl == std::string::npos) break; - pos = nl + 1; - } - return {}; -} - // Collect all non-comment, non-empty lines from a macro body. static std::vector allMacroCommands(const std::string& macroText) { std::vector cmds; @@ -1742,36 +1707,6 @@ static std::vector allMacroCommands(const std::string& macroText) { return cmds; } -// Returns the #showtooltip argument from a macro body: -// "#showtooltip Spell" → "Spell" -// "#showtooltip" → "__auto__" (derive from first /cast) -// (none) → "" -static std::string getMacroShowtooltipArg(const std::string& macroText) { - size_t pos = 0; - while (pos <= macroText.size()) { - size_t nl = macroText.find('\n', pos); - std::string line = (nl != std::string::npos) ? macroText.substr(pos, nl - pos) : macroText.substr(pos); - if (!line.empty() && line.back() == '\r') line.pop_back(); - size_t fs = line.find_first_not_of(" \t"); - if (fs != std::string::npos) line = line.substr(fs); - if (line.rfind("#showtooltip", 0) == 0 || line.rfind("#show", 0) == 0) { - size_t sp = line.find(' '); - if (sp != std::string::npos) { - std::string arg = line.substr(sp + 1); - size_t as = arg.find_first_not_of(" \t"); - if (as != std::string::npos) arg = arg.substr(as); - size_t ae = arg.find_last_not_of(" \t"); - if (ae != std::string::npos) arg.resize(ae + 1); - if (!arg.empty()) return arg; - } - return "__auto__"; - } - if (nl == std::string::npos) break; - pos = nl + 1; - } - return {}; -} - // --------------------------------------------------------------------------- // WoW macro conditional evaluator // Parses: [cond1,cond2] Spell1; [cond3] Spell2; DefaultSpell diff --git a/src/ui/combat_ui.cpp b/src/ui/combat_ui.cpp index ecaa88a5..0427f337 100644 --- a/src/ui/combat_ui.cpp +++ b/src/ui/combat_ui.cpp @@ -32,13 +32,6 @@ namespace { constexpr auto& kColorBrightGreen = kBrightGreen; constexpr auto& kColorYellow = kYellow; - // Format a duration in seconds as compact text: "2h", "3:05", "42" - void fmtDurationCompact(char* buf, size_t sz, int secs) { - if (secs >= 3600) snprintf(buf, sz, "%dh", secs / 3600); - else if (secs >= 60) snprintf(buf, sz, "%d:%02d", secs / 60, secs % 60); - else snprintf(buf, sz, "%d", secs); - } - // Render "Remaining: Xs" or "Remaining: Xm Ys" in a tooltip (light gray) void renderAuraRemaining(int remainMs) { if (remainMs <= 0) return; @@ -269,7 +262,6 @@ void CombatUI::renderRaidWarningOverlay(game::GameHandler& gameHandler) { // Walk only the new messages (deque — iterate from back by skipping old ones) size_t toScan = newCount - raidWarnChatSeenCount_; size_t startIdx = newCount > toScan ? newCount - toScan : 0; - auto* renderer = services_.renderer; for (size_t i = startIdx; i < newCount; ++i) { const auto& msg = chatHistory[i]; if (msg.type == game::ChatType::RAID_WARNING || diff --git a/src/ui/game_screen.cpp b/src/ui/game_screen.cpp index 99247350..23461ce3 100644 --- a/src/ui/game_screen.cpp +++ b/src/ui/game_screen.cpp @@ -76,24 +76,6 @@ namespace { // Common ImGui window flags for popup dialogs const ImGuiWindowFlags kDialogFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize; - // Build a WoW-format item link string for chat insertion. - // Format: |cff|Hitem::0:0:0:0:0:0:0:0|h[]|h|r - std::string buildItemChatLink(uint32_t itemId, uint8_t quality, const std::string& name) { - static constexpr const char* kQualHex[] = {"9d9d9d","ffffff","1eff00","0070dd","a335ee","ff8000","e6cc80","e6cc80"}; - uint8_t qi = quality < 8 ? quality : 1; - char buf[512]; - snprintf(buf, sizeof(buf), "|cff%s|Hitem:%u:0:0:0:0:0:0:0:0|h[%s]|h|r", - kQualHex[qi], itemId, name.c_str()); - return buf; - } - - std::string trim(const std::string& s) { - size_t first = s.find_first_not_of(" \t\r\n"); - if (first == std::string::npos) return ""; - size_t last = s.find_last_not_of(" \t\r\n"); - return s.substr(first, last - first + 1); - } - // Format a duration in seconds as compact text: "2h", "3:05", "42" void fmtDurationCompact(char* buf, size_t sz, int secs) { if (secs >= 3600) snprintf(buf, sz, "%dh", secs / 3600); @@ -111,13 +93,6 @@ namespace { ImGui::TextColored(kLightGray, "%s", buf); } - std::string toLower(std::string s) { - std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { - return static_cast(std::tolower(c)); - }); - return s; - } - // Render gold/silver/copper amounts in WoW-canonical colors on the current ImGui line. // Skips zero-value denominations (except copper, which is always shown when gold=silver=0). // Aliases for shared class color helpers (wowee::ui namespace) @@ -138,40 +113,6 @@ namespace { return wowee::game::getClassName(static_cast(classId)); } - bool isPortBotTarget(const std::string& target) { - std::string t = toLower(trim(target)); - return t == "portbot" || t == "gmbot" || t == "telebot"; - } - - std::string buildPortBotCommand(const std::string& rawInput) { - std::string input = trim(rawInput); - if (input.empty()) return ""; - - std::string lower = toLower(input); - if (lower == "help" || lower == "?") { - return "__help__"; - } - - if (lower.rfind(".tele ", 0) == 0 || lower.rfind(".go ", 0) == 0) { - return input; - } - - if (lower.rfind("xyz ", 0) == 0) { - return ".go " + input; - } - - if (lower == "sw" || lower == "stormwind") return ".tele stormwind"; - if (lower == "if" || lower == "ironforge") return ".tele ironforge"; - if (lower == "darn" || lower == "darnassus") return ".tele darnassus"; - if (lower == "org" || lower == "orgrimmar") return ".tele orgrimmar"; - if (lower == "tb" || lower == "thunderbluff") return ".tele thunderbluff"; - if (lower == "uc" || lower == "undercity") return ".tele undercity"; - if (lower == "shatt" || lower == "shattrath") return ".tele shattrath"; - if (lower == "dal" || lower == "dalaran") return ".tele dalaran"; - - return ".tele " + input; - } - bool raySphereIntersect(const wowee::rendering::Ray& ray, const glm::vec3& center, float radius, float& tOut) { glm::vec3 oc = ray.origin - center; float b = glm::dot(oc, ray.direction); @@ -199,50 +140,6 @@ namespace { return "Unknown"; } - // Collect all non-comment, non-empty lines from a macro body. - std::vector allMacroCommands(const std::string& macroText) { - std::vector cmds; - size_t pos = 0; - while (pos <= macroText.size()) { - size_t nl = macroText.find('\n', pos); - std::string line = (nl != std::string::npos) ? macroText.substr(pos, nl - pos) : macroText.substr(pos); - if (!line.empty() && line.back() == '\r') line.pop_back(); - size_t start = line.find_first_not_of(" \t"); - if (start != std::string::npos) line = line.substr(start); - if (!line.empty() && line.front() != '#') - cmds.push_back(std::move(line)); - if (nl == std::string::npos) break; - pos = nl + 1; - } - return cmds; - } - - // Returns the #showtooltip argument from a macro body. - std::string getMacroShowtooltipArg(const std::string& macroText) { - size_t pos = 0; - while (pos <= macroText.size()) { - size_t nl = macroText.find('\n', pos); - std::string line = (nl != std::string::npos) ? macroText.substr(pos, nl - pos) : macroText.substr(pos); - if (!line.empty() && line.back() == '\r') line.pop_back(); - size_t fs = line.find_first_not_of(" \t"); - if (fs != std::string::npos) line = line.substr(fs); - if (line.rfind("#showtooltip", 0) == 0 || line.rfind("#show", 0) == 0) { - size_t sp = line.find(' '); - if (sp != std::string::npos) { - std::string arg = line.substr(sp + 1); - size_t as = arg.find_first_not_of(" \t"); - if (as != std::string::npos) arg = arg.substr(as); - size_t ae = arg.find_last_not_of(" \t"); - if (ae != std::string::npos) arg.resize(ae + 1); - if (!arg.empty()) return arg; - } - return "__auto__"; - } - if (nl == std::string::npos) break; - pos = nl + 1; - } - return {}; - } } namespace wowee { namespace ui { diff --git a/src/ui/window_manager.cpp b/src/ui/window_manager.cpp index f25db424..b7a516dc 100644 --- a/src/ui/window_manager.cpp +++ b/src/ui/window_manager.cpp @@ -43,25 +43,6 @@ namespace { constexpr auto& kColorGray = kGray; constexpr auto& kColorDarkGray = kDarkGray; - // Render gold/silver/copper amounts in WoW-canonical colors - void renderGoldText(uint32_t totalCopper) { - uint32_t gold = totalCopper / 10000; - uint32_t silver = (totalCopper / 100) % 100; - uint32_t copper = totalCopper % 100; - bool shown = false; - if (gold > 0) { - ImGui::TextColored(ImVec4(1.0f, 0.84f, 0.0f, 1.0f), "%ug", gold); - shown = true; - } - if (silver > 0 || shown) { - if (shown) { ImGui::SameLine(0, 2); } - ImGui::TextColored(ImVec4(0.75f, 0.75f, 0.75f, 1.0f), "%us", silver); - shown = true; - } - if (shown) { ImGui::SameLine(0, 2); } - ImGui::TextColored(ImVec4(0.72f, 0.45f, 0.2f, 1.0f), "%uc", copper); - } - // Common ImGui window flags for popup dialogs const ImGuiWindowFlags kDialogFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize;