DB/ItemDisplayInfo/GeosRenderPrep: Difference between revisions

From wowdev
Jump to navigation Jump to search
(Updated code for 8.0.1. It's also more clear.)
No edit summary
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
==WOD==
  // GeosetRenderPrep.cpp : Defines the entry point for the console application.
  // GeosetRenderPrep.cpp : Defines the entry point for the console application.
  //
  //
 
  #include "stdafx.h"
  #include "stdafx.h"
 
  int main()
  int main()
  {
  {
return 0;
    return 0;
  }
  }
 
  struct CCharacterComponent
  struct CCharacterComponent
  {
  {
uint32_t raceID;
    uint32_t raceID;
uint32_t classID;
    uint32_t classID;
uint32_t skinIndex;
    uint32_t skinIndex;
uint32_t genderID;
    uint32_t genderID;
uint32_t faceIndex;
    uint32_t faceIndex;
void *modelPtr;
    void *modelPtr;
uint32_t submeshIds[29];
    uint32_t submeshIds[29];
uint32_t itemids[10];
    uint32_t itemids[10];
uint32_t gap2[520];
    uint32_t gap2[520];
uint64_t shirtRelated[6];
    uint64_t shirtRelated[6];
uint32_t flags;
    uint32_t flags;
 
static void GeosRenderPrep(CCharacterComponent *pCharComponent);
    static void GeosRenderPrep(CCharacterComponent *pCharComponent);
  };
  };
 
  struct CharSectionsRec
  struct CharSectionsRec
  {
  {
uint32_t Flags;
    uint32_t Flags;
  };
  };
 
  struct CM2Model
  struct CM2Model
  {
  {
static void SetGeometryVisible(void *model, uint32_t start, uint32_t end, BOOL visible) {}
    static void SetGeometryVisible(void *model, uint32_t start, uint32_t end, BOOL visible) {}
  };
  };
 
  struct ItemDisplayInfoRec
  struct ItemDisplayInfoRec
  {
  {
uint32_t Flags;
    uint32_t Flags;
uint32_t GeosetGroup[4];
    uint32_t GeosetGroup[4];
  };
  };
 
  CharSectionsRec *ComponentGetSectionsRecord(uint32_t raceID, uint32_t genderID, uint32_t sectionID, uint32_t faceIndex, uint32_t skinIndex, uint32_t unk1)
  CharSectionsRec *ComponentGetSectionsRecord(uint32_t raceID, uint32_t genderID, uint32_t sectionID, uint32_t faceIndex, uint32_t skinIndex, uint32_t unk1)
  {
  {
return nullptr;
    return nullptr;
  }
  }
 
  uint32_t GetConditionalGeoset(uint32_t raceID, uint32_t geosetGroup)
  uint32_t GetConditionalGeoset(uint32_t raceID, uint32_t geosetGroup)
  {
  {
return 0;
    return 0;
  }
  }
 
  ItemDisplayInfoRec *GetItemDisplayInfoRec(uint32_t itemID)
  ItemDisplayInfoRec *GetItemDisplayInfoRec(uint32_t itemID)
  {
  {
return nullptr;
    return nullptr;
  }
  }
 
  void CCharacterComponent::GeosRenderPrep(CCharacterComponent *pCharComponent)
  void CCharacterComponent::GeosRenderPrep(CCharacterComponent *pCharComponent)
  {
  {
BOOL eyeGlowFlag;
    BOOL eyeGlowFlag = 0;
 
    if (pCharComponent->classID == 6) // DK
    {
        eyeGlowFlag = 1;
    }
    else
    {
        // section Face
        auto pFaceSection = ComponentGetSectionsRecord(pCharComponent->raceID, pCharComponent->genderID, 1, pCharComponent->faceIndex, pCharComponent->skinIndex, 0);
 
        if (pFaceSection)
            eyeGlowFlag = pFaceSection->Flags & 4;// flags & 0x4
        else
            eyeGlowFlag = 0;
    }
 
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 0, 3000, 0); // disable all
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 0, 0, 1); // enable skin
 
    uint32_t i = 0;
    do
    {
        if (eyeGlowFlag && i == 17)
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1703, 1703, 1);
        else
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pCharComponent->submeshIds[i], pCharComponent->submeshIds[i], 1);
        ++i;
    } while (i != 29);
 
    // Tail
    BOOL tailFlag = 0;
    // section Skin
    auto pSkinSection = ComponentGetSectionsRecord(pCharComponent->raceID, pCharComponent->genderID, 0, 0, pCharComponent->skinIndex, 0);
    if (pSkinSection)
        tailFlag = pSkinSection->Flags & 0x100; // flags & 0x100
 
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1900, 1999, 0);
 
    uint32_t tailGeoset = 1;
    if (!tailFlag)
        tailGeoset = GetConditionalGeoset(pCharComponent->raceID, 19);
    if (tailGeoset <= 0)
        tailGeoset = 1;
   
   
if (pCharComponent->classID == 6) // DK
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1900 + tailGeoset, 1900 + tailGeoset, 1);
{
eyeGlowFlag = 1;
    // Item ID's
}
    // 0 Head?
else
    // 1 Shoulder?
{
    auto shirtID = pCharComponent->itemids[2];
// section Face
    auto chestID = pCharComponent->itemids[3];
auto pFaceSection = ComponentGetSectionsRecord(pCharComponent->raceID, pCharComponent->genderID, 1, pCharComponent->faceIndex, pCharComponent->skinIndex, 0);
    auto beltID = pCharComponent->itemids[4];
    auto pantsID = pCharComponent->itemids[5];
    auto bootsID = pCharComponent->itemids[6];
    // 7 wrist?
    auto glovesID = pCharComponent->itemids[8];
    auto tabardID = pCharComponent->itemids[9];
    auto cloakID = pCharComponent->itemids[10];
    // 11 Weapon (Main Hand)?
    // 12 Weapon (Off Hand)?
    // 13 Shield?
    // 14 Ammo?
   
   
if (pFaceSection)
    // Gloves
eyeGlowFlag = pFaceSection->Flags & 4;// flags & 0x4
    if (glovesID)
else
    {
eyeGlowFlag = 0;
        auto pGloves = GetItemDisplayInfoRec(glovesID);
  }
        if (pGloves && pGloves->GeosetGroup[0])
        {
            auto glovesGeoset = 401 + pGloves->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 401, 499, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, glovesGeoset, glovesGeoset, 1);
        }
    }
    else
    {
        // Chest
        if (chestID)
        {
            auto pChest = GetItemDisplayInfoRec(chestID);
            if (pChest && pChest->GeosetGroup[0])
            {
                auto chesetGeoset = 801 + pChest->GeosetGroup[0];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chesetGeoset, chesetGeoset, 1);
            }
        }
    }
 
    // unknown shirt pre-check
    // possibly !textureArmUpper && !textureArmLower && !textureTorsoUpper && !textureTorsoLower && !textureLegUpper && !textureLegLower ?
    if (!pCharComponent->shirtRelated[0] && !pCharComponent->shirtRelated[1] && !pCharComponent->shirtRelated[2] && !pCharComponent->shirtRelated[3] && !pCharComponent->shirtRelated[4] && !pCharComponent->shirtRelated[5])
    {
        // Shirt
        if (shirtID)
        {
            auto pShirt = GetItemDisplayInfoRec(shirtID);
            if (pShirt && pShirt->GeosetGroup[0])
            {
                auto shirtGeoset = 801 + pShirt->GeosetGroup[0];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, shirtGeoset, shirtGeoset, 1);
            }
        }
    }
 
    // Tabard
    auto pTabard = GetItemDisplayInfoRec(tabardID);
    if (pTabard)
    {
        if (!(pTabard->Flags & 0x100000))
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2200, 2299, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2202, 2202, 1);
        }
    }
    else
    {
        // Chest
        if (chestID)
        {
            auto pChest = GetItemDisplayInfoRec(chestID);
            if (pChest && pChest->GeosetGroup[3])
            {
                auto chestGeoset = 2201 + pChest->GeosetGroup[3];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2200, 2299, 0);
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
            }
        }
    }
 
    // Belt
    BOOL hasBulkyBeltFlag = 0;
    auto pBelt = GetItemDisplayInfoRec(beltID);
    if (pBelt)
        hasBulkyBeltFlag = pBelt->Flags & 0x200;
 
    BOOL dressPants, dressChestpiece;
 
    // Chest
    if (chestID)
    {
        auto pChest = GetItemDisplayInfoRec(chestID);
        if (pChest && pChest->GeosetGroup[2])
        {
            if (pChest->GeosetGroup[2])
            {
                dressPants = 0;
                dressChestpiece = 1;
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 902, 999, 0);
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1100, 1199, 0);
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
                auto chestGeoset = 1301 + pChest->GeosetGroup[2];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
            }
        }
    }
    else if (pantsID)// Pants
    {
        auto pPants = GetItemDisplayInfoRec(pantsID);
        if (pPants && pPants->GeosetGroup[2] && !HIWORD(pCharComponent->flags))
        {
            dressPants = 1;
            dressChestpiece = 0;
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 902, 999, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1100, 1199, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
            auto pantsGeoset = 1301 + pPants->GeosetGroup[2];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
        }
    }
    else
    {
        dressPants = 0;
        dressChestpiece = 0;
        // Boots
        auto pBoots = GetItemDisplayInfoRec(bootsID);
        if (pBoots && pBoots->GeosetGroup[0])
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 901, 901, 1);
            auto bootsGeoset = 501 + pBoots->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, bootsGeoset, bootsGeoset, 1);
        }
        else
        {
            // Pants
            auto pPants = GetItemDisplayInfoRec(pantsID);
            uint32_t pantsGeoset;
            if (pPants && pPants->GeosetGroup[1] && !HIWORD(pCharComponent->flags))
            {
                pantsGeoset = 901 + pPants->GeosetGroup[1];
            }
            else
            {
                pantsGeoset = 901;
            }
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
        }
    }
 
    // Boots
    BOOL bootsFlag = 0;
    auto pBoots = GetItemDisplayInfoRec(bootsID);
    if (pBoots)
        bootsFlag = (pBoots->Flags & 0x100000) == 0;
 
    uint32_t bootsGeoset;
    if (pBoots && pBoots->GeosetGroup[1])
    {
        bootsGeoset = 2000 + pBoots->GeosetGroup[1];
    }
    else
    {
        if (bootsFlag)
        {
            bootsGeoset = 2002;
        }
        else
        {
            bootsGeoset = 2001;
        }
    }
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, bootsGeoset, bootsGeoset, 1);
 
    // Tabard
    BOOL showsTabard = 0;
    BOOL hasDress = dressChestpiece | dressPants;
    if (!hasDress && tabardID != 0 && pTabard && pTabard->GeosetGroup[0])
    {
        showsTabard = 0;
        uint32_t tabardGeoset;
        if (hasBulkyBeltFlag)
        {
            showsTabard = 1;
            tabardGeoset = 1203;
        }
        else
        {
            tabardGeoset = 1201 + pTabard->GeosetGroup[0];
            showsTabard = 1;
        }
        CM2Model::SetGeometryVisible(pCharComponent->modelPtr, tabardGeoset, tabardGeoset, 1);
    }
    else if (!(pCharComponent->flags & 0x10))
    {
        // nop
    }
    else
    {
        CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1201, 1201, 1);
 
        if (!hasDress)
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1202, 1202, 1);
            showsTabard = 1;
        }
    }
 
    if (!(dressChestpiece | showsTabard))
    {
        // Chest
        if (chestID)
        {
            auto pChest = GetItemDisplayInfoRec(chestID);
            if (pChest && pChest->GeosetGroup[1])
            {
                auto chestGeoset = 1001 + pChest->GeosetGroup[1];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
            }
        }
        else if (shirtID)
        {
            auto pShirt = GetItemDisplayInfoRec(shirtID);
            if (pShirt && pShirt->GeosetGroup[1])
            {
                auto shirtGeoset = 1001 + pShirt->GeosetGroup[1];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, shirtGeoset, shirtGeoset, 1);
            }
        }
    }
 
    if (!dressChestpiece && !HIWORD(pCharComponent->flags))
    {
        if (pantsID)
        {
            auto pPants = GetItemDisplayInfoRec(pantsID);
            if (pPants && pPants->GeosetGroup[0])
            {
                auto geosetGroup = pPants->GeosetGroup[0];
                auto pantsGeoset = 1101 + geosetGroup;
                if (geosetGroup > 2)
                {
                    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
                    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
                }
                else if (!showsTabard)
                    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
            }
        }
    }
 
    // Cloak
    if (cloakID)
    {
        auto pCloak = GetItemDisplayInfoRec(cloakID);
        if (pCloak && pCloak->GeosetGroup[0])
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1500, 1599, 0);
            auto cloakGeoset = 1501 + pCloak->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, cloakGeoset, cloakGeoset, 1);
        }
    }
 
    // Belt
    if (beltID)
    {
        auto pBelt = GetItemDisplayInfoRec(beltID);
        if (pBelt && pBelt->GeosetGroup[0])
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1800, 1899, 0);
            auto beltGeoset = 1801 + pBelt->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, beltGeoset, beltGeoset, 1);
        }
    }
 
    BOOL unkBool;
 
    if (pCharComponent->flags & 8)
    {
        unkBool = !pantsID && !dressChestpiece && !dressPants && !showsTabard && !tailFlag && !hasBulkyBeltFlag;
        //unkBool = ((pantsID | showsTabard | hasDress) == 0) & ((hasBulkyBeltFlag | tailFlag) ^ 1);
        if (unkBool)
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1401, 1401, 1);
        }
        else
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1400, 1499, 0);
        }
    }
    else
    {
        unkBool = 0;
    }
 
    // DH hands
    uint32_t v86 = GetConditionalGeoset(pCharComponent->raceID, 23);
    if (v86 <= 0)
        v86 = 1;
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2300 + v86, 2300 + v86, 1);
 
    //sub_1401BCDC0(pCharComponent, unkBool);
    //auto v132 = sub_1401C53B0(pCharComponent->raceID, pCharComponent->genderID);
    //auto v133 = sub_14023D380(pCharComponent->raceID, pCharComponent->genderID, pCharComponent->faceIndex, v132 != 0);
    //uint32_t v2 = 0;
    //if (v133)
    //  v2 = *v133;
    //sub_1412EFA90(pCharComponent->modelPtr, v2);
    //sub_1412EE6B0(pCharComponent->modelPtr);
    //LOBYTE(pCharComponent->flags) &= 0xFDu;
}
 
==TBC (2.4.3.8606)==
typedef struct item_display_info_line_s
{
uint32_t id;
char *model_name_left;
char *model_name_right;
char *model_texture_left;
char *model_texture_right;
char *icon1;
char *icon2;
  uint32_t geoset1;
uint32_t geoset2;
uint32_t geoset3;
/* ... */
} item_display_info_line_t;
   
   
  CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 0, 3000, 0); // disable all
typedef struct CCharacterComponent
  CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 0, 0, 1); // enable skin
{
/* 0x00A */ uint8_t initialized;
  /* 0x00C */ uint8_t unk_C;
/* 0x00D */ uint8_t unk_D;
/* 0x034 */ CM2Model *model;
/* 0x100 */ uint32_t submesh_ids[17];
/* 0x2A8 */ uint32_t unk_bitmask;
  /* 0x4AC */ uint32_t helm_id;
/* 0x4B0 */ uint32_t shoulder_id;
/* 0x4B4 */ uint32_t shirt_id;
/* 0x4B8 */ uint32_t chest_id;
/* 0x4BC */ uint32_t belt_id;
/* 0x4C0 */ uint32_t pants_id;
/* 0x4C4 */ uint32_t boots_id;
/* 0x4CC */ uint32_t gloves_id;
/* 0x4D0 */ uint32_t tabard_id;
/* 0x4D4 */ uint32_t cloak_id;
} CCharacterComponent;
   
   
uint32_t i = 0;
/* sub_717020 */
do
void CM2Model::SetGeometryVisible(uint32_t first, uint32_t last, uint32_t visible)
{
{
if (eyeGlowFlag && i == 17)
/* XXX */
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1703, 1703, 1);
}
else
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pCharComponent->submeshIds[i], pCharComponent->submeshIds[i], 1);
++i;
} while (i != 29);
   
   
// Tail
/* sub_47A180 */
BOOL tailFlag = 0;
void CCharacterComponent::HideGeometry(uint32_t first, uint32_t last)
// section Skin
{
  auto pSkinSection = ComponentGetSectionsRecord(pCharComponent->raceID, pCharComponent->genderID, 0, 0, pCharComponent->skinIndex, 0);
  this->model->SetGeometryVisible(first, last, 0);
if (pSkinSection)
}
tailFlag = pSkinSection->Flags & 0x100; // flags & 0x100
   
   
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1900, 1999, 0);
/* sub_47A1A0 */
void CCharacterComponent::ShowGeometry(uint32_t id)
{
this->model->SetGeometryVisible(id, id, 1);
}
   
   
uint32_t tailGeoset = 1;
/* sub_47BE80 */
  if (!tailFlag)
bool CCharacterComponent::GetObjectGeoset(uint32_t id, uint32_t geoset_id, item_display_info_line_t *line)
  tailGeoset = GetConditionalGeoset(pCharComponent->raceID, 19);
{
  if (tailGeoset <= 0)
  if (!id)
  tailGeoset = 1;
  return false;
if (!g_item_display_info->GetLine(id, line))
return false;
  if (!*((&line->geoset1)[geoset_id]))
  return false;
return true;
}
   
   
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1900 + tailGeoset, 1900 + tailGeoset, 1);
/* sub_47BEC0 */
void CCharacterComponent::GeosRenderPrep()
{
/* loaded flag ? */
if (!this->initialized)
return;
   
   
  // Item ID's
  item_display_info_line_t tmp_line;
auto shirtID = pCharComponent->itemids[0];
auto chestID = pCharComponent->itemids[1];
auto beltID = pCharComponent->itemids[2];
auto pantsID = pCharComponent->itemids[3];
auto bootsID = pCharComponent->itemids[4];
// 5?
auto glovesID = pCharComponent->itemids[6];
auto tabardID = pCharComponent->itemids[7];
auto cloakID = pCharComponent->itemids[8];
   
   
  // Gloves
  /* disable everything */
  if (glovesID)
  model->HideGeometry(0, 1900);
{
  /* display skin */
auto pGloves = GetItemDisplayInfoRec(glovesID);
model->ShowGeometry(0);
if (pGloves && pGloves->GeosetGroup[0])
{
auto glovesGeoset = 401 + pGloves->GeosetGroup[0];
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 401, 499, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, glovesGeoset, glovesGeoset, 1);
}
  }
