mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
fix: restore correct CharSections.dbc field indices for character textures
PR #19 (572bb4ef) swapped CharSections.dbc field indices, placing
Texture1-3 at fields 4-6 and VariationIndex/ColorIndex at 8-9. Binary
analysis of the actual DBC files (Classic, TBC, Turtle — all identical
layout, no WotLK-specific override) confirms the correct order is:
Field 4 = VariationIndex
Field 5 = ColorIndex
Field 6 = Texture1 (string)
Field 7 = Texture2 (string)
Field 8 = Texture3 (string)
Field 9 = Flags
With the wrong indices, VariationIndex/ColorIndex reads returned string
offsets (garbage values that never matched), so all CharSections lookups
failed silently — producing white untextured character models at the
login screen and in-world.
Fixes all 4 expansion JSON layouts, hardcoded fallbacks in
character_preview.cpp, application.cpp, and character_create_screen.cpp.
Also handles the single-layer edge case (body skin only, no face/underwear)
by loading the texture directly instead of skipping compositing.
This commit is contained in:
parent
329a1f4b12
commit
e9ce062112
7 changed files with 49 additions and 38 deletions
|
|
@ -37,12 +37,12 @@
|
|||
"RaceID": 1,
|
||||
"SexID": 2,
|
||||
"BaseSection": 3,
|
||||
"Texture1": 4,
|
||||
"Texture2": 5,
|
||||
"Texture3": 6,
|
||||
"Flags": 7,
|
||||
"VariationIndex": 8,
|
||||
"ColorIndex": 9
|
||||
"VariationIndex": 4,
|
||||
"ColorIndex": 5,
|
||||
"Texture1": 6,
|
||||
"Texture2": 7,
|
||||
"Texture3": 8,
|
||||
"Flags": 9
|
||||
},
|
||||
"SpellIcon": {
|
||||
"ID": 0,
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@
|
|||
"RaceID": 1,
|
||||
"SexID": 2,
|
||||
"BaseSection": 3,
|
||||
"Texture1": 4,
|
||||
"Texture2": 5,
|
||||
"Texture3": 6,
|
||||
"Flags": 7,
|
||||
"VariationIndex": 8,
|
||||
"ColorIndex": 9
|
||||
"VariationIndex": 4,
|
||||
"ColorIndex": 5,
|
||||
"Texture1": 6,
|
||||
"Texture2": 7,
|
||||
"Texture3": 8,
|
||||
"Flags": 9
|
||||
},
|
||||
"SpellIcon": {
|
||||
"ID": 0,
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@
|
|||
"RaceID": 1,
|
||||
"SexID": 2,
|
||||
"BaseSection": 3,
|
||||
"Texture1": 4,
|
||||
"Texture2": 5,
|
||||
"Texture3": 6,
|
||||
"Flags": 7,
|
||||
"VariationIndex": 8,
|
||||
"ColorIndex": 9
|
||||
"VariationIndex": 4,
|
||||
"ColorIndex": 5,
|
||||
"Texture1": 6,
|
||||
"Texture2": 7,
|
||||
"Texture3": 8,
|
||||
"Flags": 9
|
||||
},
|
||||
"SpellIcon": {
|
||||
"ID": 0,
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@
|
|||
"RaceID": 1,
|
||||
"SexID": 2,
|
||||
"BaseSection": 3,
|
||||
"Texture1": 4,
|
||||
"Texture2": 5,
|
||||
"Texture3": 6,
|
||||
"Flags": 7,
|
||||
"VariationIndex": 8,
|
||||
"ColorIndex": 9
|
||||
"VariationIndex": 4,
|
||||
"ColorIndex": 5,
|
||||
"Texture1": 6,
|
||||
"Texture2": 7,
|
||||
"Texture3": 8,
|
||||
"Flags": 9
|
||||
},
|
||||
"SpellIcon": {
|
||||
"ID": 0,
|
||||
|
|
|
|||
|
|
@ -3671,13 +3671,13 @@ void Application::spawnPlayerCharacter() {
|
|||
uint32_t raceId = charSectionsDbc->getUInt32(r, csL ? (*csL)["RaceID"] : 1);
|
||||
uint32_t sexId = charSectionsDbc->getUInt32(r, csL ? (*csL)["SexID"] : 2);
|
||||
uint32_t baseSection = charSectionsDbc->getUInt32(r, csL ? (*csL)["BaseSection"] : 3);
|
||||
uint32_t variationIndex = charSectionsDbc->getUInt32(r, csL ? (*csL)["VariationIndex"] : 8);
|
||||
uint32_t colorIndex = charSectionsDbc->getUInt32(r, csL ? (*csL)["ColorIndex"] : 9);
|
||||
uint32_t variationIndex = charSectionsDbc->getUInt32(r, csL ? (*csL)["VariationIndex"] : 4);
|
||||
uint32_t colorIndex = charSectionsDbc->getUInt32(r, csL ? (*csL)["ColorIndex"] : 5);
|
||||
|
||||
if (raceId != targetRaceId || sexId != targetSexId) continue;
|
||||
|
||||
// Section 0 = skin: match by colorIndex = skin byte
|
||||
const uint32_t csTex1 = csL ? (*csL)["Texture1"] : 4;
|
||||
const uint32_t csTex1 = csL ? (*csL)["Texture1"] : 6;
|
||||
if (baseSection == 0 && !foundSkin && colorIndex == charSkinId) {
|
||||
std::string tex1 = charSectionsDbc->getString(r, csTex1);
|
||||
if (!tex1.empty()) {
|
||||
|
|
|
|||
|
|
@ -336,8 +336,8 @@ bool CharacterPreview::loadCharacter(game::Race race, game::Gender gender,
|
|||
uint32_t fRace = csL ? (*csL)["RaceID"] : 1;
|
||||
uint32_t fSex = csL ? (*csL)["SexID"] : 2;
|
||||
uint32_t fBase = csL ? (*csL)["BaseSection"] : 3;
|
||||
uint32_t fVar = csL ? (*csL)["VariationIndex"] : 8;
|
||||
uint32_t fColor = csL ? (*csL)["ColorIndex"] : 9;
|
||||
uint32_t fVar = csL ? (*csL)["VariationIndex"] : 4;
|
||||
uint32_t fColor = csL ? (*csL)["ColorIndex"] : 5;
|
||||
for (uint32_t r = 0; r < charSectionsDbc->getRecordCount(); r++) {
|
||||
uint32_t raceId = charSectionsDbc->getUInt32(r, fRace);
|
||||
uint32_t sexId = charSectionsDbc->getUInt32(r, fSex);
|
||||
|
|
@ -350,7 +350,7 @@ bool CharacterPreview::loadCharacter(game::Race race, game::Gender gender,
|
|||
// Section 0: Body skin (variation=0, colorIndex = skin color)
|
||||
if (baseSection == 0 && !foundSkin &&
|
||||
variationIndex == 0 && colorIndex == static_cast<uint32_t>(skin)) {
|
||||
std::string tex1 = charSectionsDbc->getString(r, csL ? (*csL)["Texture1"] : 4);
|
||||
std::string tex1 = charSectionsDbc->getString(r, csL ? (*csL)["Texture1"] : 6);
|
||||
if (!tex1.empty()) {
|
||||
bodySkinPath_ = tex1;
|
||||
foundSkin = true;
|
||||
|
|
@ -360,8 +360,8 @@ bool CharacterPreview::loadCharacter(game::Race race, game::Gender gender,
|
|||
else if (baseSection == 1 && !foundFace &&
|
||||
variationIndex == static_cast<uint32_t>(face) &&
|
||||
colorIndex == static_cast<uint32_t>(skin)) {
|
||||
std::string tex1 = charSectionsDbc->getString(r, csL ? (*csL)["Texture1"] : 4);
|
||||
std::string tex2 = charSectionsDbc->getString(r, csL ? (*csL)["Texture2"] : 5);
|
||||
std::string tex1 = charSectionsDbc->getString(r, csL ? (*csL)["Texture1"] : 6);
|
||||
std::string tex2 = charSectionsDbc->getString(r, csL ? (*csL)["Texture2"] : 7);
|
||||
if (!tex1.empty()) faceLowerPath = tex1;
|
||||
if (!tex2.empty()) faceUpperPath = tex2;
|
||||
foundFace = true;
|
||||
|
|
@ -370,7 +370,7 @@ bool CharacterPreview::loadCharacter(game::Race race, game::Gender gender,
|
|||
else if (baseSection == 3 && !foundHair &&
|
||||
variationIndex == static_cast<uint32_t>(hairStyle) &&
|
||||
colorIndex == static_cast<uint32_t>(hairColor)) {
|
||||
std::string tex1 = charSectionsDbc->getString(r, csL ? (*csL)["Texture1"] : 4);
|
||||
std::string tex1 = charSectionsDbc->getString(r, csL ? (*csL)["Texture1"] : 6);
|
||||
if (!tex1.empty()) {
|
||||
hairScalpPath = tex1;
|
||||
foundHair = true;
|
||||
|
|
@ -379,7 +379,7 @@ bool CharacterPreview::loadCharacter(game::Race race, game::Gender gender,
|
|||
// Section 4: Underwear (variation=0, colorIndex = skin color)
|
||||
else if (baseSection == 4 && !foundUnderwear &&
|
||||
variationIndex == 0 && colorIndex == static_cast<uint32_t>(skin)) {
|
||||
uint32_t texBase = csL ? (*csL)["Texture1"] : 4;
|
||||
uint32_t texBase = csL ? (*csL)["Texture1"] : 6;
|
||||
for (uint32_t f = texBase; f <= texBase + 2; f++) {
|
||||
std::string tex = charSectionsDbc->getString(r, f);
|
||||
if (!tex.empty()) {
|
||||
|
|
@ -462,6 +462,17 @@ bool CharacterPreview::loadCharacter(game::Race race, game::Gender gender,
|
|||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Single layer (body skin only, no face/underwear overlays) — load directly
|
||||
VkTexture* skinTex = charRenderer_->loadTexture(bodySkinPath_);
|
||||
if (skinTex != nullptr) {
|
||||
for (size_t ti = 0; ti < model.textures.size(); ti++) {
|
||||
if (model.textures[ti].type == 1) {
|
||||
charRenderer_->setModelTexture(PREVIEW_MODEL_ID, static_cast<uint32_t>(ti), skinTex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -257,8 +257,8 @@ void CharacterCreateScreen::updateAppearanceRanges() {
|
|||
if (raceId != targetRaceId || sexId != targetSexId) continue;
|
||||
|
||||
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);
|
||||
uint32_t variationIndex = dbc->getUInt32(r, csL ? (*csL)["VariationIndex"] : 4);
|
||||
uint32_t colorIndex = dbc->getUInt32(r, csL ? (*csL)["ColorIndex"] : 5);
|
||||
|
||||
if (baseSection == 0 && variationIndex == 0) {
|
||||
skinMax = std::max(skinMax, static_cast<int>(colorIndex));
|
||||
|
|
@ -284,8 +284,8 @@ void CharacterCreateScreen::updateAppearanceRanges() {
|
|||
if (raceId != targetRaceId || sexId != targetSexId) continue;
|
||||
|
||||
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);
|
||||
uint32_t variationIndex = dbc->getUInt32(r, csL ? (*csL)["VariationIndex"] : 4);
|
||||
uint32_t colorIndex = dbc->getUInt32(r, csL ? (*csL)["ColorIndex"] : 5);
|
||||
|
||||
if (baseSection == 1 && colorIndex == static_cast<uint32_t>(skin)) {
|
||||
faceMax = std::max(faceMax, static_cast<int>(variationIndex));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue