feat(entity): a character's components as the client makes them

LWOCharacterComponent::Factory makes possession control, mount control, pet
creator, level progression and forced movement, then the character, all with
componentID -1; DLU now makes the same set in the same order (mount control
and pet creator are new, empty). The ghost is added after the component walk,
where the client adds it, for a character with physics. Nothing sent changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-10-01 15:30:20 -05:00
parent b0dd69cf0d
commit 8f09121ad4
3 changed files with 52 additions and 10 deletions

View File

@@ -95,6 +95,8 @@
#include "GateRushComponent.h"
#include "FactionTriggerComponent.h"
#include "RocketLandingComponent.h"
#include "MountControlComponent.h"
#include "PetCreatorComponent.h"
#include "HFLightDirectionGadgetComponent.h"
#include "SpawnerComponent.h"
#include "PathfindingComponent.h"
@@ -437,18 +439,17 @@ void Entity::Initialize() {
case eReplicaComponentType::CHARACTER: {
const auto characterID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CHARACTER);
if (characterID > 0 || m_Character) {
// Character Component always has a possessor, level, and forced movement components
AddComponent<PossessorComponent>(characterID);
// load in the xml for the level
AddComponent<LevelProgressionComponent>(characterID)->LoadFromSaveData(m_Character->GetXMLDoc());
AddComponent<PlayerForcedMovementComponent>(characterID);
// LWOCharacterComponent::Factory (0x0104db40): possession control, mount control, pet creator, level
// progression and forced movement, then the character, all componentID -1
AddComponent<PossessorComponent>(-1);
AddComponent<MountControlComponent>(-1);
AddComponent<PetCreatorComponent>(-1);
AddComponent<LevelProgressionComponent>(-1)->LoadFromSaveData(m_Character->GetXMLDoc());
AddComponent<PlayerForcedMovementComponent>(-1);
auto& systemAddress = m_Character->GetParentUser() ? m_Character->GetParentUser()->GetSystemAddress() : UNASSIGNED_SYSTEM_ADDRESS;
AddComponent<CharacterComponent>(characterID, m_Character, systemAddress)->LoadFromSaveData(m_Character->GetXMLDoc());
AddComponent<CharacterComponent>(-1, m_Character, systemAddress)->LoadFromSaveData(m_Character->GetXMLDoc());
AddComponent<GhostComponent>(characterID)->LoadFromSaveData(m_Character->GetXMLDoc());
}
break;
}
@@ -1044,8 +1045,13 @@ void Entity::Initialize() {
}
/**
* Added after the walk, as the client does (DoObjectComponentLoad): the trigger from the level config
* Added after the walk, as the client does (DoObjectComponentLoad): the ghost of a character (LWOGhostComponent's
* allocator 0x0101c010 makes one for characters with physics; level and plain spawned objects get none), then the
* trigger from the level config
*/
if (m_Character && HasComponent(eReplicaComponentType::CONTROLLABLE_PHYSICS)) {
AddComponent<GhostComponent>(-1)->LoadFromSaveData(m_Character->GetXMLDoc());
}
const auto triggerInfo = GetVarAsString(u"trigger_id");
if (!triggerInfo.empty()) AddComponent<TriggerComponent>(-1, triggerInfo);

View File

@@ -0,0 +1,18 @@
#ifndef MOUNTCONTROLCOMPONENT_H
#define MOUNTCONTROLCOMPONENT_H
#include "Component.h"
#include "eReplicaComponentType.h"
/**
* Mount control (111): the character's riding of mounts, as the client's LWOMountControlComponent: the client makes it (componentID -1) with every character
* (LWOCharacterComponent::Factory). Nothing of it is sent or done on the server yet.
*/
class MountControlComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MOUNT_CONTROL;
MountControlComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {}
};
#endif // MOUNTCONTROLCOMPONENT_H

View File

@@ -0,0 +1,18 @@
#ifndef PETCREATORCOMPONENT_H
#define PETCREATORCOMPONENT_H
#include "Component.h"
#include "eReplicaComponentType.h"
/**
* Pet creator (37): the character's taming of pets, as the client's LWOPetCreatorComponent: the client makes it (componentID -1) with every character
* (LWOCharacterComponent::Factory). Nothing of it is sent or done on the server yet.
*/
class PetCreatorComponent final : public Component {
public:
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PET_CREATOR;
PetCreatorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {}
};
#endif // PETCREATORCOMPONENT_H