else
{
// Chest
if (chestID)
{
auto pChest = GetItemDisplayInfoRec(chestID);
if (pChest && pChest->GeosetGroup[0])
{
auto chesetGeoset = 801 + pChest->GeosetGroup[0];
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chesetGeoset, chesetGeoset, 1);
}
}
}
   
   
  // unknown shirt pre-check
  uint32_t *submesh_ids = this->submesh_ids;
  if (!pCharComponent->shirtRelated[0] && !pCharComponent->shirtRelated[1] && !pCharComponent->shirtRelated[2] && !pCharComponent->shirtRelated[3] && !pCharComponent->shirtRelated[4] && !pCharComponent->shirtRelated[5])
uint32_t i = 18;
  do
  {
  {
  // Shirt
  /* loc_47BEF5 */
  if (shirtID)
  this->model->SetGeometryVisible(*submesh_ids, *submesh_ids, 1);
{
  submesh_ids++;
auto pShirt = GetItemDisplayInfoRec(shirtID);
  } while (--i);
if (pShirt && pShirt->GeosetGroup[0])
{
auto shirtGeoset = 801 + pShirt->GeosetGroup[0];
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, shirtGeoset, shirtGeoset, 1);
}
  }
  }
   
   
  // Tabard
  if (GetObjectGeoset(this->gloves_id, 0, &tmp_line))
auto pTabard = GetItemDisplayInfoRec(tabardID);
if (pTabard)
  {
  {
  if (!(pTabard->Flags & 0x100000))
  /* disable gloves */
  {
  HideGeometry(401, 499);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2200, 2299, 0);
/* enable glove */
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2202, 2202, 1);
ShowGeometry(401 + tmp_line.geoset1);
}
  }
  }
  else
  else if (GetObjectGeoset(this->chest_id, 0, &tmp_line))
  {
  {
  // Chest
  /* enable wrists */
  if (chestID)
  ShowGeometry(801 + tmp_line.geoset1);
{
auto pChest = GetItemDisplayInfoRec(chestID);
if (pChest && pChest->GeosetGroup[3])
{
auto chestGeoset = 2201 + pChest->GeosetGroup[3];
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2200, 2299, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
}
}
  }
  }
   
   
  // Belt
  /* loc_47BF6F */
  BOOL hasBulkyBeltFlag = 0;
  for (uint32_t i = 0; i < 7; ++i)
auto pBelt = GetItemDisplayInfoRec(beltID);
if (pBelt)
hasBulkyBeltFlag = pBelt->Flags & 0x200;
BOOL dressPants, dressChestpiece;
// Chest
if (chestID)
  {
  {
  auto pChest = GetItemDisplayInfoRec(chestID);
  if (!(this->unk_bitmask & (1 << i)))
if (pChest && pChest->GeosetGroup[2])
  goto found;
{
if (pChest->GeosetGroup[2])
{
dressPants = 0;
dressChestpiece = 1;
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 902, 999, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1100, 1199, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
auto chestGeoset = pChest->GeosetGroup[2] + 1301;
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
  }
}
  }
  }
  else if (pantsID)// Pants
  if (GetObjectGeoset(this->shirt_id, 0, &tmp_line))
  {
  {
  auto pPants = GetItemDisplayInfoRec(pantsID);
  /* enable wrists */
  if (pPants && pPants->GeosetGroup[2] && !HIWORD(pCharComponent->flags))
  ShowGeometry(801 + tmp_line.geoset1);
{
dressPants = 1;
dressChestpiece = 0;
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 902, 999, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1100, 1199, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
auto pantsGeoset = pPants->GeosetGroup[2] + 1301;
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
}
  }
  }
  else
  /* loc_47BFBC */
found:
uint32_t displayed_tabard = false;
uint32_t displayed_chestpiece = false;
uint32_t displayed_pants = 0;
if (GetObjectGeoset(this->chest_id, 2, &tmp_line))
  {
  {
  dressPants = 0;
  /* hide boots */
  dressChestpiece = 0;
  HideGeometry(501, 509);
  // Boots
  /* hide kneepads */
  auto pBoots = GetItemDisplayInfoRec(bootsID);
  HideGeometry(902, 999);
  if (pBoots && pBoots->GeosetGroup[0])
  /* hide pants */
  {
  HideGeometry(1100, 1199);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
/* hide trousers */
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 901, 901, 1);
HideGeometry(1300, 1399);
auto bootsGeoset = 501 + pBoots->GeosetGroup[0];
  /* show trousers */
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, bootsGeoset, bootsGeoset, 1);
ShowGeometry(1301 + tmp_line.geoset3);
  }
displayed_chestpiece = true;
else
{
// Pants
auto pPants = GetItemDisplayInfoRec(pantsID);
uint32_t pantsGeoset;
if (pPants && pPants->GeosetGroup[1] && !HIWORD(pCharComponent->flags))
{
pantsGeoset = pPants->GeosetGroup[1] + 901;
}
else
{
pantsGeoset = 901;
}
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
}
  }
  }
  else if (GetObjectGeoset(this->pants_id, 2, &tmp_line) && !this->unk_C)
// Boots
BOOL bootsFlag = 0;
auto pBoots = GetItemDisplayInfoRec(bootsID);
  if (pBoots)
