diff --git a/src/component/CCharacterComponent.cpp b/src/component/CCharacterComponent.cpp index 65a99d1..83b1d53 100644 --- a/src/component/CCharacterComponent.cpp +++ b/src/component/CCharacterComponent.cpp @@ -1048,6 +1048,21 @@ void CCharacterComponent::GeosRenderPrep() { this->m_flags &= ~0x4; } +void CCharacterComponent::GetPreferences(CharacterPreferences* preferences) { + if (!preferences) { + return; + } + + preferences->raceID = this->m_data.raceID; + preferences->sexID = this->m_data.sexID; + preferences->classID = this->m_data.classID; + preferences->hairColorID = this->m_data.hairColorID; + preferences->skinColorID = this->m_data.skinColorID; + preferences->faceID = this->m_data.faceID; + preferences->facialHairStyleID = this->m_data.facialHairStyleID; + preferences->hairStyleID = this->m_data.hairStyleID; +} + CharSectionsRec* CCharacterComponent::GetSectionsRecord(COMPONENT_VARIATIONS sectionIndex, int32_t variationIndex, int32_t colorIndex, bool* found) { return ComponentGetSectionsRecord( CCharacterComponent::s_chrVarArray, diff --git a/src/component/CCharacterComponent.hpp b/src/component/CCharacterComponent.hpp index e0b3a61..b747709 100644 --- a/src/component/CCharacterComponent.hpp +++ b/src/component/CCharacterComponent.hpp @@ -88,6 +88,7 @@ class CCharacterComponent { void CreateBaseTexture(); void* CreateTexture(const ItemDisplayInfoRec* displayRec, int32_t section); void GeosRenderPrep(); + void GetPreferences(CharacterPreferences* preferences); CharSectionsRec* GetSectionsRecord(COMPONENT_VARIATIONS sectionIndex, int32_t variationIndex, int32_t colorIndex, bool* found); int32_t Init(ComponentData* data, const char* a3); int32_t ItemsLoaded(int32_t a2); diff --git a/src/component/ComponentData.cpp b/src/component/ComponentData.cpp index 097e69c..8af0069 100644 --- a/src/component/ComponentData.cpp +++ b/src/component/ComponentData.cpp @@ -1,21 +1,6 @@ #include "component/ComponentData.hpp" #include "component/Types.hpp" -void ComponentData::GetPreferences(CharacterPreferences* preferences) { - if (!preferences) { - return; - } - - preferences->raceID = this->raceID; - preferences->sexID = this->sexID; - preferences->classID = this->classID; - preferences->hairColorID = this->hairColorID; - preferences->skinColorID = this->skinColorID; - preferences->faceID = this->faceID; - preferences->facialHairStyleID = this->facialHairStyleID; - preferences->hairStyleID = this->hairStyleID; -} - void ComponentData::SetPreferences(CharacterPreferences* preferences) { if (!preferences) { return; diff --git a/src/component/ComponentData.hpp b/src/component/ComponentData.hpp index fb5751a..3f284ed 100644 --- a/src/component/ComponentData.hpp +++ b/src/component/ComponentData.hpp @@ -42,7 +42,6 @@ struct ComponentData { 1801, }; - void GetPreferences(CharacterPreferences* preferences); void SetPreferences(CharacterPreferences* preferences); }; diff --git a/src/glue/CCharacterCreation.cpp b/src/glue/CCharacterCreation.cpp index 3e8c63d..2474ff6 100644 --- a/src/glue/CCharacterCreation.cpp +++ b/src/glue/CCharacterCreation.cpp @@ -1,4 +1,5 @@ #include "glue/CCharacterCreation.hpp" +#include "glue/CCharacterSelection.hpp" #include "component/CCharacterComponent.hpp" #include "component/Types.hpp" #include "db/Db.hpp" @@ -10,6 +11,7 @@ CCharacterComponent* CCharacterCreation::s_character; CSimpleModelFFX* CCharacterCreation::s_charCustomizeFrame; float CCharacterCreation::s_charFacing; +CharacterPreferences* CCharacterCreation::s_charPreferences[22][2]; TSFixedArray CCharacterCreation::s_classes; int32_t CCharacterCreation::s_existingCharacterIndex; int32_t CCharacterCreation::s_raceIndex; @@ -262,6 +264,20 @@ void CCharacterCreation::SetFacing(float orientation) { } } +void CCharacterCreation::SavePreferences() { + auto raceID = CCharacterCreation::s_races.m_data[CCharacterCreation::s_raceIndex]; + auto sexID = CCharacterCreation::s_character->m_data.sexID; + + auto preferences = CCharacterCreation::s_charPreferences[raceID][sexID]; + + if (!preferences) { + preferences = STORM_NEW(CharacterPreferences); + CCharacterCreation::s_charPreferences[raceID][sexID] = preferences; + } + + CCharacterCreation::s_character->GetPreferences(preferences); +} + void CCharacterCreation::SetSelectedClass(int32_t classID) { if (!CCharacterCreation::IsClassValid(classID)) { return; @@ -287,3 +303,82 @@ void CCharacterCreation::SetSelectedClass(int32_t classID) { CGlueLoading::StartLoad(CCharacterCreation::s_character, true); } + +void CCharacterCreation::SetSelectedRace(int32_t raceIndex) { + if (raceIndex >= CCharacterCreation::s_races.Count() || raceIndex == CCharacterCreation::s_raceIndex) { + return; + } + + auto selectedRaceID = CCharacterCreation::s_races[raceIndex]; + auto selectedSexID = CCharacterCreation::s_character->m_data.sexID; + + CCharacterCreation::SavePreferences(); + + CCharacterCreation::s_raceIndex = raceIndex; + + ComponentData data = {}; + + auto existingCharacter = CCharacterCreation::s_existingCharacterIndex >= 0 + ? CCharacterSelection::GetCharacterDisplay(CCharacterCreation::s_existingCharacterIndex) + : nullptr; + + bool useExistingCharacter = existingCharacter + && existingCharacter->m_info.raceID == selectedRaceID + && existingCharacter->m_info.customizeFlags & 0x110000; + + bool usePreferences = !useExistingCharacter && + CCharacterCreation::s_charPreferences[selectedRaceID][selectedSexID]; + + if (useExistingCharacter) { + data.raceID = existingCharacter->m_info.raceID; + data.sexID = existingCharacter->m_info.sexID; + data.classID = existingCharacter->m_info.classID; + data.skinColorID = existingCharacter->m_info.skinColorID; + data.hairStyleID = existingCharacter->m_info.hairStyleID; + data.hairColorID = existingCharacter->m_info.hairColorID; + data.facialHairStyleID = existingCharacter->m_info.facialHairStyleID; + data.faceID = existingCharacter->m_info.faceID; + + CCharacterCreation::CreateComponent(&data, false); + + CCharacterCreation::SetSelectedSex(existingCharacter->m_info.sexID); + } else if (usePreferences) { + auto preferences = CCharacterCreation::s_charPreferences[selectedRaceID][selectedSexID]; + data.SetPreferences(preferences); + + CCharacterCreation::CalcClasses(data.raceID); + + if (!CCharacterCreation::IsRaceClassValid(data.raceID, CCharacterCreation::s_selectedClassID)) { + CCharacterCreation::s_selectedClassID = CCharacterCreation::GetRandomClassID(); + } + + data.classID = CCharacterCreation::s_selectedClassID; + + // TODO CCharacterComponent::ValidateComponentData(&data, 0); + + CCharacterCreation::CreateComponent(&data, false); + } else { + data.raceID = selectedRaceID; + data.sexID = selectedSexID; + + CCharacterCreation::CalcClasses(data.raceID); + + if (!CCharacterCreation::IsRaceClassValid(data.raceID, CCharacterCreation::s_selectedClassID)) { + CCharacterCreation::SetSelectedClass(CCharacterCreation::GetRandomClassID()); + } + + data.classID = CCharacterCreation::s_selectedClassID; + + CCharacterCreation::CreateComponent(&data, true); + } + + // TODO name gen stuff + + CCharacterCreation::Dress(); + + CGlueLoading::StartLoad(CCharacterCreation::s_character, true); +} + +void CCharacterCreation::SetSelectedSex(int32_t sexID) { + // TODO +} diff --git a/src/glue/CCharacterCreation.hpp b/src/glue/CCharacterCreation.hpp index 1f1991d..231aee0 100644 --- a/src/glue/CCharacterCreation.hpp +++ b/src/glue/CCharacterCreation.hpp @@ -7,6 +7,8 @@ class ChrClassesRec; class CCharacterComponent; class CSimpleModelFFX; + +struct CharacterPreferences; struct ComponentData; class CCharacterCreation { @@ -15,6 +17,7 @@ class CCharacterCreation { static CCharacterComponent* s_character; static CSimpleModelFFX* s_charCustomizeFrame; static float s_charFacing; + static CharacterPreferences* s_charPreferences[22][2]; static TSFixedArray s_classes; static int32_t s_existingCharacterIndex; static int32_t s_raceIndex; @@ -31,9 +34,12 @@ class CCharacterCreation { static bool IsClassValid(int32_t classID); static bool IsRaceClassValid(int32_t raceID, int32_t classID); static void ResetCharCustomizeInfo(); + static void SavePreferences(); static void SetCharCustomizeModel(const char* filename); static void SetFacing(float orientation); static void SetSelectedClass(int32_t classID); + static void SetSelectedRace(int32_t raceIndex); + static void SetSelectedSex(int32_t sexID); }; #endif diff --git a/src/glue/CCharacterCreationScript.cpp b/src/glue/CCharacterCreationScript.cpp index 336d9c2..3832a51 100644 --- a/src/glue/CCharacterCreationScript.cpp +++ b/src/glue/CCharacterCreationScript.cpp @@ -237,7 +237,15 @@ int32_t Script_GetSelectedClass(lua_State* L) { } int32_t Script_SetSelectedRace(lua_State* L) { - WHOA_UNIMPLEMENTED(0); + if (!lua_isnumber(L, 1)) { + luaL_error(L, "Usage: SetSelectedRace(index)"); + return 0; + } + + auto raceIndex = lua_tointeger(L, 1); + CCharacterCreation::SetSelectedRace(raceIndex - 1); + + return 0; } int32_t Script_SetSelectedSex(lua_State* L) {