DB/ItemDisplayInfo/GeosRenderPrep: Difference between revisions

From wowdev
Jump to navigation Jump to search
(Created page with " void CCharacterComponent::GeosRenderPrep(CCharacterComponent *characterComponent) { // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND] // "characte...")
 
No edit summary
 
(6 intermediate revisions by 3 users not shown)
Line 1: Line 1:
  void CCharacterComponent::GeosRenderPrep(CCharacterComponent *characterComponent)
==WOD==
  // GeosetRenderPrep.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
 
int main()
  {
  {
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
    return 0;
 
}
  // "characterComponent->componentData.model2" simplified to "ourModel" for (vastly) shorter code
 
  // SHIRT = item_ids[2]
struct CCharacterComponent
  // CHEST = item_ids[3]
{
  // BELT = item_ids[4]
    uint32_t raceID;
  // PANTS = item_ids[5]
    uint32_t classID;
  // BOOTS = item_ids[6]
    uint32_t skinIndex;
  // GLOVES = item_ids[8]
    uint32_t genderID;
  // TABARD = item_ids[9]
    uint32_t faceIndex;
  // CLOAK = field_6C0
    void *modelPtr;
   
    uint32_t submeshIds[29];
  // Lookup something (if class is not DK)
    uint32_t itemids[10];
  booleanOfQuestionableUsefulness = false;
    uint32_t gap2[520];
  if ( characterComponent->componentData.class_ != 6 )
    uint64_t shirtRelated[6];
  {
    uint32_t flags;
     booleanOfQuestionableUsefulness = true;
 
     // ComponentGetSectionsRecord matches against CharSections.db2.
    static void GeosRenderPrep(CCharacterComponent *pCharComponent);
    // parameters: UNKNOWN, raceID, genderID, baseSection, variationIndex, colorIndex
};
     // since baseSection is 1, it is referring to the face, so variationIndex is really the 'type of face', and colorIndex is the skin color (so the face has matching skin color)'
 
     // what -exactly- v3 is is a bit of a mystery to me. Could be row ID from the DBC
struct CharSectionsRec
    v3 = ComponentGetSectionsRecord(
{
            (__int64)&s_chrVarArray,
    uint32_t Flags;
            characterComponent->componentData.race,
};
            characterComponent->componentData.gender,
 
            1,
struct CM2Model
            characterComponent->componentData.face,
  {
            characterComponent->componentData.skinColor,
    static void SetGeometryVisible(void *model, uint32_t start, uint32_t end, BOOL visible) {}
            0);
};
     if ( v3 )
 
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
     {
     {
      booleanOfQuestionableUsefulness = (*(_BYTE *)(v3 + 28) & 4) == 0;
        // 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
  // Disable all geosets from 0 to 2200
    CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 0, 0, 1); // enable skin
  CM2Model::SetGeometryVisible(ourModel, 0, 2200, 0);
 
 
     uint32_t i = 0;
  // Enable geoset 0, the skin
  CM2Model::SetGeometryVisible(ourModel, 0, 0, 1);
 
  // Enable default geosets for that model (i.e. fill in all the holes that there would be on a model with no armor on)
  if ( booleanOfQuestionableUsefulness )
  {
     v4 = 0; // Counter variable
     do
     do
     {
     {
      CM2Model::SetGeometryVisible(ourModel, characterComponent->componentData.submeshIds[v4], characterComponent->componentData.submeshIds[v4], 1);
        if (eyeGlowFlag && i == 17)
      ++v4;
            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);
        }
     }
     }
     while ( (_DWORD)v4 != 21 );
     else
  }
  // If Class is DK (or Race has eye glow?), enable special eyes
  else
  {
    v5 = 0; // Counter variable
    do
     {
     {
      if ( (_DWORD)v5 == 17 )
        // Chest
      {
        if (chestID)
        v6 = 1703;
        {
        v7 = 1703;
            auto pChest = GetItemDisplayInfoRec(chestID);
      }
            if (pChest && pChest->GeosetGroup[0])
      else
            {
      {
                auto chesetGeoset = 801 + pChest->GeosetGroup[0];
        v6 = characterComponent->componentData.submeshIds[v5];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chesetGeoset, chesetGeoset, 1);
        v7 = characterComponent->componentData.submeshIds[v5];
            }
      }
        }
      CM2Model::SetGeometryVisible(ourModel, v6, v7, 1);
      ++v5;
     }
     }
     while ( (_DWORD)v5 != 21 );
 
  }
     // unknown shirt pre-check
 
     // possibly !textureArmUpper && !textureArmLower && !textureTorsoUpper && !textureTorsoLower && !textureLegUpper && !textureLegLower ?
  // TAIL is checked here? 'GetConditionalGeoset' probably checks racial conditions or something.
    if (!pCharComponent->shirtRelated[0] && !pCharComponent->shirtRelated[1] && !pCharComponent->shirtRelated[2] && !pCharComponent->shirtRelated[3] && !pCharComponent->shirtRelated[4] && !pCharComponent->shirtRelated[5])
  CM2Model::SetGeometryVisible(ourModel, 1900, 1999, 0);
  v8 = GetConditionalGeoset(&characterComponent->componentData, (COMP_GEOSET)19);
  v9 = v8 + 1900;
  if ( (signed int)v8 <= 0 )
  {
     v9 = 1901;
  }
  CM2Model::SetGeometryVisible(ourModel, v9, v9, 1);
 
  // GLOVES (8)
  v10 = characterComponent->item_ids[GLOVES];
  if ( v10 && g_itemDisplayInfoDB->GetRecord(v10) && g_itemDisplayInfoDB->GetRecord(v10)->m_geosetGroup[0] )
  {
    CM2Model::SetGeometryVisible(ourModel, 400, 499, 0);
    CM2Model::SetGeometryVisible(
      ourModel,
      g_itemDisplayInfoDB->GetRecord(v10)->m_geosetGroup[0] + 401,
      g_itemDisplayInfoDB->GetRecord(v10)->m_geosetGroup[0] + 401,
      1);
  }
  else
  {
    // if no glove geoset, CHEST (3) - m_geosetGroup[0] modifies 801
    v14 = characterComponent->item_ids[CHEST];
    if ( v14 )
     {
     {
      v15 = g_itemDisplayInfoDB->GetRecord(v14);
         // Shirt
      if ( v15 )
         if (shirtID)
      {
         v16 = v15->m_geosetGroup[0];
         if ( v16 )
         {
         {
          CM2Model::SetGeometryVisible(ourModel, v16 + 801, v16 + 801, 1);
            auto pShirt = GetItemDisplayInfoRec(shirtID);
            if (pShirt && pShirt->GeosetGroup[0])
            {
                auto shirtGeoset = 801 + pShirt->GeosetGroup[0];
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, shirtGeoset, shirtGeoset, 1);
            }
         }
         }
      }
     }
     }
  }
 
 
    // Tabard
  bool valid = true;
    auto pTabard = GetItemDisplayInfoRec(tabardID);
  for ( int v13 = 65; v13 <= 70; ++v13 )
     if (pTabard)
  {
     if ( *(&characterComponent->field_0 + v13) != 0 )
     {
     {
      valid = false;
        if (!(pTabard->Flags & 0x100000))
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2200, 2299, 0);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2202, 2202, 1);
        }
     }
     }
  }
     else
  if (valid)
     // (CONDITIONALLY) SHIRT (2) - m_geosetGroup[0] modifies 801
    v18 = characterComponent->item_ids[SHIRT];
    if ( v18 )
     {
     {
      v19 = g_itemDisplayInfoDB->GetRecord(v18);
         // Chest
      if ( v19 )
         if (chestID)
      {
         v20 = v19->m_geosetGroup[0];
         if ( v20 )
         {
         {
          CM2Model::SetGeometryVisible(ourModel, v20 + 801, v20 + 801, 1);
            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
  // BELT (4) - m_geosetGroup[0] modifies a truth value used later to test whether to apply the tabard geoset (only if m_flags & 0x200)
    BOOL hasBulkyBeltFlag = 0;
  hasBulkyBeltFlag = 0;
    auto pBelt = GetItemDisplayInfoRec(beltID);
  v21 = characterComponent->item_ids[BELT];
    if (pBelt)
  if ( v21 )
        hasBulkyBeltFlag = pBelt->Flags & 0x200;
  {
 
    v23 = g_itemDisplayInfoDB->GetRecord(v21);
    BOOL dressPants, dressChestpiece;
     if ( v23 )
 
    // Chest
     if (chestID)
     {
     {
      if ( v23->m_geosetGroup[0] )
        auto pChest = GetItemDisplayInfoRec(chestID);
      {
        if (pChest && pChest->GeosetGroup[2])
        hasBulkyBeltFlag = ((unsigned int)v23->m_flags >> 9) & 1;
        {
      }
            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
 
  v24 = characterComponent->item_ids[CHEST];
  v29 = characterComponent->item_ids[PANTS];
  // CHEST (3) - m_geosetGroup[2] modifies 1301
  if ( v24 && g_itemDisplayInfoDB->GetRecord(v24) && g_itemDisplayInfoDB->GetRecord(v24)->m_geosetGroup[2] )
  {
    dressPants = false;
    dressChestpiece = true;
     CM2Model::SetGeometryVisible(ourModel, g_itemDisplayInfoDB->GetRecord(v24)->m_geosetGroup[2] + 1301, g_itemDisplayInfoDB->GetRecord(v24)->m_geosetGroup[2] + 1301, 1);
  }
  // (CONDITIONALLY) PANTS (5) - m_geosetGroup[2] modifies 1301 (only if CHEST's m_geosetGroup[2] is 0)
  // FIELD 20 CHECK (&0x08 == 0)
  else if ( v29 && g_itemDisplayInfoDB->GetRecord(v29) && g_itemDisplayInfoDB->GetRecord(v29)->m_geosetGroup[2]  && (characterComponent->field_20 & 8 == 0) )
  {
    dressPants = true;
    dressChestpiece = false;
    CM2Model::SetGeometryVisible(ourModel, g_itemDisplayInfoDB->GetRecord(v29)->m_geosetGroup[2] + 1301, g_itemDisplayInfoDB->GetRecord(v29)->m_geosetGroup[2] + 1301, 1);
  }
  else
  {
    dressPants = false;
    dressChestpiece = false;
    // (CONDITIONALLY) BOOTS (6) - m_geosetGroup[0] modifies 501 (only if CHEST's m_geosetGroup[2] is 0 and PANTS' m_geosetGroup[2] is 0)
    v31 = characterComponent->item_ids[BOOTS];
    if ( v31 && g_itemDisplayInfoDB->GetRecord(v31) && g_itemDisplayInfoDB->GetRecord(v31)->m_geosetGroup[0] )
     {
     {
      CM2Model::SetGeometryVisible(ourModel, g_itemDisplayInfoDB->GetRecord(v31)->m_geosetGroup[0] + 501, g_itemDisplayInfoDB->GetRecord(v31)->m_geosetGroup[0] + 501, 1);
        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
     else
     {
     {
      // (CONDITIONALLY) PANTS (5) - m_geosetGroup[1] modifies 901 (only if CHEST's m_geosetGroup[2] is 0 and PANTS' m_geosetGroup[2] is 0 and BOOTS' m_geosetGroup[0] is 0 and field_20 & 0x08 != 0)
        dressPants = 0;
      v34 = characterComponent->item_ids[PANTS];
        dressChestpiece = 0;
      // FIELD 20 CHECK (&0x08 == 0)
        // Boots
      if ( v34 && g_itemDisplayInfoDB->GetRecord(v34) && g_itemDisplayInfoDB->GetRecord(v34)->m_geosetGroup[1] && (characterComponent->field_20 & 8 == 0) )
        auto pBoots = GetItemDisplayInfoRec(bootsID);
      {
        if (pBoots && pBoots->GeosetGroup[0])
        v38 = v36 + 901;
        {
      }
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 501, 599, 0);
      // else, else, else: 901 is set (901 is default set then)
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 901, 901, 1);
      else
            auto bootsGeoset = 501 + pBoots->GeosetGroup[0];
      {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, bootsGeoset, bootsGeoset, 1);
        v38 = 901;
        }
      }
        else
      CM2Model::SetGeometryVisible(ourModel, v38, v38, 1);
        {
            // 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
  // BOOTS (6) - m_geosetGroup[1] modifies 2000 (yes, 2000) and has some fun conditionals
    BOOL bootsFlag = 0;
  v40 = characterComponent->item_ids[BOOTS];
    auto pBoots = GetItemDisplayInfoRec(bootsID);
  // If you are wearing BOOTS
    if (pBoots)
  if ( v40 )
        bootsFlag = (pBoots->Flags & 0x100000) == 0;
  {
 
    v41 = g_itemDisplayInfoDB->GetRecord(v40);
     uint32_t bootsGeoset;
     // If your BOOTS' m_geosetGroup[1] is 0
     if (pBoots && pBoots->GeosetGroup[1])
     if ( !v41 || !v41->m_geosetGroup[1] )
     {
     {
      v44 = 2002;
        bootsGeoset = 2000 + pBoots->GeosetGroup[1];
      v45 = 2002;
     }
     }
    // If your BOOTS' m_geosetGroup[1] is non-zero
     else
     else
     {
     {
      v44 = v41->m_geosetGroup[1] + 2000;
        if (bootsFlag)
      v45 = v41->m_geosetGroup[1] + 2000;
        {
            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
  // If you are not wearing BOOTS
  else
  {
    v44 = 2001;
    v45 = 2001;
  }
  CM2Model::SetGeometryVisible(ourModel, v44, v45, 1);
 
  // (CONDITIONALLY) TABARD (9) - m_geosetGroup[0] modifies 1201 (if not wearing a dress and m_flags & 0x200 is 0 for your BELT)
  showsTabard = false;
  hasDress = (dressChestpiece | dressPants);
  if ( !hasDress && !hasBulkyBeltFlag )
  {
    v49 = characterComponent->item_ids[TABARD];
    if ( v49 )
     {
     {
      v50 = g_itemDisplayInfoDB->GetRecord(v49);
        CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1201, 1201, 1);
      if ( v50 )
 
      {
         if (!hasDress)
        v51 = v50->m_geosetGroup[0];
         if ( v51 )
         {
         {
          showsTabard = true;
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1202, 1202, 1);
          CM2Model::SetGeometryVisible(ourModel, v51 + 1201, v51 + 1201, 1);
            showsTabard = 1;
         }
         }
      }
     }
     }
  }
 
  // FIELD 20 CHECK (&0x20 == 0) - result is tabard geoset hidden
     if (!(dressChestpiece | showsTabard))
  if ( characterComponent->field_20 & 0x20 == 0 )
  {
     CM2Model::SetGeometryVisible(ourModel, 1201, 1201, 1)
  }
  // FIELD 20 CHECK (&0x20 == 0) - result is tabard geoset shown if hasDress is false
  if ( (characterComponent->field_20 & 0x20 == 0) && !hasDress )
  {
    CM2Model::SetGeometryVisible(ourModel, 1202, 1202, 1);
    showsTabard = true;
  }
  else
  {
    if ( !showsTabard && !dressChestpiece )
     {
     {
      // (CONDITIONALLY) CHEST (3) - m_geosetGroup[1] modifies 1001
        // Chest
      if (characterComponent->item_ids[CHEST] && g_itemDisplayInfoDB->GetRecord(characterComponent->item_ids[CHEST]) && g_itemDisplayInfoDB->GetRecord(characterComponent->item_ids[CHEST])->m_geosetGroup[1])
        if (chestID)
      {
        {
        CM2Model::SetGeometryVisible(ourModel, g_itemDisplayInfoDB->GetRecord(characterComponent->item_ids[CHEST])->m_geosetGroup[1] + 1001, g_itemDisplayInfoDB->GetRecord(characterComponent->item_ids[CHEST])->m_geosetGroup[1] + 1001, 1);
            auto pChest = GetItemDisplayInfoRec(chestID);
         showsTabard = false;
            if (pChest && pChest->GeosetGroup[1])
      }
            {
      // (CONDITIONALLY) SHIRT (2) - m_geosetGroup[1] modifies 1001
                auto chestGeoset = 1001 + pChest->GeosetGroup[1];
      else if (characterComponent->item_ids[SHIRT] && g_itemDisplayInfoDB->GetRecord(characterComponent->item_ids[SHIRT]) && g_itemDisplayInfoDB->GetRecord(characterComponent->item_ids[SHIRT])->m_geosetGroup[1])
                CM2Model::SetGeometryVisible(pCharComponent->modelPtr, chestGeoset, chestGeoset, 1);
      {
            }
        CM2Model::SetGeometryVisible(ourModel, g_itemDisplayInfoDB->GetRecord(characterComponent->item_ids[SHIRT])->m_geosetGroup[1] + 1001, g_itemDisplayInfoDB->GetRecord(characterComponent->item_ids[SHIRT])->m_geosetGroup[1] + 1001, 1);
         }
         showsTabard = false;
        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))
  // FIELD 20 CHECK (&0x08 == 0)
  if ( !dressChestpiece && (characterComponent->field_20 & 8 == 0) )
  {
    // (CONDITIONALLY) PANTS (5) - m_geosetGroup[0] modifies 1101 (if m_geosetGroup[0] > 2, it wipes all geosets from 1300 to 1399 and then sets 1101. if it is less than or equal to 2 and if a tabard is shown, it sets 1101.)
    v58 = characterComponent->item_ids[PANTS];
    if ( v58 )
     {
     {
      v59 = g_itemDisplayInfoDB->GetRecord(v58);
         if (pantsID)
      if ( v59 )
      {
        v60 = v59->m_geosetGroup[0];
         if ( v60 )
         {
         {
          if ( v60 > 2 )
            auto pPants = GetItemDisplayInfoRec(pantsID);
          {
            if (pPants && pPants->GeosetGroup[0])
            CM2Model::SetGeometryVisible(ourModel, 1300, 1399, 0);
            {
            CM2Model::SetGeometryVisible(ourModel, v60 + 1101, v60 + 1101, 1);
                auto geosetGroup = pPants->GeosetGroup[0];
          }
                auto pantsGeoset = 1101 + geosetGroup;
          else if ( showsTabard )
                if (geosetGroup > 2)
          {
                {
            CM2Model::SetGeometryVisible(ourModel, v60 + 1101, v60 + 1101, 1);
                    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
  // CLOAK (?) - m_geosetGroup[0] modifies 1501
     if (cloakID)
  // FIELD 6C0 CHECK (it's an itemID?)
  v61 = characterComponent->field_6C0;
  if ( v61 )
  {
    v62 = g_itemDisplayInfoDB->GetRecord(v61);
     if ( v62 )
     {
     {
      if ( v62->m_geosetGroup[0] )
        auto pCloak = GetItemDisplayInfoRec(cloakID);
      {
        if (pCloak && pCloak->GeosetGroup[0])
        CM2Model::SetGeometryVisible(ourModel, 1500, 1599, 0);
        {
        CM2Model::SetGeometryVisible(ourModel, v62->m_geosetGroup[0] + 1501, v62->m_geosetGroup[0] + 1501, 1);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1500, 1599, 0);
      }
            auto cloakGeoset = 1501 + pCloak->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, cloakGeoset, cloakGeoset, 1);
        }
     }
     }
  }
 
  // BELT (4) - m_geosetGroup[0] modifies 1801
    // Belt
  v64 = characterComponent->item_ids[BELT];
     if (beltID)
  if ( v64 )
  {
    v65 = g_itemDisplayInfoDB->GetRecord(v64);
     if ( v65 )
     {
     {
      if ( v65->m_geosetGroup[0] )
        auto pBelt = GetItemDisplayInfoRec(beltID);
      {
        if (pBelt && pBelt->GeosetGroup[0])
        CM2Model::SetGeometryVisible(ourModel, 1800, 1899, 0);
        {
        CM2Model::SetGeometryVisible(ourModel, v65->m_geosetGroup[0] + 1801, v65->m_geosetGroup[0] + 1801, 1);
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1800, 1899, 0);
      }
            auto beltGeoset = 1801 + pBelt->GeosetGroup[0];
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, beltGeoset, beltGeoset, 1);
        }
     }
     }
  }
 
  // FIELD 20 CHECK (&0x10 != 0)
    BOOL unkBool;
  if ( characterComponent->field_20 & 0x10 != )
 
  {
     if (pCharComponent->flags & 8)
    // If you aren't wearing PANTS, you have a tabard, and you don't have a dress (a dress from CHEST presumably, since you aren't wearing PANTS), enable 1401
     if ( showsTabard && !characterComponent->item_ids[PANTS] && !hasDress )
     {
     {
      v67 = 1401;
        unkBool = !pantsID && !dressChestpiece && !dressPants && !showsTabard && !tailFlag && !hasBulkyBeltFlag;
      v68 = 1401;
        //unkBool = ((pantsID | showsTabard | hasDress) == 0) & ((hasBulkyBeltFlag | tailFlag) ^ 1);
      v69 = 1;
        if (unkBool)
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1401, 1401, 1);
        }
        else
        {
            CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 1400, 1499, 0);
        }
     }
     }
     else
     else
     {
     {
      v67 = 1400;
        unkBool = 0;
      v68 = 1499;
      v69 = 0;
     }
     }
     CM2Model::SetGeometryVisible(ourModel, v67, v68, v69);
 
  }
    // DH hands
 
    uint32_t v86 = GetConditionalGeoset(pCharComponent->raceID, 23);
  // Remove unneeded edges and vertices due to the enabled geosets
    if (v86 <= 0)
  CM2Model::OptimizeVisibleGeometry(ourModel);
        v86 = 1;
 
     CM2Model::SetGeometryVisible(pCharComponent->modelPtr, 2300 + v86, 2300 + v86, 1);
  // FIELD 20 MODIFICATION (&=0xFD)
 
  characterComponent->field_20 &= 0xFD;
    //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();
  }
  }

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();
}