bootsFlag = (pBoots->Flags & 0x100000) == 0;
uint32_t bootsGeoset;
if (pBoots && pBoots->GeosetGroup[1])
  {
  {
  bootsGeoset = pBoots->GeosetGroup[1] + 2000;
  /* hide boots */
HideGeometry(501, 599);
/* hide kneepads */
HideGeometry(902, 999);
/* hide pants */
HideGeometry(1100, 1199);
/* hide trousers */
HideGeometry(1300, 1399);
/* show trousers */
ShowGeometry(1301 + tmp_line.geoset3);
displayed_pants = 1;
  }
  }
  else
  else
  {
  {
  if (bootsFlag)
/* loc_47C0B5 */
{
  if (GetObjectGeoset(this->boots_id, 0, &tmp_line))
bootsGeoset = 2002;
}
else
  {
  {
  bootsGeoset = 2001;
  /* hide boots */
HideGeometry(501, 599);
/* show kneepads */
ShowGeometry(901);
/* show boots */
ShowGeometry(501 + tmp_line.geoset1);
  }
  }
}
else if (GetObjectGeoset(this->pants_id, 1, &tmp_line))
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, bootsGeoset, bootsGeoset, 1);
// Tabard
BOOL showsTabard = 0;
BOOL hasDress = dressChestpiece | dressPants;
if (!hasDress && tabardID != 0 && pTabard && pTabard->GeosetGroup[0])
{
showsTabard = 0;
uint32_t tabardGeoset;
if (hasBulkyBeltFlag)
  {
  {
  showsTabard = 1;
  /* show kneepads */
  tabardGeoset = 1203;
  ShowGeometry(901 + tmp_line.geoset2);
  }
  }
  else
  else
  {
  {
  tabardGeoset = pTabard->GeosetGroup[0] + 1201;
  /* show kneepads */
  showsTabard = 1;
  ShowGeometry(901);
  }
  }
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, tabardGeoset, tabardGeoset, 1);
}
else if (!(pCharComponent->flags & 0x10))
{
}
else
{
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1201, 1201, 1);
   
   
  if (!hasDress)
/* loc_47C11F */
  if (GetObjectGeoset(this->tabard_id, 0, &tmp_line))
  {
  {
  CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1202, 1202, 1);
  /* show tabard */
  showsTabard = 1;
ShowGeometry(1201 + tmp_line.geoset1);
  displayed_tabard = true;
  }
  }
  }
  }
   
   
  if (!(dressChestpiece | showsTabard))
  if (this->unk_D)
  {
  {
  // Chest
  /* show tabard */
  if (chestID)
  ShowGeometry(1201);
  {
  if (displayed_chestpiece)
auto pChest = GetItemDisplayInfoRec(chestID);
  goto end_robe;
if (pChest && pChest->GeosetGroup[1])
  if (!displayed_pants)
  {
  ShowGeometry(1202);
auto chestGeoset = 1001 + pChest->GeosetGroup[1];
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
}
}
  else if (shirtID)
{
auto pShirt = GetItemDisplayInfoRec(shirtID);
if (pShirt && pShirt->GeosetGroup[1])
  {
auto shirtGeoset = 1001 + pShirt->GeosetGroup[1];
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, shirtGeoset, shirtGeoset, 1);
}
}
  }
  }
  else if (displayed_chestpiece)
  if (!dressChestpiece && !HIWORD(pCharComponent->flags))
  {
  {
  if (pantsID)
  goto end_robe;
{
auto pPants = GetItemDisplayInfoRec(pantsID);
if (pPants && pPants->GeosetGroup[0])
{
auto geosetGroup = pPants->GeosetGroup[0];
auto pantsGeoset = 1101 + geosetGroup;
if (geosetGroup > 2)
{
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
}
else if (!showsTabard)
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
}
}
  }
  }
   
   
  // Cloak
  /* loc_47C182 */
  if (cloakID)
  if (!displayed_tabard)
  {
  {
  auto pCloak = GetItemDisplayInfoRec(cloakID);
  if (GetObjectGeoset(this->shirt_id, 1, &tmp_line))
if (pCloak && pCloak->GeosetGroup[0])
  {
  {
  CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1500, 1599, 0);
  /* show chest */
  auto cloakGeoset = 1501 + pCloak->GeosetGroup[0];
  ShowGeometry(1001 + tmp_line.geoset2);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, cloakGeoset, cloakGeoset, 1);
  }
  }
}
if (GetObjectGeoset(this->pants_id, 0, &tmp_line))
// Belt
if (beltID)
{
auto pBelt = GetItemDisplayInfoRec(beltID);
if (pBelt && pBelt->GeosetGroup[0])
  {
  {
  CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1800, 1899, 0);
  /* show pants */
  auto beltGeoset = 1801 + pBelt->GeosetGroup[0];
  ShowGeometry(1102 + tmp_line.geoset1);
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, beltGeoset, beltGeoset, 1);
  }
  }
  }
  }
   
   
  BOOL v76;
  /* loc_47C1DA */
end_robe:
   
   
  if (pCharComponent->flags & 8)
  if (GetObjectGeoset(this->cloak_id, 0, &tmp_line))
{
v76 = ((pantsID | showsTabard | hasDress) == 0) & ((hasBulkyBeltFlag | tailFlag) ^ 1);
if (v76)
{
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1401, 1401, 1);
}
else
{
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1400, 1400, 0);
}
}
else
  {
  {
  v76 = 0;
  /* hide cloak */
HideGeometry(1500, 1599);
/* show cloak */
ShowGeometry(1501 + tmp_line.geoset1);
  }
  }
   
   
  // DH hands
  this->sub_47A1C0();
uint32_t v86 = GetConditionalGeoset(pCharComponent->raceID, 23);
if (v86 <= 0)
v86 = 1;
CM2Model::SetGeometryVisible(pCharComponent->modelPtr, (v86 + 2300), (v86 + 2300), 1);
//sub_1000990E0(pCharComponent, v76 != 0);
//v87 = pCharComponent->raceID;
//v88 = *genderID;
//if (!byte_101E3C7D0)
//{
// byte_101E3C7D0 = 1;
// v89 = qword_101E3C7C8;
// if (qword_101E3C7C8 || (v89 = sub_1000E0760("hdPlayerModels"), (qword_101E3C7C8 = v89) != 0))
// v90 = *(v89 + 92) != 0;
// else
// v90 = 0;
// sub_100097210(v90, dword_101E3C15C);
//}
//v91 = 0;
//if (v87 > 36)
//{
// v92 = 0;
//}
//else
//{
// v92 = 0;
// if (v88 <= 1)
// v92 = dword_101E3C15C[4 * v87 + 2 * v88] == 1;
//}
//v93 = sub_100148CA0(pCharComponent->raceID, *genderID, pCharComponent->faceIndex, v92);
//if (v93)
// v91 = *v93;
//sub_101436B70(pCharComponent->modelPtr, v91);
//sub_1014387C0(pCharComponent->modelPtr);
//LOBYTE(pCharComponent->flags) &= 0xFDu;
  }
  }

Latest revision as of 14:15, 28 January 2023

WOD

// GeosetRenderPrep.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
 
int main()
{
    return 0;
}
 
struct CCharacterComponent
{
    uint32_t raceID;
    uint32_t classID;
    uint32_t skinIndex;
    uint32_t genderID;
    uint32_t faceIndex;
    void *modelPtr;
    uint32_t submeshIds[29];
    uint32_t itemids[10];
    uint32_t gap2[520];
    uint64_t shirtRelated[6];
    uint32_t flags;
 
    static void GeosRenderPrep(CCharacterComponent *pCharComponent);
};
 
struct CharSectionsRec
{
    uint32_t Flags;
};
 
struct CM2Model
{
    static void SetGeometryVisible(void *model, uint32_t start, uint32_t end, BOOL visible) {}
};
 
struct ItemDisplayInfoRec
{
    uint32_t Flags;
    uint32_t GeosetGroup[4];
};
 
CharSectionsRec *ComponentGetSectionsRecord(uint32_t raceID, uint32_t genderID, uint32_t sectionID, uint32_t faceIndex, uint32_t skinIndex, uint32_t unk1)
{
    return nullptr;
}
 
uint32_t GetConditionalGeoset(uint32_t raceID, uint32_t geosetGroup)
{
    return 0;
}
 
ItemDisplayInfoRec *GetItemDisplayInfoRec(uint32_t itemID)
{
    return nullptr;
}
 
