From 66c003e424314974f2cd096e8da1bd783ce7ef25 Mon Sep 17 00:00:00 2001 From: fallenoak Date: Mon, 27 Oct 2025 16:46:50 -0500 Subject: [PATCH] feat(component): add CCharacterComponent::SetHairStyle --- src/component/CCharacterComponent.cpp | 39 +++++++++++++++++++++++++++ src/component/CCharacterComponent.hpp | 2 ++ src/component/Util.cpp | 14 ++++++++++ src/component/Util.hpp | 3 +++ 4 files changed, 58 insertions(+) diff --git a/src/component/CCharacterComponent.cpp b/src/component/CCharacterComponent.cpp index abfabcd..42c6559 100644 --- a/src/component/CCharacterComponent.cpp +++ b/src/component/CCharacterComponent.cpp @@ -716,6 +716,7 @@ void CCharacterComponent::Init(ComponentData* data, const char* a3) { // TODO this->SetSkinColor(this->m_data.skinColorID, false, true, a3); + this->SetHairStyle(this->m_data.hairStyleID, a3); // TODO } @@ -874,6 +875,44 @@ void CCharacterComponent::SetFace(int32_t faceID, bool a3, const char* a4) { this->m_flags &= ~0x8; } +void CCharacterComponent::SetHairColor(int32_t hairColorID, bool a3, const char* a4) { + // TODO +} + +void CCharacterComponent::SetHairStyle(int32_t hairStyleID, const char* a3) { + if (!ComponentValidateBase( + CCharacterComponent::s_chrVarArray, + this->m_data.raceID, + this->m_data.sexID, + VARIATION_HAIR, + hairStyleID, + this->m_data.hairColorID + )) { + return; + } + + this->m_data.hairStyleID = hairStyleID; + + auto hairGeoset = ComponentGetHairGeoset(&this->m_data); + this->m_data.geosets[0] = hairGeoset; + + bool isNPC = this->m_data.flags & 0x1; + + if (!isNPC) { + this->LoadBaseVariation(VARIATION_HAIR, 1, this->m_data.hairStyleID, this->m_data.hairColorID, SECTION_HEAD_LOWER, a3); + this->LoadBaseVariation(VARIATION_HAIR, 2, this->m_data.hairStyleID, this->m_data.hairColorID, SECTION_HEAD_UPPER, a3); + } + + this->SetHairColor(this->m_data.hairColorID, false, a3); + + this->m_flags |= 0x4; + this->m_sectionDirty |= (1 << SECTION_HEAD_LOWER) | (1 << SECTION_HEAD_UPPER); + + // TODO component request logic + + this->m_flags &= ~0x8; +} + void CCharacterComponent::SetSkinColor(int32_t skinColorID, bool a3, bool a4, const char* a5) { bool isNPC = this->m_data.flags & 0x1; diff --git a/src/component/CCharacterComponent.hpp b/src/component/CCharacterComponent.hpp index 775822d..adbcc70 100644 --- a/src/component/CCharacterComponent.hpp +++ b/src/component/CCharacterComponent.hpp @@ -127,6 +127,8 @@ class CCharacterComponent { void RenderPrepSections(); void ReplaceExtraSkinTexture(const char* a2); void SetFace(int32_t faceID, bool a3, const char* a4); + void SetHairColor(int32_t hairColorID, bool a3, const char* a4); + void SetHairStyle(int32_t hairStyleID, const char* a3); void SetSkinColor(int32_t skinColorID, bool a3, bool a4, const char* a5); int32_t VariationsLoaded(int32_t a2); }; diff --git a/src/component/Util.cpp b/src/component/Util.cpp index eb97d54..2740879 100644 --- a/src/component/Util.cpp +++ b/src/component/Util.cpp @@ -1,4 +1,5 @@ #include "component/Util.hpp" +#include "component/CCharacterComponent.hpp" #include "db/Db.hpp" #include "object/Types.hpp" #include @@ -128,6 +129,19 @@ int32_t BuildComponentArray(uint32_t varArrayLength, st_race** varArrayPtr) { return 1; } +int32_t ComponentGetHairGeoset(ComponentData* data) { + for (int32_t i = 0; i < g_charHairGeosetsDB.GetNumRecords(); i++) { + auto hairGeosetRec = g_charHairGeosetsDB.GetRecordByIndex(i); + + if (hairGeosetRec->m_raceID == data->raceID && hairGeosetRec->m_sexID == data->sexID && hairGeosetRec->m_variationID == data->hairStyleID) { + auto geosetId = hairGeosetRec->m_geosetID; + return geosetId > 0 ? geosetId : 1; + } + } + + return 1; +} + int32_t ComponentGetNumColors(st_race* varArray, int32_t raceId, int32_t sexId, COMPONENT_VARIATIONS sectionIndex, int32_t variationIndex) { auto& section = varArray[(raceId * UNITSEX_NUM_SEXES + sexId)].sections[sectionIndex]; diff --git a/src/component/Util.hpp b/src/component/Util.hpp index d5e88a9..4c84802 100644 --- a/src/component/Util.hpp +++ b/src/component/Util.hpp @@ -6,6 +6,7 @@ class CharSectionsRec; +struct ComponentData; struct st_variation; struct st_color { @@ -28,6 +29,8 @@ struct st_variation { int32_t BuildComponentArray(uint32_t varArrayLength, st_race** varArrayPtr); +int32_t ComponentGetHairGeoset(ComponentData* data); + int32_t ComponentGetNumColors(st_race* varArray, int32_t raceId, int32_t sexId, COMPONENT_VARIATIONS sectionIndex, int32_t variationIndex); CharSectionsRec* ComponentGetSectionsRecord(st_race* varArray, int32_t raceId, int32_t sexId, COMPONENT_VARIATIONS sectionIndex, int32_t variationIndex, int32_t colorIndex, bool* found);