feat: debuff dispel-type border coloring in buff bar

Read DispelType from Spell.dbc (new field in all expansion DBC layouts)
and use it to color debuff icon borders: magic=blue, curse=purple,
disease=brown, poison=green, other=red. Buffs remain green-bordered.
Adds getSpellDispelType() to GameHandler for lazy cache lookup.
This commit is contained in:
Kelsi 2026-03-12 06:55:16 -07:00
parent 9a21e19486
commit d817e4144c
7 changed files with 45 additions and 7 deletions

View file

@ -16983,6 +16983,14 @@ void GameHandler::loadSpellNameCache() {
if (f != 0xFFFFFFFF && f < dbc->getFieldCount()) { schoolEnumField = f; hasSchoolEnum = true; }
}
// DispelType field (0=none,1=magic,2=curse,3=disease,4=poison,5=stealth,…)
uint32_t dispelField = 0xFFFFFFFF;
bool hasDispelField = false;
if (spellL) {
uint32_t f = spellL->field("DispelType");
if (f != 0xFFFFFFFF && f < dbc->getFieldCount()) { dispelField = f; hasDispelField = true; }
}
uint32_t count = dbc->getRecordCount();
for (uint32_t i = 0; i < count; ++i) {
uint32_t id = dbc->getUInt32(i, spellL ? (*spellL)["ID"] : 0);
@ -16990,7 +16998,7 @@ void GameHandler::loadSpellNameCache() {
std::string name = dbc->getString(i, spellL ? (*spellL)["Name"] : 136);
std::string rank = dbc->getString(i, spellL ? (*spellL)["Rank"] : 153);
if (!name.empty()) {
SpellNameEntry entry{std::move(name), std::move(rank), 0};
SpellNameEntry entry{std::move(name), std::move(rank), 0, 0};
if (hasSchoolMask) {
entry.schoolMask = dbc->getUInt32(i, schoolMaskField);
} else if (hasSchoolEnum) {
@ -16999,6 +17007,9 @@ void GameHandler::loadSpellNameCache() {
uint32_t e = dbc->getUInt32(i, schoolEnumField);
entry.schoolMask = (e < 7) ? enumToBitmask[e] : 0;
}
if (hasDispelField) {
entry.dispelType = static_cast<uint8_t>(dbc->getUInt32(i, dispelField));
}
spellNameCache_[id] = std::move(entry);
}
}
@ -17192,6 +17203,12 @@ const std::string& GameHandler::getSpellRank(uint32_t spellId) const {
return (it != spellNameCache_.end()) ? it->second.rank : EMPTY_STRING;
}
uint8_t GameHandler::getSpellDispelType(uint32_t spellId) const {
const_cast<GameHandler*>(this)->loadSpellNameCache();
auto it = spellNameCache_.find(spellId);
return (it != spellNameCache_.end()) ? it->second.dispelType : 0;
}
const std::string& GameHandler::getSkillLineName(uint32_t spellId) const {
auto slIt = spellToSkillLine_.find(spellId);
if (slIt == spellToSkillLine_.end()) return EMPTY_STRING;

View file

@ -9503,7 +9503,22 @@ void GameScreen::renderBuffBar(game::GameHandler& gameHandler) {
ImGui::PushID(static_cast<int>(i) + (pass * 256));
ImVec4 borderColor = isBuff ? ImVec4(0.2f, 0.8f, 0.2f, 0.9f) : ImVec4(0.8f, 0.2f, 0.2f, 0.9f);
// Determine border color: buffs = green; debuffs use WoW dispel-type colors
ImVec4 borderColor;
if (isBuff) {
borderColor = ImVec4(0.2f, 0.8f, 0.2f, 0.9f); // green
} else {
// Debuff: color by dispel type (0=none/red, 1=magic/blue, 2=curse/purple,
// 3=disease/brown, 4=poison/green, other=dark-red)
uint8_t dt = gameHandler.getSpellDispelType(aura.spellId);
switch (dt) {
case 1: borderColor = ImVec4(0.15f, 0.50f, 1.00f, 0.9f); break; // magic: blue
case 2: borderColor = ImVec4(0.70f, 0.20f, 0.90f, 0.9f); break; // curse: purple
case 3: borderColor = ImVec4(0.55f, 0.30f, 0.10f, 0.9f); break; // disease: brown
case 4: borderColor = ImVec4(0.10f, 0.70f, 0.10f, 0.9f); break; // poison: green
default: borderColor = ImVec4(0.80f, 0.20f, 0.20f, 0.9f); break; // other: red
}
}
// Try to get spell icon
VkDescriptorSet iconTex = VK_NULL_HANDLE;