void CCharacterComponent::GeosRenderPrep(CCharacterComponent *pCharComponent)
{
    BOOL eyeGlowFlag = 0;
 
    if (pCharComponent->classID == 6) // DK
    {
        eyeGlowFlag = 1;
    }
    else
    {
        // section Face
        auto pFaceSection = ComponentGetSectionsRecord(pCharComponent->raceID, pCharComponent->genderID, 1, pCharComponent->faceIndex, pCharComponent->skinIndex, 0);
 
        if (pFaceSection)
            eyeGlowFlag = pFaceSection->Flags & 4;// flags & 0x4
        else
            eyeGlowFlag = 0;
    }
 
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 0, 3000, 0); // disable all
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 0, 0, 1); // enable skin
 
    uint32_t i = 0;
    do
    {
        if (eyeGlowFlag && i == 17)
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1703, 1703, 1);
        else
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pCharComponent->submeshIds[i], pCharComponent->submeshIds[i], 1);
        ++i;
    } while (i != 29);
 
    // Tail
    BOOL tailFlag = 0;
    // section Skin
    auto pSkinSection = ComponentGetSectionsRecord(pCharComponent->raceID, pCharComponent->genderID, 0, 0, pCharComponent->skinIndex, 0);
    if (pSkinSection)
        tailFlag = pSkinSection->Flags & 0x100; // flags & 0x100
 
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1900, 1999, 0);
 
    uint32_t tailGeoset = 1;
    if (!tailFlag)
        tailGeoset = GetConditionalGeoset(pCharComponent->raceID, 19);
    if (tailGeoset <= 0)
        tailGeoset = 1;

    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1900 + tailGeoset, 1900 + tailGeoset, 1);

    // Item ID's
    // 0 Head?
    // 1 Shoulder?
    auto shirtID = pCharComponent->itemids[2];
    auto chestID = pCharComponent->itemids[3];
    auto beltID = pCharComponent->itemids[4];
    auto pantsID = pCharComponent->itemids[5];
    auto bootsID = pCharComponent->itemids[6];
    // 7 wrist?
    auto glovesID = pCharComponent->itemids[8];
    auto tabardID = pCharComponent->itemids[9];
    auto cloakID = pCharComponent->itemids[10];
    // 11 Weapon (Main Hand)?
    // 12 Weapon (Off Hand)?
    // 13 Shield?
    // 14 Ammo?

    // Gloves
    if (glovesID)
    {
        auto pGloves = GetItemDisplayInfoRec(glovesID);
        if (pGloves && pGloves->GeosetGroup[0])
        {
            auto glovesGeoset = 401 + pGloves->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 401, 499, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, glovesGeoset, glovesGeoset, 1);
        }
    }
    else
    {
        // Chest
        if (chestID)
        {
            auto pChest = GetItemDisplayInfoRec(chestID);
            if (pChest && pChest->GeosetGroup[0])
            {
                auto chesetGeoset = 801 + pChest->GeosetGroup[0];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chesetGeoset, chesetGeoset, 1);
            }
        }
    }
 
    // unknown shirt pre-check
    // possibly !textureArmUpper && !textureArmLower && !textureTorsoUpper && !textureTorsoLower && !textureLegUpper && !textureLegLower ?
    if (!pCharComponent->shirtRelated[0] && !pCharComponent->shirtRelated[1] && !pCharComponent->shirtRelated[2] && !pCharComponent->shirtRelated[3] && !pCharComponent->shirtRelated[4] && !pCharComponent->shirtRelated[5])
    {
        // Shirt
        if (shirtID)
        {
            auto pShirt = GetItemDisplayInfoRec(shirtID);
            if (pShirt && pShirt->GeosetGroup[0])
            {
                auto shirtGeoset = 801 + pShirt->GeosetGroup[0];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, shirtGeoset, shirtGeoset, 1);
            }
        }
    }
 
    // Tabard
    auto pTabard = GetItemDisplayInfoRec(tabardID);
    if (pTabard)
    {
        if (!(pTabard->Flags & 0x100000))
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2200, 2299, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2202, 2202, 1);
        }
    }
    else
    {
        // Chest
        if (chestID)
        {
            auto pChest = GetItemDisplayInfoRec(chestID);
            if (pChest && pChest->GeosetGroup[3])
            {
                auto chestGeoset = 2201 + pChest->GeosetGroup[3];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2200, 2299, 0);
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
            }
        }
    }
 
    // Belt
    BOOL hasBulkyBeltFlag = 0;
    auto pBelt = GetItemDisplayInfoRec(beltID);
    if (pBelt)
        hasBulkyBeltFlag = pBelt->Flags & 0x200;
 
    BOOL dressPants, dressChestpiece;
 
    // Chest
    if (chestID)
    {
        auto pChest = GetItemDisplayInfoRec(chestID);
        if (pChest && pChest->GeosetGroup[2])
        {
            if (pChest->GeosetGroup[2])
            {
                dressPants = 0;
                dressChestpiece = 1;
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 902, 999, 0);
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1100, 1199, 0);
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
                auto chestGeoset = 1301 + pChest->GeosetGroup[2];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
            }
        }
    }
    else if (pantsID)// Pants
    {
        auto pPants = GetItemDisplayInfoRec(pantsID);
        if (pPants && pPants->GeosetGroup[2] && !HIWORD(pCharComponent->flags))
        {
            dressPants = 1;
            dressChestpiece = 0;
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 902, 999, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1100, 1199, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
            auto pantsGeoset = 1301 + pPants->GeosetGroup[2];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
        }
    }
    else
    {
        dressPants = 0;
        dressChestpiece = 0;
        // Boots
        auto pBoots = GetItemDisplayInfoRec(bootsID);
        if (pBoots && pBoots->GeosetGroup[0])
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 901, 901, 1);
            auto bootsGeoset = 501 + pBoots->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, bootsGeoset, bootsGeoset, 1);
        }
        else
        {
            // Pants
            auto pPants = GetItemDisplayInfoRec(pantsID);
            uint32_t pantsGeoset;
            if (pPants && pPants->GeosetGroup[1] && !HIWORD(pCharComponent->flags))
            {
                pantsGeoset = 901 + pPants->GeosetGroup[1];
            }
            else
            {
                pantsGeoset = 901;
            }
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
        }
    }
 
    // Boots
    BOOL bootsFlag = 0;
    auto pBoots = GetItemDisplayInfoRec(bootsID);
    if (pBoots)
        bootsFlag = (pBoots->Flags & 0x100000) == 0;
 
    uint32_t bootsGeoset;
    if (pBoots && pBoots->GeosetGroup[1])
    {
        bootsGeoset = 2000 + pBoots->GeosetGroup[1];
    }
    else
    {
        if (bootsFlag)
        {
            bootsGeoset = 2002;
        }
        else
        {
            bootsGeoset = 2001;
        }
    }
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, bootsGeoset, bootsGeoset, 1);
 
    // Tabard
    BOOL showsTabard = 0;
    BOOL hasDress = dressChestpiece | dressPants;
    if (!hasDress && tabardID != 0 && pTabard && pTabard->GeosetGroup[0])
    {
        showsTabard = 0;
        uint32_t tabardGeoset;
        if (hasBulkyBeltFlag)
        {
            showsTabard = 1;
            tabardGeoset = 1203;
        }
        else
        {
            tabardGeoset = 1201 + pTabard->GeosetGroup[0];
            showsTabard = 1;
        }
        CM2Model::SetGeometryVisible(pCharComponent->modelPtr, tabardGeoset, tabardGeoset, 1);
    }
    else if (!(pCharComponent->flags & 0x10))
    {
        // nop
    }
    else
    {
        CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1201, 1201, 1);
 
        if (!hasDress)
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1202, 1202, 1);
            showsTabard = 1;
        }
    }
 
    if (!(dressChestpiece | showsTabard))
    {
        // Chest
        if (chestID)
        {
            auto pChest = GetItemDisplayInfoRec(chestID);
            if (pChest && pChest->GeosetGroup[1])
            {
                auto chestGeoset = 1001 + pChest->GeosetGroup[1];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
            }
        }
        else if (shirtID)
        {
            auto pShirt = GetItemDisplayInfoRec(shirtID);
            if (pShirt && pShirt->GeosetGroup[1])
            {
                auto shirtGeoset = 1001 + pShirt->GeosetGroup[1];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, shirtGeoset, shirtGeoset, 1);
            }
        }
    }
 
    if (!dressChestpiece && !HIWORD(pCharComponent->flags))
    {
        if (pantsID)
        {
            auto pPants = GetItemDisplayInfoRec(pantsID);
            if (pPants && pPants->GeosetGroup[0])
            {
                auto geosetGroup = pPants->GeosetGroup[0];
                auto pantsGeoset = 1101 + geosetGroup;
                if (geosetGroup > 2)
                {
                    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1300, 1399, 0);
                    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
                }
                else if (!showsTabard)
                    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, pantsGeoset, pantsGeoset, 1);
            }
        }
    }
 
    // Cloak
    if (cloakID)
    {
        auto pCloak = GetItemDisplayInfoRec(cloakID);
        if (pCloak && pCloak->GeosetGroup[0])
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1500, 1599, 0);
            auto cloakGeoset = 1501 + pCloak->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, cloakGeoset, cloakGeoset, 1);
        }
    }
 
    // Belt
    if (beltID)
    {
        auto pBelt = GetItemDisplayInfoRec(beltID);
        if (pBelt && pBelt->GeosetGroup[0])
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1800, 1899, 0);
            auto beltGeoset = 1801 + pBelt->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, beltGeoset, beltGeoset, 1);
        }
    }
 
    BOOL unkBool;
 
    if (pCharComponent->flags & 8)
    {
        unkBool = !pantsID && !dressChestpiece && !dressPants && !showsTabard && !tailFlag && !hasBulkyBeltFlag;
        //unkBool = ((pantsID | showsTabard | hasDress) == 0) & ((hasBulkyBeltFlag | tailFlag) ^ 1);
        if (unkBool)
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1401, 1401, 1);
        }
        else
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1400, 1499, 0);
        }
    }
    else
    {
        unkBool = 0;
    }
 
    // DH hands
    uint32_t v86 = GetConditionalGeoset(pCharComponent->raceID, 23);
    if (v86 <= 0)
        v86 = 1;
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2300 + v86, 2300 + v86, 1);
 
    //sub_1401BCDC0(pCharComponent, unkBool);
    //auto v132 = sub_1401C53B0(pCharComponent->raceID, pCharComponent->genderID);
    //auto v133 = sub_14023D380(pCharComponent->raceID, pCharComponent->genderID, pCharComponent->faceIndex, v132 != 0);
    //uint32_t v2 = 0;
    //if (v133)
    //  v2 = *v133;
    //sub_1412EFA90(pCharComponent->modelPtr, v2);
    //sub_1412EE6B0(pCharComponent->modelPtr);
    //LOBYTE(pCharComponent->flags) &= 0xFDu;
}

TBC (2.4.3.8606)

typedef struct item_display_info_line_s
{
	uint32_t id;
	char *model_name_left;
	char *model_name_right;
	char *model_texture_left;
	char *model_texture_right;
	char *icon1;
	char *icon2;
	uint32_t geoset1;
	uint32_t geoset2;
	uint32_t geoset3;
	/* ... */
} item_display_info_line_t;

