feat: parse SMSG_SET_FACTION_ATWAR/VISIBLE and show at-war status in reputation panel

- Parse SMSG_SET_FACTION_ATWAR (uint32 repListId + uint8 set) to track
  per-faction at-war flags in initialFactions_ flags byte
- Parse SMSG_SET_FACTION_VISIBLE (uint32 repListId + uint8 visible) to
  track faction visibility changes from the server
- Add FACTION_FLAG_* constants (VISIBLE, AT_WAR, HIDDEN, etc.) to GameHandler
- Build repListId <-> factionId bidirectional maps when loading Faction.dbc
  (ReputationListID field 1); used to correlate flag packets with standings
- Fix Faction.dbc field layout comment: field 1=ReputationListID, field 23=Name
  (was incorrectly documented as field 22 with no ReputationListID field)
- Add isFactionAtWar(), isFactionVisible(), getFactionIdByRepListId(),
  getRepListIdByFactionId() accessors on GameHandler
- Reputation panel now shows watched faction at top, highlights at-war
  factions in red with "(At War)" label, and marks tracked faction in gold
This commit is contained in:
Kelsi 2026-03-12 23:30:44 -07:00
parent 1d9dc6dcae
commit de5c122307
3 changed files with 126 additions and 22 deletions

View file

@ -1420,10 +1420,13 @@ void InventoryScreen::renderReputationPanel(game::GameHandler& gameHandler) {
ImGui::BeginChild("##ReputationList", ImVec2(0, 0), true);
// Sort factions alphabetically by name
// Sort: watched faction first, then alphabetically by name
uint32_t watchedFactionId = gameHandler.getWatchedFactionId();
std::vector<std::pair<uint32_t, int32_t>> sortedFactions(standings.begin(), standings.end());
std::sort(sortedFactions.begin(), sortedFactions.end(),
[&](const auto& a, const auto& b) {
if (a.first == watchedFactionId) return true;
if (b.first == watchedFactionId) return false;
const std::string& na = gameHandler.getFactionNamePublic(a.first);
const std::string& nb = gameHandler.getFactionNamePublic(b.first);
return na < nb;
@ -1435,10 +1438,25 @@ void InventoryScreen::renderReputationPanel(game::GameHandler& gameHandler) {
const std::string& factionName = gameHandler.getFactionNamePublic(factionId);
const char* displayName = factionName.empty() ? "Unknown Faction" : factionName.c_str();
// Faction name + tier label on same line
// Determine at-war status via repListId lookup
uint32_t repListId = gameHandler.getRepListIdByFactionId(factionId);
bool atWar = (repListId != 0xFFFFFFFFu) && gameHandler.isFactionAtWar(repListId);
bool isWatched = (factionId == watchedFactionId);
// Faction name + tier label on same line; mark at-war and watched factions
ImGui::TextColored(tier.color, "[%s]", tier.name);
ImGui::SameLine(90.0f);
ImGui::Text("%s", displayName);
if (atWar) {
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "%s", displayName);
ImGui::SameLine();
ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f), "(At War)");
} else if (isWatched) {
ImGui::TextColored(ImVec4(1.0f, 0.9f, 0.5f, 1.0f), "%s", displayName);
ImGui::SameLine();
ImGui::TextDisabled("(Tracked)");
} else {
ImGui::Text("%s", displayName);
}
// Progress bar showing position within current tier
float ratio = 0.0f;