mirror of
https://github.com/whoahq/whoa.git
synced 2026-02-01 00:02:45 +03:00
267 lines
7.8 KiB
C++
267 lines
7.8 KiB
C++
#include "glue/CCharacterCreation.hpp"
|
|
#include "component/CCharacterComponent.hpp"
|
|
#include "component/Types.hpp"
|
|
#include "db/Db.hpp"
|
|
#include "glue/CGlueLoading.hpp"
|
|
#include "model/CM2Shared.hpp"
|
|
#include "object/client/Player_C.hpp"
|
|
#include "ui/simple/CSimpleModelFFX.hpp"
|
|
|
|
CCharacterComponent* CCharacterCreation::s_character;
|
|
CSimpleModelFFX* CCharacterCreation::s_charCustomizeFrame;
|
|
float CCharacterCreation::s_charFacing;
|
|
TSFixedArray<const ChrClassesRec*> CCharacterCreation::s_classes;
|
|
int32_t CCharacterCreation::s_existingCharacterIndex;
|
|
int32_t CCharacterCreation::s_raceIndex;
|
|
TSGrowableArray<int32_t> CCharacterCreation::s_races;
|
|
int32_t CCharacterCreation::s_selectedClassID;
|
|
|
|
void CCharacterCreation::CalcClasses(int32_t raceID) {
|
|
uint32_t classCount = 0;
|
|
|
|
for (int32_t i = 0; i < g_charBaseInfoDB.GetNumRecords(); i++) {
|
|
auto infoRec = g_charBaseInfoDB.GetRecordByIndex(i);
|
|
|
|
if (infoRec->m_raceID == raceID) {
|
|
classCount++;
|
|
}
|
|
}
|
|
|
|
CCharacterCreation::s_classes.SetCount(classCount);
|
|
|
|
uint32_t classIndex = 0;
|
|
|
|
for (int32_t i = 0; i < g_charBaseInfoDB.GetNumRecords(); i++) {
|
|
auto infoRec = g_charBaseInfoDB.GetRecordByIndex(i);
|
|
|
|
if (infoRec->m_raceID != raceID) {
|
|
continue;
|
|
}
|
|
|
|
auto classRec = g_chrClassesDB.GetRecord(infoRec->m_classID);
|
|
CCharacterCreation::s_classes[classIndex++] = classRec;
|
|
}
|
|
}
|
|
|
|
void CCharacterCreation::CreateComponent(ComponentData* data, bool randomize) {
|
|
auto modelData = Player_C_GetModelName(data->raceID, data->sexID);
|
|
|
|
if (!modelData || !modelData->m_modelName) {
|
|
return;
|
|
}
|
|
|
|
auto existingComponent = CCharacterCreation::s_character;
|
|
|
|
if (existingComponent) {
|
|
auto model = existingComponent->m_data.model;
|
|
|
|
if (model->m_attachParent) {
|
|
model->DetachFromParent();
|
|
}
|
|
|
|
// TODO CCharacterComponent::FreeComponent(existingComponent);
|
|
}
|
|
|
|
CCharacterCreation::s_character = CCharacterComponent::AllocComponent();
|
|
|
|
auto scene = CCharacterCreation::s_charCustomizeFrame->GetScene();
|
|
auto model = scene->CreateModel(modelData->m_modelName, 0);
|
|
data->model = model;
|
|
|
|
if (!model) {
|
|
return;
|
|
}
|
|
|
|
// TODO lighting
|
|
|
|
data->model->SetBoneSequence(-1, 0, 0, 0, 1.0f, 1, 1);
|
|
|
|
data->flags |= 0x2;
|
|
|
|
CCharacterCreation::s_character->Init(data, nullptr);
|
|
|
|
if (randomize) {
|
|
// TODO select random variations
|
|
}
|
|
|
|
// TODO track previous variations
|
|
|
|
// TODO set facing
|
|
|
|
CCharacterCreation::Dress();
|
|
|
|
CCharacterCreation::s_character->RenderPrep(0);
|
|
|
|
if (CCharacterCreation::s_charCustomizeFrame->m_model) {
|
|
model->AttachToParent(CCharacterCreation::s_charCustomizeFrame->m_model, 0, nullptr, 0);
|
|
}
|
|
}
|
|
|
|
void CCharacterCreation::Dress() {
|
|
// TODO
|
|
}
|
|
|
|
int32_t CCharacterCreation::GetRandomClassID() {
|
|
// TODO
|
|
return 1;
|
|
}
|
|
|
|
void CCharacterCreation::GetRandomRaceAndSex(ComponentData* data) {
|
|
// TODO
|
|
data->raceID = 1;
|
|
data->sexID = UNITSEX_MALE;
|
|
}
|
|
|
|
void CCharacterCreation::Initialize() {
|
|
CCharacterCreation::s_charFacing = 0.0f;
|
|
CCharacterCreation::s_charCustomizeFrame = nullptr;
|
|
CCharacterCreation::s_existingCharacterIndex = -1;
|
|
|
|
CCharacterCreation::s_races.SetCount(0);
|
|
|
|
// TODO enum or define for faction sides
|
|
for (int32_t side = 0; side < 2; side++) {
|
|
for (int32_t race = 0; race < g_chrRacesDB.GetNumRecords(); race++) {
|
|
auto raceRec = g_chrRacesDB.GetRecordByIndex(race);
|
|
|
|
// TODO NPCOnly?
|
|
if (raceRec->m_flags & 0x1) {
|
|
continue;
|
|
}
|
|
|
|
auto factionTemplateRec = g_factionTemplateDB.GetRecord(raceRec->m_factionID);
|
|
|
|
for (int32_t group = 0; group < g_factionGroupDB.GetNumRecords(); group++) {
|
|
auto factionGroupRec = g_factionGroupDB.GetRecordByIndex(group);
|
|
|
|
if (!factionGroupRec || !factionGroupRec->m_maskID) {
|
|
continue;
|
|
}
|
|
|
|
bool templateMatch = (1 << factionGroupRec->m_maskID) & factionTemplateRec->m_factionGroup;
|
|
|
|
if (!templateMatch) {
|
|
continue;
|
|
}
|
|
|
|
bool sideMatch =
|
|
(side == 0 && !SStrCmpI(factionGroupRec->m_internalName, "Alliance"))
|
|
|| (side == 1 && !SStrCmpI(factionGroupRec->m_internalName, "Horde"));
|
|
|
|
if (!sideMatch) {
|
|
continue;
|
|
}
|
|
|
|
// Race is playable and part of a faction aligned to either Alliance or Horde
|
|
*CCharacterCreation::s_races.New() = raceRec->m_ID;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CCharacterCreation::IsClassValid(int32_t classID) {
|
|
for (int32_t i = 0; i < CCharacterCreation::s_classes.Count(); i++) {
|
|
auto classRec = CCharacterCreation::s_classes[i];
|
|
|
|
if (classRec->m_ID == classID) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CCharacterCreation::ResetCharCustomizeInfo() {
|
|
if (!CCharacterCreation::s_charCustomizeFrame) {
|
|
return;
|
|
}
|
|
|
|
CCharacterCreation::s_existingCharacterIndex = -1;
|
|
|
|
auto model = CCharacterCreation::s_charCustomizeFrame->m_model;
|
|
|
|
if (model) {
|
|
model->DetachAllChildrenById(0);
|
|
}
|
|
|
|
ComponentData data = {};
|
|
CCharacterCreation::GetRandomRaceAndSex(&data);
|
|
CCharacterCreation::CalcClasses(data.raceID);
|
|
|
|
CCharacterCreation::CreateComponent(&data, true);
|
|
|
|
CCharacterCreation::SetSelectedClass(CCharacterCreation::GetRandomClassID());
|
|
data.classID = CCharacterCreation::s_selectedClassID;
|
|
|
|
CCharacterCreation::s_raceIndex = -1;
|
|
|
|
for (int32_t i = 0; i < CCharacterCreation::s_races.Count(); i++) {
|
|
auto raceID = CCharacterCreation::s_races[i];
|
|
|
|
if (CCharacterCreation::s_character->m_data.raceID == raceID) {
|
|
CCharacterCreation::s_raceIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// TODO name gen stuff
|
|
|
|
CGlueLoading::StartLoad(CCharacterCreation::s_character, true);
|
|
}
|
|
|
|
void CCharacterCreation::SetCharCustomizeModel(const char* filename) {
|
|
if (!CCharacterCreation::s_charCustomizeFrame || !filename || !*filename) {
|
|
return;
|
|
}
|
|
|
|
auto existingModel = CCharacterCreation::s_charCustomizeFrame->m_model;
|
|
|
|
if (existingModel && !SStrCmpI(existingModel->m_shared->m_filePath, filename)) {
|
|
return;
|
|
}
|
|
|
|
CCharacterCreation::s_charCustomizeFrame->SetModel(filename);
|
|
auto customizeModel = CCharacterCreation::s_charCustomizeFrame->m_model;
|
|
|
|
// TODO inlined?
|
|
if (customizeModel) {
|
|
// TODO lighting stuff
|
|
customizeModel->IsDrawable(1, 1);
|
|
}
|
|
|
|
// TODO inlined?
|
|
if (customizeModel) {
|
|
auto characterModel = CCharacterCreation::s_character->m_data.model;
|
|
|
|
if (characterModel) {
|
|
characterModel->AttachToParent(customizeModel, 0, nullptr, 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCharacterCreation::SetSelectedClass(int32_t classID) {
|
|
if (!CCharacterCreation::IsClassValid(classID)) {
|
|
return;
|
|
}
|
|
|
|
CCharacterCreation::s_selectedClassID = classID;
|
|
|
|
ComponentData data = {};
|
|
data.raceID = CCharacterCreation::s_character->m_data.raceID;
|
|
data.sexID = CCharacterCreation::s_character->m_data.sexID;
|
|
data.classID = classID;
|
|
data.skinColorID = CCharacterCreation::s_character->m_data.skinColorID;
|
|
data.hairStyleID = CCharacterCreation::s_character->m_data.hairStyleID;
|
|
data.hairColorID = CCharacterCreation::s_character->m_data.hairColorID;
|
|
data.facialHairStyleID = CCharacterCreation::s_character->m_data.facialHairStyleID;
|
|
data.faceID = CCharacterCreation::s_character->m_data.faceID;
|
|
|
|
// TODO CCharacterComponent::ValidateComponentData(&data, 0);
|
|
|
|
CCharacterCreation::CreateComponent(&data, false);
|
|
|
|
CCharacterCreation::Dress();
|
|
|
|
CGlueLoading::StartLoad(CCharacterCreation::s_character, true);
|
|
}
|