typedef struct CCharacterComponent
{
	/* 0x00A */ uint8_t initialized;
	/* 0x00C */ uint8_t unk_C;
	/* 0x00D */ uint8_t unk_D;
	/* 0x034 */ CM2Model *model;
	/* 0x100 */ uint32_t submesh_ids[17];
	/* 0x2A8 */ uint32_t unk_bitmask;
	/* 0x4AC */ uint32_t helm_id;
	/* 0x4B0 */ uint32_t shoulder_id;
	/* 0x4B4 */ uint32_t shirt_id;
	/* 0x4B8 */ uint32_t chest_id;
	/* 0x4BC */ uint32_t belt_id;
	/* 0x4C0 */ uint32_t pants_id;
	/* 0x4C4 */ uint32_t boots_id;
	/* 0x4CC */ uint32_t gloves_id;
	/* 0x4D0 */ uint32_t tabard_id;
	/* 0x4D4 */ uint32_t cloak_id;
} CCharacterComponent;

/* sub_717020 */
void CM2Model::SetGeometryVisible(uint32_t first, uint32_t last, uint32_t visible)
{
	/* XXX */
}

/* sub_47A180 */
void CCharacterComponent::HideGeometry(uint32_t first, uint32_t last)
{
	this->model->SetGeometryVisible(first, last, 0);
}

/* sub_47A1A0 */
void CCharacterComponent::ShowGeometry(uint32_t id)
{
	this->model->SetGeometryVisible(id, id, 1);
}

/* sub_47BE80 */
bool CCharacterComponent::GetObjectGeoset(uint32_t id, uint32_t geoset_id, item_display_info_line_t *line)
{
	if (!id)
		return false;
	if (!g_item_display_info->GetLine(id, line))
		return false;
	if (!*((&line->geoset1)[geoset_id]))
		return false;
	return true;
}

/* sub_47BEC0 */
void CCharacterComponent::GeosRenderPrep()
{
	/* loaded flag ? */
	if (!this->initialized)
		return;

	item_display_info_line_t tmp_line;

	/* disable everything */
	model->HideGeometry(0, 1900);
	/* display skin */
	model->ShowGeometry(0);

	uint32_t *submesh_ids = this->submesh_ids;
	uint32_t i = 18;
	do
	{
		/* loc_47BEF5 */
		this->model->SetGeometryVisible(*submesh_ids, *submesh_ids, 1);
		submesh_ids++;
	} while (--i);

	if (GetObjectGeoset(this->gloves_id, 0, &tmp_line))
	{
		/* disable gloves */
		HideGeometry(401, 499);
		/* enable glove */
		ShowGeometry(401 + tmp_line.geoset1);
	}
	else if (GetObjectGeoset(this->chest_id, 0, &tmp_line))
	{
		/* enable wrists */
		ShowGeometry(801 + tmp_line.geoset1);
	}

	/* loc_47BF6F */
	for (uint32_t i = 0; i < 7; ++i)
	{
		if (!(this->unk_bitmask & (1 << i)))
			goto found;
	}

	if (GetObjectGeoset(this->shirt_id, 0, &tmp_line))
	{
		/* enable wrists */
		ShowGeometry(801 + tmp_line.geoset1);
	}

	/* loc_47BFBC */
found:
	uint32_t displayed_tabard = false;
	uint32_t displayed_chestpiece = false;
	uint32_t displayed_pants = 0;
	if (GetObjectGeoset(this->chest_id, 2, &tmp_line))
	{
		/* hide boots */
		HideGeometry(501, 509);
		/* hide kneepads */
		HideGeometry(902, 999);
		/* hide pants */
		HideGeometry(1100, 1199);
		/* hide trousers */
		HideGeometry(1300, 1399);
		/* show trousers */
		ShowGeometry(1301 + tmp_line.geoset3);
		displayed_chestpiece = true;
	}
	else if (GetObjectGeoset(this->pants_id, 2, &tmp_line) && !this->unk_C)
	{
		/* hide boots */
		HideGeometry(501, 599);
		/* hide kneepads */
		HideGeometry(902, 999);
		/* hide pants */
		HideGeometry(1100, 1199);
		/* hide trousers */
		HideGeometry(1300, 1399);
		/* show trousers */
		ShowGeometry(1301 + tmp_line.geoset3);
		displayed_pants = 1;
	}
	else
	{
		/* loc_47C0B5 */
		if (GetObjectGeoset(this->boots_id, 0, &tmp_line))
		{
			/* hide boots */
			HideGeometry(501, 599);
			/* show kneepads */
			ShowGeometry(901);
			/* show boots */
			ShowGeometry(501 + tmp_line.geoset1);
		}
		else if (GetObjectGeoset(this->pants_id, 1, &tmp_line))
		{
			/* show kneepads */
			ShowGeometry(901 + tmp_line.geoset2);
		}
		else
		{
			/* show kneepads */
			ShowGeometry(901);
		}

		/* loc_47C11F */
		if (GetObjectGeoset(this->tabard_id, 0, &tmp_line))
		{
			/* show tabard */
			ShowGeometry(1201 + tmp_line.geoset1);
			displayed_tabard = true;
		}
	}

	if (this->unk_D)
	{
		/* show tabard */
		ShowGeometry(1201);
		if (displayed_chestpiece)
			goto end_robe;
		if (!displayed_pants)
			ShowGeometry(1202);
	}
	else if (displayed_chestpiece)
	{
		goto end_robe;
	}

	/* loc_47C182 */
	if (!displayed_tabard)
	{
		if (GetObjectGeoset(this->shirt_id, 1, &tmp_line))
		{
			/* show chest */
			ShowGeometry(1001 + tmp_line.geoset2);
		}
		if (GetObjectGeoset(this->pants_id, 0, &tmp_line))
		{
			/* show pants */
			ShowGeometry(1102 + tmp_line.geoset1);
		}
	}

	/* loc_47C1DA */
end_robe:

	if (GetObjectGeoset(this->cloak_id, 0, &tmp_line))
	{
		/* hide cloak */
		HideGeometry(1500, 1599);
		/* show cloak */
		ShowGeometry(1501 + tmp_line.geoset1);
	}

	this->sub_47A1C0();
}