feat: update CCharacterComponent and CCharacterCreation classes

This commit is contained in:
VDm 2025-05-17 20:00:10 +04:00
parent 971b781368
commit f2a253f5ad
8 changed files with 348 additions and 22 deletions

View File

@ -12,6 +12,7 @@
#include "db/Db.hpp" #include "db/Db.hpp"
#include "db/Startup_Strings.hpp" #include "db/Startup_Strings.hpp"
#include "glue/CGlueMgr.hpp" #include "glue/CGlueMgr.hpp"
#include "glue/CCharacterComponent.hpp"
#include "gameui/CGGameUI.hpp" #include "gameui/CGGameUI.hpp"
#include "gx/Screen.hpp" #include "gx/Screen.hpp"
#include "gx/Texture.hpp" #include "gx/Texture.hpp"
@ -736,8 +737,8 @@ void WowClientInit() {
// TODO // TODO
// sub_6F75E0(); // sub_6F75E0();
// sub_401FF0();
CCharacterComponent::Initialize();
ClientServices::Initialize(); ClientServices::Initialize();
// TODO ClientServices::SetMessageHandler(SMSG_TUTORIAL_FLAGS, (int)sub_530920, 0); // TODO ClientServices::SetMessageHandler(SMSG_TUTORIAL_FLAGS, (int)sub_530920, 0);

View File

@ -1 +1,136 @@
#include "glue/CCharacterComponent.hpp" #include "glue/CCharacterComponent.hpp"
#include <algorithm>
#include <common/ObjectAlloc.hpp>
#include <common/Processor.hpp>
#include "console/Types.hpp"
#include "console/CVar.hpp"
CVar* CCharacterComponent::g_componentTextureLevelVar = nullptr;
CVar* CCharacterComponent::g_componentThreadVar = nullptr;
CVar* CCharacterComponent::g_componentCompressVar = nullptr;
uint32_t* CCharacterComponent::s_heap = nullptr;
static bool ComponentVarHandler(CVar*, const char*, const char*, void*) {
return true;
}
ComponentData::ComponentData() {
this->m_unkFlag &= 0xFFFFFFFC;
memset(&this->m_info, 0, sizeof(this->m_info));
this->m_model = nullptr;
}
void CCharacterComponent::Initialize() {
CCharacterComponent::g_componentTextureLevelVar = CVar::Register(
"componentTextureLevel",
"Number of mip levels used for character component textures",
0x1,
"8",
&ComponentVarHandler,
CATEGORY::DEBUG,
0,
nullptr,
false);
CCharacterComponent::g_componentThreadVar = CVar::Register(
"componentThread",
"Multi thread character component processing",
0x1,
"1",
&ComponentVarHandler,
CATEGORY::DEBUG,
0,
nullptr,
false);
CCharacterComponent::g_componentCompressVar = CVar::Register(
"componentCompress",
"Character component texture compression",
0x1,
"1",
&ComponentVarHandler,
CATEGORY::DEBUG,
0,
nullptr,
false);
uint32_t mipLevels = CCharacterComponent::g_componentTextureLevelVar->GetInt();
int32_t useThreads = CCharacterComponent::g_componentThreadVar->GetInt();
int32_t useCompression = CCharacterComponent::g_componentCompressVar->GetInt();
if (!useThreads || OsGetProcessorCount() < 2) {
useThreads = 0;
if (mipLevels > 8) {
mipLevels = 8;
}
useCompression = 0;
}
if (mipLevels > 9) {
mipLevels = 9;
}
if (mipLevels < 7) {
mipLevels = 7;
}
CCharacterComponent::Initialize(GxTex_Rgb565, mipLevels, useThreads, useCompression);
}
void CCharacterComponent::Initialize(EGxTexFormat format, uint32_t mipLevels, int32_t useThreads, int32_t useCompression) {
CCharacterComponent::s_heap = static_cast<uint32_t*>(ALLOC(sizeof(uint32_t)));
if (CCharacterComponent::s_heap) {
*CCharacterComponent::s_heap = ObjectAllocAddHeap(sizeof(CCharacterComponent), 32, "CCharacterComponent", true);
}
// TODO
}
CCharacterComponent* CCharacterComponent::AllocComponent() {
uint32_t handle;
void* memory;
if (ObjectAlloc(*CCharacterComponent::s_heap, &handle, &memory, false) && memory) {
auto component = new (memory) CCharacterComponent();
component->m_handle = handle;
return component;
}
return nullptr;
}
void CCharacterComponent::FreeComponent(CCharacterComponent* component) {
component->~CCharacterComponent();
// TODO: ObjectFree()
}
CCharacterComponent::CCharacterComponent() {
}
CCharacterComponent::~CCharacterComponent() {
}
void CCharacterComponent::SetRandomSkin(COMPONENT_CONTEXT context) {
}
void CCharacterComponent::SetRandomHairColor(COMPONENT_CONTEXT context) {
}
void CCharacterComponent::SetRandomHairStyle(COMPONENT_CONTEXT context) {
}
void CCharacterComponent::SetRandomFace(COMPONENT_CONTEXT context) {
}
void CCharacterComponent::SetRandomFacialFeature(COMPONENT_CONTEXT context) {
}
bool CCharacterComponent::Init(ComponentData* data, const char* a3) {
return false;
}

View File

@ -2,16 +2,61 @@
#define GLUE_C_CHARACTER_COMPONENT_HPP #define GLUE_C_CHARACTER_COMPONENT_HPP
#include "net/Types.hpp" #include "net/Types.hpp"
#include "gx/Types.hpp"
#include <storm/Array.hpp> #include <storm/Array.hpp>
class CSimpleModelFFX; class CSimpleModelFFX;
class CM2Model; class CM2Model;
class CVar;
class ComponentData {
public:
ComponentData();
public:
CHARACTER_CREATE_INFO m_info;
CM2Model* m_model;
uint32_t m_unkFlag;
};
class CCharacterComponent { class CCharacterComponent {
public:
enum COMPONENT_CONTEXT
{
DEFAULT_CONTEXT = 0,
CONTEXT_1,
CONTEXT_2,
CONTEXT_3
};
public: public:
// Static variables // Static variables
static CVar* g_componentTextureLevelVar;
static CVar* g_componentThreadVar;
static CVar* g_componentCompressVar;
static uint32_t* s_heap;
// Static functions // Static functions
static void Initialize();
static void Initialize(EGxTexFormat format, uint32_t mipLevels, int32_t useThreads, int32_t useCompression);
static CCharacterComponent* AllocComponent();
static void FreeComponent(CCharacterComponent* component);
CCharacterComponent();
~CCharacterComponent();
void SetRandomSkin(COMPONENT_CONTEXT context = DEFAULT_CONTEXT);
void SetRandomHairColor(COMPONENT_CONTEXT context = DEFAULT_CONTEXT);
void SetRandomHairStyle(COMPONENT_CONTEXT context = DEFAULT_CONTEXT);
void SetRandomFace(COMPONENT_CONTEXT context = DEFAULT_CONTEXT);
void SetRandomFacialFeature(COMPONENT_CONTEXT context = DEFAULT_CONTEXT);
bool Init(ComponentData* data, const char* a3);
public:
uint32_t m_handle;
ComponentData m_data;
}; };
#endif // GLUE_C_CHARACTER_COMPONENT_HPP #endif // GLUE_C_CHARACTER_COMPONENT_HPP

View File

@ -1,8 +1,114 @@
#include "glue/CCharacterCreation.hpp" #include "glue/CCharacterCreation.hpp"
#include "glue/CCharacterComponent.hpp"
#include "ui/CSimpleModelFFX.hpp"
#include "model/CM2Model.hpp"
#include "clientobject/Player_C.hpp"
#include "db/Db.hpp"
float CCharacterCreation::m_charFacing = 0.0; int32_t CCharacterCreation::m_existingCharacterIndex;
CharacterCreationDisplay CCharacterCreation::m_character = {}; int32_t CCharacterCreation::m_raceIndex;
CSimpleModel* CCharacterCreation::m_charCustomizeFrame;
float CCharacterCreation::m_charFacing;
uint32_t CCharacterCreation::m_prevSkinIndex;
uint32_t CCharacterCreation::m_prevFaceIndex;
uint32_t CCharacterCreation::m_prevHairColorIndex;
uint32_t CCharacterCreation::m_prevHairStyleIndex;
uint32_t CCharacterCreation::m_prevFacialFeatureIndex;
CCharacterComponent* CCharacterCreation::m_character = nullptr;
TSGrowableArray<uint32_t> CCharacterCreation::m_races;
void CCharacterCreation::Initialize() { void CCharacterCreation::Initialize() {
CCharacterCreation::m_charFacing = 0.0; CCharacterCreation::m_charFacing = 0.0;
CCharacterCreation::m_charCustomizeFrame = nullptr;
CCharacterCreation::m_existingCharacterIndex = -1;
}
void CCharacterCreation::SetCharCustomizeFrame(CSimpleModel* frame) {
CCharacterCreation::m_charCustomizeFrame = frame;
}
void CCharacterCreation::SetCharCustomizeModel(char const* filename) {
if (!CCharacterCreation::m_charCustomizeFrame || !filename || !*filename) {
return;
}
// TODO
CCharacterCreation::m_charCustomizeFrame->SetModel(filename);
}
void CCharacterCreation::ResetCharCustomizeInfo() {
if (!CCharacterCreation::m_charCustomizeFrame) {
return;
}
CCharacterCreation::m_existingCharacterIndex = -1;
// TODO: CM2Model__DetachAllChildrenById
ComponentData data;
CCharacterCreation::GetRandomRaceAndSex(&data);
CCharacterCreation::CalcClasses(data.m_info.raceID);
CCharacterCreation::InitCharacterComponent(&data, 1);
// TODO
CCharacterCreation::m_raceIndex = -1;
// TODO
}
void CCharacterCreation::GetRandomRaceAndSex(ComponentData* data) {
// TODO
// WORKAROUND
data->m_info.raceID = 1;
}
void CCharacterCreation::CalcClasses(uint32_t raceID) {
}
void CCharacterCreation::InitCharacterComponent(ComponentData* data, int32_t randomize) {
auto record = Player_C_GetModelName(data->m_info.raceID, data->m_info.sexID);
if (!record || !record->m_modelName[0]) {
return;
}
if (CCharacterCreation::m_character) {
auto model = CCharacterCreation::m_character->m_data.m_model;
if (model->m_attachParent) {
// TODO: model->DetachFromParent();
}
CCharacterComponent::FreeComponent(CCharacterCreation::m_character);
}
CCharacterCreation::m_character = CCharacterComponent::AllocComponent();
auto scene = CCharacterCreation::m_charCustomizeFrame->GetScene();
data->m_model = scene->CreateModel(record->m_modelName, 0);
if (!data->m_model) {
return;
}
data->m_unkFlag |= 2u;
CCharacterCreation::m_character->Init(data, nullptr);
if (randomize) {
CCharacterCreation::RandomizeCharFeatures();
}
// TODO
}
void CCharacterCreation::RandomizeCharFeatures() {
CCharacterCreation::m_character->SetRandomSkin();
CCharacterCreation::m_character->SetRandomHairColor();
CCharacterCreation::m_character->SetRandomHairStyle();
CCharacterCreation::m_character->SetRandomFace();
CCharacterCreation::m_character->SetRandomFacialFeature();
const auto& info = CCharacterCreation::m_character->m_data.m_info;
CCharacterCreation::m_prevSkinIndex = info.skinID;
CCharacterCreation::m_prevFaceIndex = info.faceID;
CCharacterCreation::m_prevHairColorIndex = info.hairColorID;
CCharacterCreation::m_prevHairStyleIndex = info.hairStyleID;
CCharacterCreation::m_prevFacialFeatureIndex = info.facialFeatureID;
} }

View File

@ -4,22 +4,37 @@
#include "net/Types.hpp" #include "net/Types.hpp"
#include <storm/Array.hpp> #include <storm/Array.hpp>
class CSimpleModel;
class CSimpleModelFFX; class CSimpleModelFFX;
class CM2Model; class CM2Model;
class ComponentData;
class CCharacterComponent;
struct CharacterCreationDisplay {
CHARACTER_CREATE_INFO m_characterInfo;
CM2Model* m_characterModel;
};
class CCharacterCreation { class CCharacterCreation {
public: public:
// Static variables // Static variables
static int32_t m_existingCharacterIndex;
static int32_t m_raceIndex;
static CSimpleModel* m_charCustomizeFrame;
static float m_charFacing; static float m_charFacing;
static CharacterCreationDisplay m_character; static uint32_t m_prevSkinIndex;
static uint32_t m_prevFaceIndex;
static uint32_t m_prevHairColorIndex;
static uint32_t m_prevHairStyleIndex;
static uint32_t m_prevFacialFeatureIndex;
static CCharacterComponent* m_character;
static TSGrowableArray<uint32_t> m_races;
// Static functions // Static functions
static void Initialize(); static void Initialize();
static void SetCharCustomizeFrame(CSimpleModel* frame);
static void SetCharCustomizeModel(char const* filename);
static void ResetCharCustomizeInfo();
static void GetRandomRaceAndSex(ComponentData* data);
static void CalcClasses(uint32_t raceID);
static void InitCharacterComponent(ComponentData* data, int32_t randomize);
static void RandomizeCharFeatures();
}; };
#endif // GLUE_C_CHARACTER_CREATION_HPP #endif // GLUE_C_CHARACTER_CREATION_HPP

View File

@ -813,15 +813,12 @@ void CGlueMgr::InitCursor() {
} }
void CGlueMgr::Resume() { void CGlueMgr::Resume() {
// TODO CGlueMgr::m_disconnectPending = 0;
// CGlueMgr::m_disconnectPending = 0; CGlueMgr::m_reconnect = 0;
// CGlueMgr::m_reconnect = 0;
CGlueMgr::m_idleState = IDLE_NONE; CGlueMgr::m_idleState = IDLE_NONE;
CGlueMgr::m_showedDisconnect = 0;
// TODO CGlueMgr::m_characterInfo = nullptr;
// CGlueMgr::m_showedDisconnect = 0;
// CGlueMgr::m_characterInfo = 0;
CGlueMgr::m_suspended = 0; CGlueMgr::m_suspended = 0;
CGlueMgr::m_reload = 0; CGlueMgr::m_reload = 0;

View File

@ -1287,9 +1287,14 @@ struct CHARACTER_INFO {
}; };
struct CHARACTER_CREATE_INFO { struct CHARACTER_CREATE_INFO {
uint8_t unk[24];
uint32_t raceID; uint32_t raceID;
uint32_t sexID; uint32_t sexID;
uint32_t unk;
uint32_t hairColorID;
uint32_t skinID;
uint32_t faceID;
uint32_t facialFeatureID;
uint32_t hairStyleID;
}; };
struct CLIENT_NETSTATS { struct CLIENT_NETSTATS {

View File

@ -1,27 +1,49 @@
#include "ui/ScriptFunctions.hpp" #include "ui/ScriptFunctions.hpp"
#include "ui/CSimpleModelFFX.hpp"
#include "ui/Types.hpp" #include "ui/Types.hpp"
#include "util/Lua.hpp" #include "util/Lua.hpp"
#include "util/Unimplemented.hpp" #include "util/Unimplemented.hpp"
#include "db/Db.hpp" #include "db/Db.hpp"
#include "clientobject/Unit_C.hpp" #include "clientobject/Unit_C.hpp"
#include "glue/CCharacterCreation.hpp" #include "glue/CCharacterCreation.hpp"
#include "glue/CCharacterComponent.hpp"
#include <cstdint> #include <cstdint>
int32_t Script_SetCharCustomizeFrame(lua_State* L) { int32_t Script_SetCharCustomizeFrame(lua_State* L) {
WHOA_UNIMPLEMENTED(0); if (!lua_isstring(L, 1)) {
return luaL_error(L, "Usage: SetCharCustomizeFrame(\"frameName\")");
}
auto type = CSimpleModel::GetObjectType();
auto name = lua_tolstring(L, 1, nullptr);
auto frame = CScriptObject::GetScriptObjectByName(name, type);
if (frame) {
CCharacterCreation::SetCharCustomizeFrame(static_cast<CSimpleModel*>(frame));
}
return 0;
} }
int32_t Script_SetCharCustomizeBackground(lua_State* L) { int32_t Script_SetCharCustomizeBackground(lua_State* L) {
WHOA_UNIMPLEMENTED(0); if (!lua_isstring(L, 1)) {
return luaL_error(L, "Usage: SetCharCustomizeBackground(\"filename\")");
}
auto filename = lua_tolstring(L, 1, nullptr);
CCharacterCreation::SetCharCustomizeModel(filename);
return 0;
} }
int32_t Script_ResetCharCustomize(lua_State* L) { int32_t Script_ResetCharCustomize(lua_State*) {
WHOA_UNIMPLEMENTED(0); CCharacterCreation::ResetCharCustomizeInfo();
return 0;
} }
int32_t Script_GetNameForRace(lua_State* L) { int32_t Script_GetNameForRace(lua_State* L) {
auto raceID = CCharacterCreation::m_character.m_characterInfo.raceID; auto raceID = CCharacterCreation::m_character->m_data.m_info.raceID;
auto sexID = CCharacterCreation::m_character.m_characterInfo.sexID; auto sexID = CCharacterCreation::m_character->m_data.m_info.sexID;
auto record = g_chrRacesDB.GetRecord(raceID); auto record = g_chrRacesDB.GetRecord(raceID);
auto raceName = CGUnit_C::GetDisplayRaceNameFromRecord(record, sexID); auto raceName = CGUnit_C::GetDisplayRaceNameFromRecord(record, sexID);
if (record && raceName) { if (record && raceName) {