mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-27 05:23:51 +00:00
Add multi-expansion support with data-driven protocol layer
Replace hardcoded WotLK protocol constants with a data-driven architecture supporting Classic 1.12.1, TBC 2.4.3, and WotLK 3.3.5a. Each expansion has JSON profiles for opcodes, update fields, and DBC layouts, plus C++ polymorphic packet parsers for binary format differences (movement flags, speed fields, transport data, spline format, char enum layout). Key components: - ExpansionRegistry: scans Data/expansions/*/expansion.json at startup - OpcodeTable: logical enum <-> wire values loaded from JSON - UpdateFieldTable: field indices loaded from JSON per expansion - DBCLayout: schema-driven DBC field lookups replacing magic numbers - PacketParsers: WotLK/TBC/Classic parsers with correct flag positions - Multi-manifest AssetManager: layered manifests with priority ordering - HDPackManager: overlay texture packs with expansion compatibility - Auth screen expansion picker replacing hardcoded version dropdown
This commit is contained in:
parent
aa16a687c2
commit
7092844b5e
51 changed files with 5258 additions and 887 deletions
|
|
@ -5,6 +5,7 @@
|
|||
#include "rendering/renderer.hpp"
|
||||
#include "pipeline/asset_manager.hpp"
|
||||
#include "audio/music_manager.hpp"
|
||||
#include "game/expansion_profile.hpp"
|
||||
#include <imgui.h>
|
||||
#include <filesystem>
|
||||
#include <sstream>
|
||||
|
|
@ -148,9 +149,30 @@ void AuthScreen::render(auth::AuthHandler& authHandler) {
|
|||
if (port < 1) port = 1;
|
||||
if (port > 65535) port = 65535;
|
||||
|
||||
// Compatibility mode dropdown
|
||||
const char* compatModes[] = { "3.3.5a" };
|
||||
ImGui::Combo("Compatibility Mode", &compatibilityMode, compatModes, IM_ARRAYSIZE(compatModes));
|
||||
// Expansion selector (populated from ExpansionRegistry)
|
||||
auto* registry = core::Application::getInstance().getExpansionRegistry();
|
||||
if (registry && !registry->getAllProfiles().empty()) {
|
||||
auto& profiles = registry->getAllProfiles();
|
||||
// Build combo items: "WotLK (3.3.5a)"
|
||||
std::string preview;
|
||||
if (expansionIndex >= 0 && expansionIndex < static_cast<int>(profiles.size())) {
|
||||
preview = profiles[expansionIndex].shortName + " (" + profiles[expansionIndex].versionString() + ")";
|
||||
}
|
||||
if (ImGui::BeginCombo("Expansion", preview.c_str())) {
|
||||
for (int i = 0; i < static_cast<int>(profiles.size()); ++i) {
|
||||
std::string label = profiles[i].shortName + " (" + profiles[i].versionString() + ")";
|
||||
bool selected = (expansionIndex == i);
|
||||
if (ImGui::Selectable(label.c_str(), selected)) {
|
||||
expansionIndex = i;
|
||||
registry->setActive(profiles[i].id);
|
||||
}
|
||||
if (selected) ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("Expansion: WotLK 3.3.5a (default)");
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
|
|
@ -291,6 +313,21 @@ void AuthScreen::attemptAuth(auth::AuthHandler& authHandler) {
|
|||
failureReason = reason;
|
||||
});
|
||||
|
||||
// Configure client version from active expansion profile
|
||||
auto* reg = core::Application::getInstance().getExpansionRegistry();
|
||||
if (reg) {
|
||||
auto* profile = reg->getActive();
|
||||
if (profile) {
|
||||
auth::ClientInfo info;
|
||||
info.majorVersion = profile->majorVersion;
|
||||
info.minorVersion = profile->minorVersion;
|
||||
info.patchVersion = profile->patchVersion;
|
||||
info.build = profile->build;
|
||||
info.protocolVersion = profile->protocolVersion;
|
||||
authHandler.setClientInfo(info);
|
||||
}
|
||||
}
|
||||
|
||||
if (authHandler.connect(hostname, static_cast<uint16_t>(port))) {
|
||||
authenticating = true;
|
||||
authTimer = 0.0f;
|
||||
|
|
@ -350,6 +387,11 @@ void AuthScreen::saveLoginInfo() {
|
|||
if (!savedPasswordHash.empty()) {
|
||||
out << "password_hash=" << savedPasswordHash << "\n";
|
||||
}
|
||||
// Save active expansion id
|
||||
auto* expReg = core::Application::getInstance().getExpansionRegistry();
|
||||
if (expReg && !expReg->getActiveId().empty()) {
|
||||
out << "expansion=" << expReg->getActiveId() << "\n";
|
||||
}
|
||||
|
||||
LOG_INFO("Login info saved to ", path);
|
||||
}
|
||||
|
|
@ -376,6 +418,15 @@ void AuthScreen::loadLoginInfo() {
|
|||
username[sizeof(username) - 1] = '\0';
|
||||
} else if (key == "password_hash" && !val.empty()) {
|
||||
savedPasswordHash = val;
|
||||
} else if (key == "expansion" && !val.empty()) {
|
||||
auto* expReg = core::Application::getInstance().getExpansionRegistry();
|
||||
if (expReg && expReg->setActive(val)) {
|
||||
// Find matching index
|
||||
auto& profiles = expReg->getAllProfiles();
|
||||
for (int i = 0; i < static_cast<int>(profiles.size()); ++i) {
|
||||
if (profiles[i].id == val) { expansionIndex = i; break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "rendering/character_preview.hpp"
|
||||
#include "game/game_handler.hpp"
|
||||
#include "pipeline/asset_manager.hpp"
|
||||
#include "pipeline/dbc_layout.hpp"
|
||||
#include <imgui.h>
|
||||
#include <cstring>
|
||||
|
||||
|
|
@ -169,16 +170,17 @@ void CharacterCreateScreen::updateAppearanceRanges() {
|
|||
uint32_t targetRaceId = static_cast<uint32_t>(allRaces[raceIndex]);
|
||||
uint32_t targetSexId = (genderIndex == 1) ? 1u : 0u;
|
||||
|
||||
const auto* csL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("CharSections") : nullptr;
|
||||
int skinMax = -1;
|
||||
int hairStyleMax = -1;
|
||||
for (uint32_t r = 0; r < dbc->getRecordCount(); r++) {
|
||||
uint32_t raceId = dbc->getUInt32(r, 1);
|
||||
uint32_t sexId = dbc->getUInt32(r, 2);
|
||||
uint32_t raceId = dbc->getUInt32(r, csL ? (*csL)["RaceID"] : 1);
|
||||
uint32_t sexId = dbc->getUInt32(r, csL ? (*csL)["SexID"] : 2);
|
||||
if (raceId != targetRaceId || sexId != targetSexId) continue;
|
||||
|
||||
uint32_t baseSection = dbc->getUInt32(r, 3);
|
||||
uint32_t variationIndex = dbc->getUInt32(r, 8);
|
||||
uint32_t colorIndex = dbc->getUInt32(r, 9);
|
||||
uint32_t baseSection = dbc->getUInt32(r, csL ? (*csL)["BaseSection"] : 3);
|
||||
uint32_t variationIndex = dbc->getUInt32(r, csL ? (*csL)["VariationIndex"] : 8);
|
||||
uint32_t colorIndex = dbc->getUInt32(r, csL ? (*csL)["ColorIndex"] : 9);
|
||||
|
||||
if (baseSection == 0 && variationIndex == 0) {
|
||||
skinMax = std::max(skinMax, static_cast<int>(colorIndex));
|
||||
|
|
@ -199,13 +201,13 @@ void CharacterCreateScreen::updateAppearanceRanges() {
|
|||
int faceMax = -1;
|
||||
std::vector<uint8_t> hairColorIds;
|
||||
for (uint32_t r = 0; r < dbc->getRecordCount(); r++) {
|
||||
uint32_t raceId = dbc->getUInt32(r, 1);
|
||||
uint32_t sexId = dbc->getUInt32(r, 2);
|
||||
uint32_t raceId = dbc->getUInt32(r, csL ? (*csL)["RaceID"] : 1);
|
||||
uint32_t sexId = dbc->getUInt32(r, csL ? (*csL)["SexID"] : 2);
|
||||
if (raceId != targetRaceId || sexId != targetSexId) continue;
|
||||
|
||||
uint32_t baseSection = dbc->getUInt32(r, 3);
|
||||
uint32_t variationIndex = dbc->getUInt32(r, 8);
|
||||
uint32_t colorIndex = dbc->getUInt32(r, 9);
|
||||
uint32_t baseSection = dbc->getUInt32(r, csL ? (*csL)["BaseSection"] : 3);
|
||||
uint32_t variationIndex = dbc->getUInt32(r, csL ? (*csL)["VariationIndex"] : 8);
|
||||
uint32_t colorIndex = dbc->getUInt32(r, csL ? (*csL)["ColorIndex"] : 9);
|
||||
|
||||
if (baseSection == 1 && colorIndex == static_cast<uint32_t>(skin)) {
|
||||
faceMax = std::max(faceMax, static_cast<int>(variationIndex));
|
||||
|
|
@ -232,12 +234,13 @@ void CharacterCreateScreen::updateAppearanceRanges() {
|
|||
}
|
||||
int facialMax = -1;
|
||||
auto facialDbc = assetManager_->loadDBC("CharacterFacialHairStyles.dbc");
|
||||
const auto* fhL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("CharacterFacialHairStyles") : nullptr;
|
||||
if (facialDbc) {
|
||||
for (uint32_t r = 0; r < facialDbc->getRecordCount(); r++) {
|
||||
uint32_t raceId = facialDbc->getUInt32(r, 0);
|
||||
uint32_t sexId = facialDbc->getUInt32(r, 1);
|
||||
uint32_t raceId = facialDbc->getUInt32(r, fhL ? (*fhL)["RaceID"] : 0);
|
||||
uint32_t sexId = facialDbc->getUInt32(r, fhL ? (*fhL)["SexID"] : 1);
|
||||
if (raceId != targetRaceId || sexId != targetSexId) continue;
|
||||
uint32_t variation = facialDbc->getUInt32(r, 2);
|
||||
uint32_t variation = facialDbc->getUInt32(r, fhL ? (*fhL)["Variation"] : 2);
|
||||
facialMax = std::max(facialMax, static_cast<int>(variation));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@
|
|||
#include "pipeline/asset_manager.hpp"
|
||||
#include "pipeline/dbc_loader.hpp"
|
||||
#include "pipeline/blp_loader.hpp"
|
||||
#include "pipeline/dbc_layout.hpp"
|
||||
#include "pipeline/hd_pack_manager.hpp"
|
||||
#include "game/expansion_profile.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include <imgui.h>
|
||||
#include <algorithm>
|
||||
|
|
@ -2360,7 +2363,8 @@ void GameScreen::updateCharacterTextures(game::Inventory& inventory) {
|
|||
int32_t recIdx = displayInfoDbc->findRecordById(cloakDisplayId);
|
||||
if (recIdx >= 0) {
|
||||
// DBC field 3 = modelTexture_1 (cape texture name)
|
||||
std::string capeName = displayInfoDbc->getString(static_cast<uint32_t>(recIdx), 3);
|
||||
const auto* dispL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("ItemDisplayInfo") : nullptr;
|
||||
std::string capeName = displayInfoDbc->getString(static_cast<uint32_t>(recIdx), dispL ? (*dispL)["LeftModelTexture"] : 3);
|
||||
if (!capeName.empty()) {
|
||||
std::string capePath = "Item\\ObjectComponents\\Cape\\" + capeName + ".blp";
|
||||
GLuint capeTex = charRenderer->loadTexture(capePath);
|
||||
|
|
@ -2422,10 +2426,11 @@ GLuint GameScreen::getSpellIcon(uint32_t spellId, pipeline::AssetManager* am) {
|
|||
|
||||
// Load SpellIcon.dbc: field 0 = ID, field 1 = icon path
|
||||
auto iconDbc = am->loadDBC("SpellIcon.dbc");
|
||||
const auto* iconL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("SpellIcon") : nullptr;
|
||||
if (iconDbc && iconDbc->isLoaded()) {
|
||||
for (uint32_t i = 0; i < iconDbc->getRecordCount(); i++) {
|
||||
uint32_t id = iconDbc->getUInt32(i, 0);
|
||||
std::string path = iconDbc->getString(i, 1);
|
||||
uint32_t id = iconDbc->getUInt32(i, iconL ? (*iconL)["ID"] : 0);
|
||||
std::string path = iconDbc->getString(i, iconL ? (*iconL)["Path"] : 1);
|
||||
if (!path.empty() && id > 0) {
|
||||
spellIconPaths_[id] = path;
|
||||
}
|
||||
|
|
@ -2434,10 +2439,11 @@ GLuint GameScreen::getSpellIcon(uint32_t spellId, pipeline::AssetManager* am) {
|
|||
|
||||
// Load Spell.dbc: field 133 = SpellIconID
|
||||
auto spellDbc = am->loadDBC("Spell.dbc");
|
||||
const auto* spellL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("Spell") : nullptr;
|
||||
if (spellDbc && spellDbc->isLoaded() && spellDbc->getFieldCount() > 133) {
|
||||
for (uint32_t i = 0; i < spellDbc->getRecordCount(); i++) {
|
||||
uint32_t id = spellDbc->getUInt32(i, 0);
|
||||
uint32_t iconId = spellDbc->getUInt32(i, 133);
|
||||
uint32_t id = spellDbc->getUInt32(i, spellL ? (*spellL)["ID"] : 0);
|
||||
uint32_t iconId = spellDbc->getUInt32(i, spellL ? (*spellL)["IconID"] : 133);
|
||||
if (id > 0 && iconId > 0) {
|
||||
spellIconIds_[id] = iconId;
|
||||
}
|
||||
|
|
@ -2530,8 +2536,9 @@ void GameScreen::renderActionBar(game::GameHandler& gameHandler) {
|
|||
if (assetMgr && assetMgr->isInitialized()) {
|
||||
auto dbc = assetMgr->loadDBC("Spell.dbc");
|
||||
if (dbc && dbc->isLoaded()) {
|
||||
const auto* actionSpellL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("Spell") : nullptr;
|
||||
uint32_t fieldCount = dbc->getFieldCount();
|
||||
uint32_t nameField = 136;
|
||||
uint32_t nameField = actionSpellL ? (*actionSpellL)["Name"] : 136;
|
||||
if (fieldCount < 137) {
|
||||
if (fieldCount > 10) {
|
||||
nameField = fieldCount > 140 ? 136 : 1;
|
||||
|
|
@ -2542,7 +2549,7 @@ void GameScreen::renderActionBar(game::GameHandler& gameHandler) {
|
|||
uint32_t count = dbc->getRecordCount();
|
||||
actionSpellNames.reserve(count);
|
||||
for (uint32_t r = 0; r < count; ++r) {
|
||||
uint32_t id = dbc->getUInt32(r, 0);
|
||||
uint32_t id = dbc->getUInt32(r, actionSpellL ? (*actionSpellL)["ID"] : 0);
|
||||
std::string name = dbc->getString(r, nameField);
|
||||
if (!name.empty() && id > 0) {
|
||||
actionSpellNames[id] = name;
|
||||
|
|
@ -4835,6 +4842,79 @@ void GameScreen::renderSettingsWindow() {
|
|||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// HD TEXTURES TAB
|
||||
// ============================================================
|
||||
if (ImGui::BeginTabItem("HD Textures")) {
|
||||
ImGui::Spacing();
|
||||
|
||||
auto& app = core::Application::getInstance();
|
||||
auto* hdMgr = app.getHDPackManager();
|
||||
|
||||
if (hdMgr) {
|
||||
const auto& packs = hdMgr->getAllPacks();
|
||||
if (packs.empty()) {
|
||||
ImGui::TextWrapped("No HD texture packs found.");
|
||||
ImGui::Spacing();
|
||||
ImGui::TextWrapped("Place packs in Data/hd/<pack_name>/ with a pack.json and manifest.json.");
|
||||
} else {
|
||||
ImGui::Text("Available HD Texture Packs:");
|
||||
ImGui::Spacing();
|
||||
|
||||
bool changed = false;
|
||||
for (const auto& pack : packs) {
|
||||
bool enabled = pack.enabled;
|
||||
if (ImGui::Checkbox(pack.name.c_str(), &enabled)) {
|
||||
hdMgr->setPackEnabled(pack.id, enabled);
|
||||
changed = true;
|
||||
}
|
||||
ImGui::SameLine(0, 10);
|
||||
ImGui::TextDisabled("(%u MB)", pack.totalSizeMB);
|
||||
if (!pack.group.empty()) {
|
||||
ImGui::SameLine(0, 10);
|
||||
ImGui::TextDisabled("[%s]", pack.group.c_str());
|
||||
}
|
||||
if (!pack.expansions.empty()) {
|
||||
std::string expList;
|
||||
for (const auto& e : pack.expansions) {
|
||||
if (!expList.empty()) expList += ", ";
|
||||
expList += e;
|
||||
}
|
||||
ImGui::TextDisabled(" Compatible: %s", expList.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
if (ImGui::Button("Apply HD Packs", ImVec2(-1, 0))) {
|
||||
std::string expansionId = "wotlk";
|
||||
if (app.getExpansionRegistry() && app.getExpansionRegistry()->getActive()) {
|
||||
expansionId = app.getExpansionRegistry()->getActive()->id;
|
||||
}
|
||||
hdMgr->applyToAssetManager(app.getAssetManager(), expansionId);
|
||||
|
||||
// Save settings
|
||||
std::string settingsDir;
|
||||
const char* xdg = std::getenv("XDG_DATA_HOME");
|
||||
if (xdg && *xdg) {
|
||||
settingsDir = std::string(xdg) + "/wowee";
|
||||
} else {
|
||||
const char* home = std::getenv("HOME");
|
||||
settingsDir = std::string(home ? home : ".") + "/.local/share/wowee";
|
||||
}
|
||||
hdMgr->saveSettings(settingsDir + "/settings.cfg");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ImGui::Text("HD Pack Manager not available.");
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "pipeline/asset_manager.hpp"
|
||||
#include "pipeline/dbc_loader.hpp"
|
||||
#include "pipeline/blp_loader.hpp"
|
||||
#include "pipeline/dbc_layout.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include <imgui.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
|
@ -60,7 +61,8 @@ GLuint InventoryScreen::getItemIcon(uint32_t displayInfoId) {
|
|||
}
|
||||
|
||||
// Field 5 = inventoryIcon_1
|
||||
std::string iconName = displayInfoDbc->getString(static_cast<uint32_t>(recIdx), 5);
|
||||
const auto* dispL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("ItemDisplayInfo") : nullptr;
|
||||
std::string iconName = displayInfoDbc->getString(static_cast<uint32_t>(recIdx), dispL ? (*dispL)["InventoryIcon"] : 5);
|
||||
if (iconName.empty()) {
|
||||
iconCache_[displayInfoId] = 0;
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "pipeline/asset_manager.hpp"
|
||||
#include "pipeline/dbc_loader.hpp"
|
||||
#include "pipeline/blp_loader.hpp"
|
||||
#include "pipeline/dbc_layout.hpp"
|
||||
#include "core/logger.hpp"
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
|
@ -30,17 +31,18 @@ void SpellbookScreen::loadSpellDBC(pipeline::AssetManager* assetManager) {
|
|||
|
||||
// WoW 3.3.5a Spell.dbc fields (0-based):
|
||||
// 0 = SpellID, 4 = Attributes, 133 = SpellIconID, 136 = SpellName_enUS, 153 = RankText_enUS
|
||||
const auto* spellL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("Spell") : nullptr;
|
||||
uint32_t count = dbc->getRecordCount();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
uint32_t spellId = dbc->getUInt32(i, 0);
|
||||
uint32_t spellId = dbc->getUInt32(i, spellL ? (*spellL)["ID"] : 0);
|
||||
if (spellId == 0) continue;
|
||||
|
||||
SpellInfo info;
|
||||
info.spellId = spellId;
|
||||
info.attributes = dbc->getUInt32(i, 4);
|
||||
info.iconId = dbc->getUInt32(i, 133);
|
||||
info.name = dbc->getString(i, 136);
|
||||
info.rank = dbc->getString(i, 153);
|
||||
info.attributes = dbc->getUInt32(i, spellL ? (*spellL)["Attributes"] : 4);
|
||||
info.iconId = dbc->getUInt32(i, spellL ? (*spellL)["IconID"] : 133);
|
||||
info.name = dbc->getString(i, spellL ? (*spellL)["Name"] : 136);
|
||||
info.rank = dbc->getString(i, spellL ? (*spellL)["Rank"] : 153);
|
||||
|
||||
if (!info.name.empty()) {
|
||||
spellData[spellId] = std::move(info);
|
||||
|
|
@ -63,9 +65,10 @@ void SpellbookScreen::loadSpellIconDBC(pipeline::AssetManager* assetManager) {
|
|||
return;
|
||||
}
|
||||
|
||||
const auto* iconL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("SpellIcon") : nullptr;
|
||||
for (uint32_t i = 0; i < dbc->getRecordCount(); i++) {
|
||||
uint32_t id = dbc->getUInt32(i, 0);
|
||||
std::string path = dbc->getString(i, 1);
|
||||
uint32_t id = dbc->getUInt32(i, iconL ? (*iconL)["ID"] : 0);
|
||||
std::string path = dbc->getString(i, iconL ? (*iconL)["Path"] : 1);
|
||||
if (!path.empty() && id > 0) {
|
||||
spellIconPaths[id] = path;
|
||||
}
|
||||
|
|
@ -82,11 +85,12 @@ void SpellbookScreen::loadSkillLineDBCs(pipeline::AssetManager* assetManager) {
|
|||
|
||||
// Load SkillLine.dbc: field 0 = ID, field 1 = categoryID, field 3 = name_enUS
|
||||
auto skillLineDbc = assetManager->loadDBC("SkillLine.dbc");
|
||||
const auto* slL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("SkillLine") : nullptr;
|
||||
if (skillLineDbc && skillLineDbc->isLoaded()) {
|
||||
for (uint32_t i = 0; i < skillLineDbc->getRecordCount(); i++) {
|
||||
uint32_t id = skillLineDbc->getUInt32(i, 0);
|
||||
uint32_t category = skillLineDbc->getUInt32(i, 1);
|
||||
std::string name = skillLineDbc->getString(i, 3);
|
||||
uint32_t id = skillLineDbc->getUInt32(i, slL ? (*slL)["ID"] : 0);
|
||||
uint32_t category = skillLineDbc->getUInt32(i, slL ? (*slL)["Category"] : 1);
|
||||
std::string name = skillLineDbc->getString(i, slL ? (*slL)["Name"] : 3);
|
||||
if (id > 0 && !name.empty()) {
|
||||
skillLineNames[id] = name;
|
||||
skillLineCategories[id] = category;
|
||||
|
|
@ -99,10 +103,11 @@ void SpellbookScreen::loadSkillLineDBCs(pipeline::AssetManager* assetManager) {
|
|||
|
||||
// Load SkillLineAbility.dbc: field 0 = ID, field 1 = skillLineID, field 2 = spellID
|
||||
auto slaDbc = assetManager->loadDBC("SkillLineAbility.dbc");
|
||||
const auto* slaL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("SkillLineAbility") : nullptr;
|
||||
if (slaDbc && slaDbc->isLoaded()) {
|
||||
for (uint32_t i = 0; i < slaDbc->getRecordCount(); i++) {
|
||||
uint32_t skillLineId = slaDbc->getUInt32(i, 1);
|
||||
uint32_t spellId = slaDbc->getUInt32(i, 2);
|
||||
uint32_t skillLineId = slaDbc->getUInt32(i, slaL ? (*slaL)["SkillLineID"] : 1);
|
||||
uint32_t spellId = slaDbc->getUInt32(i, slaL ? (*slaL)["SpellID"] : 2);
|
||||
if (spellId > 0 && skillLineId > 0) {
|
||||
spellToSkillLine[spellId] = skillLineId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/logger.hpp"
|
||||
#include "pipeline/asset_manager.hpp"
|
||||
#include "pipeline/blp_loader.hpp"
|
||||
#include "pipeline/dbc_layout.hpp"
|
||||
#include <algorithm>
|
||||
#include <GL/glew.h>
|
||||
|
||||
|
|
@ -448,15 +449,16 @@ void TalentScreen::loadSpellDBC(pipeline::AssetManager* assetManager) {
|
|||
}
|
||||
|
||||
// WoW 3.3.5a Spell.dbc fields: 0=SpellID, 133=SpellIconID, 136=SpellName_enUS, 139=Tooltip_enUS
|
||||
const auto* spellL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("Spell") : nullptr;
|
||||
uint32_t count = dbc->getRecordCount();
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
uint32_t spellId = dbc->getUInt32(i, 0);
|
||||
uint32_t spellId = dbc->getUInt32(i, spellL ? (*spellL)["ID"] : 0);
|
||||
if (spellId == 0) continue;
|
||||
|
||||
uint32_t iconId = dbc->getUInt32(i, 133);
|
||||
uint32_t iconId = dbc->getUInt32(i, spellL ? (*spellL)["IconID"] : 133);
|
||||
spellIconIds[spellId] = iconId;
|
||||
|
||||
std::string tooltip = dbc->getString(i, 139);
|
||||
std::string tooltip = dbc->getString(i, spellL ? (*spellL)["Tooltip"] : 139);
|
||||
if (!tooltip.empty()) {
|
||||
spellTooltips[spellId] = tooltip;
|
||||
}
|
||||
|
|
@ -477,9 +479,10 @@ void TalentScreen::loadSpellIconDBC(pipeline::AssetManager* assetManager) {
|
|||
return;
|
||||
}
|
||||
|
||||
const auto* iconL = pipeline::getActiveDBCLayout() ? pipeline::getActiveDBCLayout()->getLayout("SpellIcon") : nullptr;
|
||||
for (uint32_t i = 0; i < dbc->getRecordCount(); i++) {
|
||||
uint32_t id = dbc->getUInt32(i, 0);
|
||||
std::string path = dbc->getString(i, 1);
|
||||
uint32_t id = dbc->getUInt32(i, iconL ? (*iconL)["ID"] : 0);
|
||||
std::string path = dbc->getString(i, iconL ? (*iconL)["Path"] : 1);
|
||||
if (!path.empty() && id > 0) {
|
||||
spellIconPaths[id] = path;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue