Skip to content

Commit 40d69ad

Browse files
committed
fix(armory): check the whole per-gender slot block, not just one slot
file_ids splits into two contiguous 5-slot blocks (0-4 male, 5-9 female) rather than a single slot per gender. Walk this gender's block in order, but lazily: only advance past a slot once it's confirmed to have no icon at all (decode finished, no texture), never while it's still resolving. That way a slot that's about to succeed is never skipped past in favor of eagerly trying a later, unrelated slot - which is exactly what caused the earlier spurious load of an entirely invalid file id.
1 parent e97ebd6 commit 40d69ad

1 file changed

Lines changed: 27 additions & 14 deletions

File tree

GWToolboxdll/Modules/Resources.cpp

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,24 +1366,37 @@ IDirect3DTexture9** Resources::GetItemImage(uint32_t model_file_id, uint32_t int
13661366
if (!model_file_id)
13671367
return nullptr;
13681368

1369-
// Composite items (armor/runes) point at the given gender's model slot (file_ids[0] male,
1370-
// file_ids[5] female) - confirmed against the client's own composite-model loader
1371-
// (CICompositePlayer, used by the character-creation dress-up doll): it walks every populated
1372-
// file_ids slot to gather ALL of them as required texture layers for the 3D worn model, with no
1373-
// per-slot priority or "alternate icon" concept - there is no slot that means "the icon". So
1374-
// there's nothing to gain by trying other slots as fallbacks; if the gendered slot has no icon,
1375-
// there isn't one. LoadItemImage/DecodeItemToArgb already covers "check the same file another
1376-
// way" by falling back to that file's own stream 0 when stream 1 (the usual icon substream)
1377-
// doesn't exist. Beyond that, give up - don't guess at unrelated slots.
1378-
uint32_t candidate = model_file_id;
1369+
// Composite items (armor/runes) keep their per-gender variants in one contiguous block of the 11
1370+
// file_ids slots: 0-4 for male, 5-9 for female (slot 10 is unused by anything we've found - see
1371+
// the client's own composite-model loader, CICompositePlayer, used by the character-creation
1372+
// dress-up doll: it just walks every populated slot as an equally-required texture layer for the
1373+
// 3D worn model, no per-slot priority). Try this gender's block in order, one at a time - only
1374+
// advancing to the next slot once the current one is *confirmed* to have no icon at all (not
1375+
// merely still decoding), so a slot that's going to succeed is never skipped past in favour of
1376+
// touching a later, unrelated (and possibly invalid) one. LoadItemImage/DecodeItemToArgb already
1377+
// covers "check this same file another way" via its stream 0 fallback; beyond the block, give up.
13791378
if (interaction & 4) {
13801379
const auto model_file_info = GW::Items::GetCompositeModelInfo(model_file_id);
1381-
const uint32_t gendered = model_file_info ? model_file_info->file_ids[is_female ? 5 : 0] : 0;
1382-
if (gendered)
1383-
candidate = gendered;
1380+
if (model_file_info) {
1381+
const size_t first_slot = is_female ? 5 : 0;
1382+
static IDirect3DTexture9* null_tex = nullptr;
1383+
IDirect3DTexture9** result = &null_tex;
1384+
for (size_t i = first_slot; i < first_slot + 5; ++i) {
1385+
const uint32_t slot_id = model_file_info->file_ids[i];
1386+
if (!slot_id)
1387+
continue;
1388+
bool slot_failed = false;
1389+
result = GwDatModule::LoadItemImage(slot_id, dyes, &slot_failed);
1390+
if (*result || !slot_failed)
1391+
return result; // succeeded, or still resolving - stop here either way
1392+
}
1393+
if (failed_out)
1394+
*failed_out = true;
1395+
return result;
1396+
}
13841397
}
13851398

1386-
return GwDatModule::LoadItemImage(candidate, dyes, failed_out);
1399+
return GwDatModule::LoadItemImage(model_file_id, dyes, failed_out);
13871400
}
13881401

13891402
IDirect3DTexture9** Resources::GetItemImage(GW::Item* item)

0 commit comments

Comments
 (0)