feat: Add isolated and simplified path to add components (#1204)

* Components: Make ComponentType inline

Prevents the next commits ODR violation

* Components: Add new components

* Entity: Add headers

inline script component ComponentType

* Components: Flip constructor argument order

Entity comes first always

* Entity: Add generic AddComponent

Allows for much easier adding of components and is error proof by not allowing the user to add more than 1 of a specific component type to an Entity.

* Entity: Migrate all component constructors

Move all to the new variadic templates AddComponent function to reduce clutter and ways the component map is modified.
The new function makes no assumptions.  Component is assumed to not exist and is checked for with operator[].  This will construct a null component which will then be newed if the component didnt exist, or it will just get the current component if it does already exist.  No new component will be allocated or constructed if the component already exists and the already existing pointer is returned instead.

* Entity: Add placement new

For the case where the component may already exist, use a placement new to construct the component again, it would be constructed again, but would not need to go through the allocator.

* Entity: Add comments on likely new code

* Tests: Fix tests

* Update Entity.cpp

* Update SGCannon.cpp

* Entity: call destructor when re-constructing

* Update Entity.cpp

Update Entity.cpp

---------

Co-authored-by: Aaron Kimbrell <aronwk.aaron@gmail.com>
This commit is contained in:
David Markowitz 2023-10-22 18:08:49 -07:00 committed by GitHub
parent 22207ea9c9
commit ae349d6b15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
59 changed files with 276 additions and 206 deletions

View File

@ -76,6 +76,10 @@
#include "eGameMasterLevel.h"
#include "eReplicaComponentType.h"
#include "eReplicaPacketType.h"
#include "ZoneControlComponent.h"
#include "RacingStatsComponent.h"
#include "CollectibleComponent.h"
#include "ItemComponent.h"
// Table includes
#include "CDComponentsRegistryTable.h"
@ -95,7 +99,6 @@ Entity::Entity(const LWOOBJID& objectID, EntityInfo info, Entity* parentEntity)
m_ParentEntity = parentEntity;
m_Character = nullptr;
m_GMLevel = eGameMasterLevel::CIVILIAN;
m_CollectibleID = 0;
m_NetworkID = 0;
m_Groups = {};
m_OwnerOverride = LWOOBJID_EMPTY;
@ -153,7 +156,7 @@ void Entity::Initialize() {
const auto triggerInfo = GetVarAsString(u"trigger_id");
if (!triggerInfo.empty()) m_Components.emplace(eReplicaComponentType::TRIGGER, new TriggerComponent(this, triggerInfo));
if (!triggerInfo.empty()) AddComponent<TriggerComponent>(triggerInfo);
/**
* Setup groups
@ -184,21 +187,17 @@ void Entity::Initialize() {
if (m_TemplateID == 14) {
const auto simplePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SIMPLE_PHYSICS);
SimplePhysicsComponent* comp = new SimplePhysicsComponent(simplePhysicsComponentID, this);
m_Components.insert(std::make_pair(eReplicaComponentType::SIMPLE_PHYSICS, comp));
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
ModelComponent* modelcomp = new ModelComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::MODEL, modelcomp));
AddComponent<ModelComponent>();
RenderComponent* render = new RenderComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render));
AddComponent<RenderComponent>();
auto destroyableComponent = new DestroyableComponent(this);
auto* destroyableComponent = AddComponent<DestroyableComponent>();
destroyableComponent->SetHealth(1);
destroyableComponent->SetMaxHealth(1.0f);
destroyableComponent->SetFaction(-1, true);
destroyableComponent->SetIsSmashable(true);
m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, destroyableComponent));
// We have all our components.
return;
}
@ -210,49 +209,46 @@ void Entity::Initialize() {
*/
if (GetParentUser()) {
auto missions = new MissionComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::MISSION, missions));
missions->LoadFromXml(m_Character->GetXMLDoc());
AddComponent<MissionComponent>()->LoadFromXml(m_Character->GetXMLDoc());
}
uint32_t petComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PET);
if (petComponentId > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::PET, new PetComponent(this, petComponentId)));
AddComponent<PetComponent>(petComponentId);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ZONE_CONTROL) > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::ZONE_CONTROL, nullptr));
AddComponent<ZoneControlComponent>();
}
uint32_t possessableComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::POSSESSABLE);
if (possessableComponentId > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::POSSESSABLE, new PossessableComponent(this, possessableComponentId)));
AddComponent<PossessableComponent>(possessableComponentId);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODULE_ASSEMBLY) > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::MODULE_ASSEMBLY, new ModuleAssemblyComponent(this)));
AddComponent<ModuleAssemblyComponent>();
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_STATS) > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::RACING_STATS, nullptr));
AddComponent<RacingStatsComponent>();
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::LUP_EXHIBIT, -1) >= 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::LUP_EXHIBIT, new LUPExhibitComponent(this)));
AddComponent<LUPExhibitComponent>();
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_CONTROL) > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::RACING_CONTROL, new RacingControlComponent(this)));
AddComponent<RacingControlComponent>();
}
const auto propertyEntranceComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_ENTRANCE);
if (propertyEntranceComponentID > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::PROPERTY_ENTRANCE,
new PropertyEntranceComponent(propertyEntranceComponentID, this)));
AddComponent<PropertyEntranceComponent>(propertyEntranceComponentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CONTROLLABLE_PHYSICS) > 0) {
ControllablePhysicsComponent* controllablePhysics = new ControllablePhysicsComponent(this);
auto* controllablePhysics = AddComponent<ControllablePhysicsComponent>();
if (m_Character) {
controllablePhysics->LoadFromXml(m_Character->GetXMLDoc());
@ -285,8 +281,6 @@ void Entity::Initialize() {
controllablePhysics->SetPosition(m_DefaultPosition);
controllablePhysics->SetRotation(m_DefaultRotation);
}
m_Components.insert(std::make_pair(eReplicaComponentType::CONTROLLABLE_PHYSICS, controllablePhysics));
}
// If an entity is marked a phantom, simple physics is made into phantom phyics.
@ -294,54 +288,42 @@ void Entity::Initialize() {
const auto simplePhysicsComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SIMPLE_PHYSICS);
if (!markedAsPhantom && simplePhysicsComponentID > 0) {
SimplePhysicsComponent* comp = new SimplePhysicsComponent(simplePhysicsComponentID, this);
m_Components.insert(std::make_pair(eReplicaComponentType::SIMPLE_PHYSICS, comp));
AddComponent<SimplePhysicsComponent>(simplePhysicsComponentID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS) > 0) {
RigidbodyPhantomPhysicsComponent* comp = new RigidbodyPhantomPhysicsComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS, comp));
AddComponent<RigidbodyPhantomPhysicsComponent>();
}
if (markedAsPhantom || compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PHANTOM_PHYSICS) > 0) {
PhantomPhysicsComponent* phantomPhysics = new PhantomPhysicsComponent(this);
phantomPhysics->SetPhysicsEffectActive(false);
m_Components.insert(std::make_pair(eReplicaComponentType::PHANTOM_PHYSICS, phantomPhysics));
AddComponent<PhantomPhysicsComponent>()->SetPhysicsEffectActive(false);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VEHICLE_PHYSICS) > 0) {
VehiclePhysicsComponent* vehiclePhysicsComponent = new VehiclePhysicsComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::VEHICLE_PHYSICS, vehiclePhysicsComponent));
auto* vehiclePhysicsComponent = AddComponent<VehiclePhysicsComponent>();
vehiclePhysicsComponent->SetPosition(m_DefaultPosition);
vehiclePhysicsComponent->SetRotation(m_DefaultRotation);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SOUND_TRIGGER, -1) != -1) {
auto* comp = new SoundTriggerComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::SOUND_TRIGGER, comp));
AddComponent<SoundTriggerComponent>();
} else if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RACING_SOUND_TRIGGER, -1) != -1) {
auto* comp = new RacingSoundTriggerComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::RACING_SOUND_TRIGGER, comp));
AddComponent<RacingSoundTriggerComponent>();
}
//Also check for the collectible id:
m_CollectibleID = GetVarAs<int32_t>(u"collectible_id");
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF) > 0) {
BuffComponent* comp = new BuffComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::BUFF, comp));
AddComponent<BuffComponent>();
}
int collectibleComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::COLLECTIBLE);
if (collectibleComponentID > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::COLLECTIBLE, nullptr));
AddComponent<CollectibleComponent>(GetVarAs<int32_t>(u"collectible_id"));
}
/**
* Multiple components require the destructible component.
*/
int buffComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUFF);
int rebuildComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD);
@ -355,7 +337,7 @@ void Entity::Initialize() {
bool isSmashable = GetVarAs<int32_t>(u"is_smashable") != 0;
if (buffComponentID > 0 || collectibleComponentID > 0 || isSmashable) {
DestroyableComponent* comp = new DestroyableComponent(this);
DestroyableComponent* comp = AddComponent<DestroyableComponent>();
if (m_Character) {
comp->LoadFromXml(m_Character->GetXMLDoc());
} else {
@ -440,36 +422,27 @@ void Entity::Initialize() {
}
}
}
m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, comp));
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::CHARACTER) > 0 || m_Character) {
// Character Component always has a possessor, level, and forced movement components
m_Components.insert(std::make_pair(eReplicaComponentType::POSSESSOR, new PossessorComponent(this)));
AddComponent<PossessorComponent>();
// load in the xml for the level
auto* levelComp = new LevelProgressionComponent(this);
levelComp->LoadFromXml(m_Character->GetXMLDoc());
m_Components.insert(std::make_pair(eReplicaComponentType::LEVEL_PROGRESSION, levelComp));
AddComponent<LevelProgressionComponent>()->LoadFromXml(m_Character->GetXMLDoc());
m_Components.insert(std::make_pair(eReplicaComponentType::PLAYER_FORCED_MOVEMENT, new PlayerForcedMovementComponent(this)));
AddComponent<PlayerForcedMovementComponent>();
CharacterComponent* charComp = new CharacterComponent(this, m_Character);
charComp->LoadFromXml(m_Character->GetXMLDoc());
m_Components.insert(std::make_pair(eReplicaComponentType::CHARACTER, charComp));
AddComponent<CharacterComponent>(m_Character)->LoadFromXml(m_Character->GetXMLDoc());
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::INVENTORY) > 0 || m_Character) {
InventoryComponent* comp = nullptr;
if (m_Character) comp = new InventoryComponent(this, m_Character->GetXMLDoc());
else comp = new InventoryComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::INVENTORY, comp));
auto* xmlDoc = m_Character ? m_Character->GetXMLDoc() : nullptr;
AddComponent<InventoryComponent>(xmlDoc);
}
// if this component exists, then we initialize it. it's value is always 0
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MULTI_ZONE_ENTRANCE, -1) != -1) {
auto comp = new MultiZoneEntranceComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::MULTI_ZONE_ENTRANCE, comp));
AddComponent<MultiZoneEntranceComponent>();
}
/**
@ -520,7 +493,7 @@ void Entity::Initialize() {
}
if (!scriptName.empty() || client || m_Character || scriptComponentID >= 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPT, new ScriptComponent(this, scriptName, true, client && scriptName.empty())));
AddComponent<ScriptComponent>(scriptName, true, client && scriptName.empty());
}
// ZoneControl script
@ -532,148 +505,137 @@ void Entity::Initialize() {
if (zoneData != nullptr) {
int zoneScriptID = zoneData->scriptID;
CDScriptComponent zoneScriptData = scriptCompTable->GetByID(zoneScriptID);
ScriptComponent* comp = new ScriptComponent(this, zoneScriptData.script_name, true);
m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPT, comp));
AddComponent<ScriptComponent>(zoneScriptData.script_name, true);
}
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SKILL, -1) != -1 || m_Character) {
SkillComponent* comp = new SkillComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::SKILL, comp));
AddComponent<SkillComponent>();
}
const auto combatAiId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BASE_COMBAT_AI);
if (combatAiId > 0) {
BaseCombatAIComponent* comp = new BaseCombatAIComponent(this, combatAiId);
m_Components.insert(std::make_pair(eReplicaComponentType::BASE_COMBAT_AI, comp));
AddComponent<BaseCombatAIComponent>(combatAiId);
}
if (int componentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::QUICK_BUILD) > 0) {
RebuildComponent* comp = new RebuildComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::QUICK_BUILD, comp));
auto* rebuildComponent = AddComponent<RebuildComponent>();
CDRebuildComponentTable* rebCompTable = CDClientManager::Instance().GetTable<CDRebuildComponentTable>();
std::vector<CDRebuildComponent> rebCompData = rebCompTable->Query([=](CDRebuildComponent entry) { return (entry.id == rebuildComponentID); });
if (rebCompData.size() > 0) {
comp->SetResetTime(rebCompData[0].reset_time);
comp->SetCompleteTime(rebCompData[0].complete_time);
comp->SetTakeImagination(rebCompData[0].take_imagination);
comp->SetInterruptible(rebCompData[0].interruptible);
comp->SetSelfActivator(rebCompData[0].self_activator);
comp->SetActivityId(rebCompData[0].activityID);
comp->SetPostImaginationCost(rebCompData[0].post_imagination_cost);
comp->SetTimeBeforeSmash(rebCompData[0].time_before_smash);
rebuildComponent->SetResetTime(rebCompData[0].reset_time);
rebuildComponent->SetCompleteTime(rebCompData[0].complete_time);
rebuildComponent->SetTakeImagination(rebCompData[0].take_imagination);
rebuildComponent->SetInterruptible(rebCompData[0].interruptible);
rebuildComponent->SetSelfActivator(rebCompData[0].self_activator);
rebuildComponent->SetActivityId(rebCompData[0].activityID);
rebuildComponent->SetPostImaginationCost(rebCompData[0].post_imagination_cost);
rebuildComponent->SetTimeBeforeSmash(rebCompData[0].time_before_smash);
const auto rebuildResetTime = GetVar<float>(u"rebuild_reset_time");
if (rebuildResetTime != 0.0f) {
comp->SetResetTime(rebuildResetTime);
rebuildComponent->SetResetTime(rebuildResetTime);
if (m_TemplateID == 9483) // Look away!
// Known bug with moving platform in FV that casues it to build at the end instead of the start.
// This extends the smash time so players can ride up the lift.
if (m_TemplateID == 9483)
{
comp->SetResetTime(comp->GetResetTime() + 25);
rebuildComponent->SetResetTime(rebuildComponent->GetResetTime() + 25);
}
}
const auto activityID = GetVar<int32_t>(u"activityID");
if (activityID > 0) {
comp->SetActivityId(activityID);
rebuildComponent->SetActivityId(activityID);
Loot::CacheMatrix(activityID);
}
const auto compTime = GetVar<float>(u"compTime");
if (compTime > 0) {
comp->SetCompleteTime(compTime);
rebuildComponent->SetCompleteTime(compTime);
}
}
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SWITCH, -1) != -1) {
SwitchComponent* comp = new SwitchComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::SWITCH, comp));
AddComponent<SwitchComponent>();
}
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::VENDOR) > 0)) {
VendorComponent* comp = new VendorComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::VENDOR, comp));
AddComponent<VendorComponent>();
} else if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::DONATION_VENDOR, -1) != -1)) {
DonationVendorComponent* comp = new DonationVendorComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::DONATION_VENDOR, comp));
AddComponent<DonationVendorComponent>();
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_VENDOR, -1) != -1) {
auto* component = new PropertyVendorComponent(this);
m_Components.insert_or_assign(eReplicaComponentType::PROPERTY_VENDOR, component);
AddComponent<PropertyVendorComponent>();
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY_MANAGEMENT, -1) != -1) {
auto* component = new PropertyManagementComponent(this);
m_Components.insert_or_assign(eReplicaComponentType::PROPERTY_MANAGEMENT, component);
AddComponent<PropertyManagementComponent>();
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BOUNCER, -1) != -1) { // you have to determine it like this because all bouncers have a componentID of 0
BouncerComponent* comp = new BouncerComponent(this);
m_Components.insert(std::make_pair(eReplicaComponentType::BOUNCER, comp));
AddComponent<BouncerComponent>();
}
int32_t renderComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RENDER);
if ((renderComponentId > 0 && m_TemplateID != 2365) || m_Character) {
RenderComponent* render = new RenderComponent(this, renderComponentId);
m_Components.insert(std::make_pair(eReplicaComponentType::RENDER, render));
AddComponent<RenderComponent>(renderComponentId);
}
if ((compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MISSION_OFFER) > 0) || m_Character) {
m_Components.insert(std::make_pair(eReplicaComponentType::MISSION_OFFER, new MissionOfferComponent(this, m_TemplateID)));
AddComponent<MissionOfferComponent>(m_TemplateID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::BUILD_BORDER, -1) != -1) {
m_Components.insert(std::make_pair(eReplicaComponentType::BUILD_BORDER, new BuildBorderComponent(this)));
AddComponent<BuildBorderComponent>();
}
// Scripted activity component
int scriptedActivityID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SCRIPTED_ACTIVITY);
if ((scriptedActivityID > 0)) {
m_Components.insert(std::make_pair(eReplicaComponentType::SCRIPTED_ACTIVITY, new ScriptedActivityComponent(this, scriptedActivityID)));
AddComponent<ScriptedActivityComponent>(scriptedActivityID);
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MODEL, -1) != -1 && !GetComponent<PetComponent>()) {
m_Components.insert(std::make_pair(eReplicaComponentType::MODEL, new ModelComponent(this)));
if (m_Components.find(eReplicaComponentType::DESTROYABLE) == m_Components.end()) {
auto destroyableComponent = new DestroyableComponent(this);
AddComponent<ModelComponent>();
if (!HasComponent(eReplicaComponentType::DESTROYABLE)) {
auto* destroyableComponent = AddComponent<DestroyableComponent>();
destroyableComponent->SetHealth(1);
destroyableComponent->SetMaxHealth(1.0f);
destroyableComponent->SetFaction(-1, true);
destroyableComponent->SetIsSmashable(true);
m_Components.insert(std::make_pair(eReplicaComponentType::DESTROYABLE, destroyableComponent));
}
}
PetComponent* petComponent;
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ITEM) > 0 && !TryGetComponent(eReplicaComponentType::PET, petComponent) && !HasComponent(eReplicaComponentType::MODEL)) {
m_Components.insert(std::make_pair(eReplicaComponentType::ITEM, nullptr));
AddComponent<ItemComponent>();
}
// Shooting gallery component
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::SHOOTING_GALLERY) > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::SHOOTING_GALLERY, new ShootingGalleryComponent(this)));
AddComponent<ShootingGalleryComponent>();
}
if (compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::PROPERTY, -1) != -1) {
m_Components.insert(std::make_pair(eReplicaComponentType::PROPERTY, new PropertyComponent(this)));
AddComponent<PropertyComponent>();
}
const int rocketId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::ROCKET_LAUNCH);
if ((rocketId > 0)) {
m_Components.insert(std::make_pair(eReplicaComponentType::ROCKET_LAUNCH, new RocketLaunchpadControlComponent(this, rocketId)));
AddComponent<RocketLaunchpadControlComponent>(rocketId);
}
const int32_t railComponentID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::RAIL_ACTIVATOR);
if (railComponentID > 0) {
m_Components.insert(std::make_pair(eReplicaComponentType::RAIL_ACTIVATOR, new RailActivatorComponent(this, railComponentID)));
AddComponent<RailActivatorComponent>(railComponentID);
}
int movementAIID = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVEMENT_AI);
@ -701,7 +663,7 @@ void Entity::Initialize() {
}
}
m_Components.insert(std::make_pair(eReplicaComponentType::MOVEMENT_AI, new MovementAIComponent(this, moveInfo)));
AddComponent<MovementAIComponent>(moveInfo);
}
} else if (petComponentId > 0 || combatAiId > 0 && GetComponent<BaseCombatAIComponent>()->GetTetherSpeed() > 0) {
MovementAIInfo moveInfo = MovementAIInfo();
@ -712,7 +674,7 @@ void Entity::Initialize() {
moveInfo.wanderDelayMax = 5;
moveInfo.wanderDelayMin = 2;
m_Components.insert(std::make_pair(eReplicaComponentType::MOVEMENT_AI, new MovementAIComponent(this, moveInfo)));
AddComponent<MovementAIComponent>(moveInfo);
}
std::string pathName = GetVarAsString(u"attached_path");
@ -722,8 +684,7 @@ void Entity::Initialize() {
if (path) {
// if we have a moving platform path, then we need a moving platform component
if (path->pathType == PathType::MovingPlatform) {
MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName);
m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat));
AddComponent<MovingPlatformComponent>(pathName);
// else if we are a movement path
} /*else if (path->pathType == PathType::Movement) {
auto movementAIcomp = GetComponent<MovementAIComponent>();
@ -737,8 +698,7 @@ void Entity::Initialize() {
// else we still need to setup moving platform if it has a moving platform comp but no path
int32_t movingPlatformComponentId = compRegistryTable->GetByIDAndType(m_TemplateID, eReplicaComponentType::MOVING_PLATFORM, -1);
if (movingPlatformComponentId >= 0) {
MovingPlatformComponent* plat = new MovingPlatformComponent(this, pathName);
m_Components.insert(std::make_pair(eReplicaComponentType::MOVING_PLATFORM, plat));
AddComponent<MovingPlatformComponent>(pathName);
}
}
@ -748,8 +708,7 @@ void Entity::Initialize() {
std::vector<CDProximityMonitorComponent> proxCompData = proxCompTable->Query([=](CDProximityMonitorComponent entry) { return (entry.id == proximityMonitorID); });
if (proxCompData.size() > 0) {
std::vector<std::string> proximityStr = GeneralUtils::SplitString(proxCompData[0].Proximities, ',');
ProximityMonitorComponent* comp = new ProximityMonitorComponent(this, std::stoi(proximityStr[0]), std::stoi(proximityStr[1]));
m_Components.insert(std::make_pair(eReplicaComponentType::PROXIMITY_MONITOR, comp));
AddComponent<ProximityMonitorComponent>(std::stoi(proximityStr[0]), std::stoi(proximityStr[1]));
}
}
@ -840,14 +799,6 @@ bool Entity::HasComponent(const eReplicaComponentType componentId) const {
return m_Components.find(componentId) != m_Components.end();
}
void Entity::AddComponent(const eReplicaComponentType componentId, Component* component) {
if (HasComponent(componentId)) {
return;
}
m_Components.insert_or_assign(componentId, component);
}
std::vector<ScriptComponent*> Entity::GetScriptComponents() {
std::vector<ScriptComponent*> comps;
for (std::pair<eReplicaComponentType, void*> p : m_Components) {
@ -876,20 +827,12 @@ void Entity::Unsubscribe(LWOOBJID scriptObjId, const std::string& notificationNa
}
void Entity::SetProximityRadius(float proxRadius, std::string name) {
ProximityMonitorComponent* proxMon = GetComponent<ProximityMonitorComponent>();
if (!proxMon) {
proxMon = new ProximityMonitorComponent(this);
m_Components.insert_or_assign(eReplicaComponentType::PROXIMITY_MONITOR, proxMon);
}
ProximityMonitorComponent* proxMon = AddComponent<ProximityMonitorComponent>();
proxMon->SetProximityRadius(proxRadius, name);
}
void Entity::SetProximityRadius(dpEntity* entity, std::string name) {
ProximityMonitorComponent* proxMon = GetComponent<ProximityMonitorComponent>();
if (!proxMon) {
proxMon = new ProximityMonitorComponent(this);
m_Components.insert_or_assign(eReplicaComponentType::PROXIMITY_MONITOR, proxMon);
}
ProximityMonitorComponent* proxMon = AddComponent<ProximityMonitorComponent>();
proxMon->SetProximityRadius(entity, name);
}
@ -1104,13 +1047,14 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
destroyableSerialized = true;
}
if (HasComponent(eReplicaComponentType::COLLECTIBLE)) {
CollectibleComponent* collectibleComponent;
if (TryGetComponent(eReplicaComponentType::COLLECTIBLE, collectibleComponent)) {
DestroyableComponent* destroyableComponent;
if (TryGetComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent) && !destroyableSerialized) {
destroyableComponent->Serialize(outBitStream, bIsInitialUpdate);
}
destroyableSerialized = true;
outBitStream->Write(m_CollectibleID); // Collectable component
collectibleComponent->Serialize(outBitStream, bIsInitialUpdate);
}
PetComponent* petComponent;
@ -1148,8 +1092,9 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
characterComponent->Serialize(outBitStream, bIsInitialUpdate);
}
if (HasComponent(eReplicaComponentType::ITEM)) {
outBitStream->Write0();
ItemComponent* itemComponent;
if (TryGetComponent(eReplicaComponentType::ITEM, itemComponent)) {
itemComponent->Serialize(outBitStream, bIsInitialUpdate);
}
InventoryComponent* inventoryComponent;
@ -1245,8 +1190,9 @@ void Entity::WriteComponents(RakNet::BitStream* outBitStream, eReplicaPacketType
}
}
if (HasComponent(eReplicaComponentType::ZONE_CONTROL)) {
outBitStream->Write<uint32_t>(0x40000000);
ZoneControlComponent* zoneControlComponent;
if (TryGetComponent(eReplicaComponentType::ZONE_CONTROL, zoneControlComponent)) {
zoneControlComponent->Serialize(outBitStream, bIsInitialUpdate);
}
// BBB Component, unused currently
@ -2102,3 +2048,8 @@ void Entity::RetroactiveVaultSize() {
modelVault->SetSize(itemsVault->GetSize());
}
uint8_t Entity::GetCollectibleID() const {
auto* collectible = GetComponent<CollectibleComponent>();
return collectible ? collectible->GetCollectibleId() : 0;
}

View File

@ -66,7 +66,7 @@ public:
eGameMasterLevel GetGMLevel() const { return m_GMLevel; }
uint8_t GetCollectibleID() const { return uint8_t(m_CollectibleID); }
uint8_t GetCollectibleID() const;
Entity* GetParentEntity() const { return m_ParentEntity; }
@ -274,6 +274,9 @@ public:
template<typename T>
T GetVarAs(const std::u16string& name) const;
template<typename ComponentType, typename... VaArgs>
ComponentType* AddComponent(VaArgs... args);
/**
* Get the LDF data.
*/
@ -501,3 +504,36 @@ T Entity::GetNetworkVar(const std::u16string& name) {
return LDFData<T>::Default;
}
/**
* @brief Adds a component of type ComponentType to this entity and forwards the arguments to the constructor.
*
* @tparam ComponentType The component class type to add. Must derive from Component.
* @tparam VaArgs The argument types to forward to the constructor.
* @param args The arguments to forward to the constructor. The first argument passed to the ComponentType constructor will be this entity.
* @return ComponentType* The added component. Will never return null.
*/
template<typename ComponentType, typename... VaArgs>
inline ComponentType* Entity::AddComponent(VaArgs... args) {
static_assert(std::is_base_of_v<Component, ComponentType>, "ComponentType must be a Component");
// Get the component if it already exists, or default construct a nullptr
auto*& componentToReturn = m_Components[ComponentType::ComponentType];
// If it doesn't exist, create it and forward the arguments to the constructor
if (!componentToReturn) {
componentToReturn = new ComponentType(this, std::forward<VaArgs>(args)...);
} else {
// In this case the block is already allocated and ready for use
// so we use a placement new to construct the component again as was requested by the caller.
// Placement new means we already have memory allocated for the object, so this just calls its constructor again.
// This is useful for when we want to create a new object in the same memory location as an old one.
componentToReturn->~Component();
new(componentToReturn) ComponentType(this, std::forward<VaArgs>(args)...);
}
// Finally return the created or already existing component.
// Because of the assert above, this should always be a ComponentType* but I need a way to guarantee the map cannot be modifed outside this function
// To allow a static cast here instead of a dynamic one.
return dynamic_cast<ComponentType*>(componentToReturn);
}

View File

@ -47,7 +47,7 @@ struct AiSkillEntry
*/
class BaseCombatAIComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI;
BaseCombatAIComponent(Entity* parentEntity, uint32_t id);
~BaseCombatAIComponent() override;

View File

@ -12,7 +12,7 @@
*/
class BouncerComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER;
BouncerComponent(Entity* parentEntity);
~BouncerComponent() override;

View File

@ -42,7 +42,7 @@ struct Buff
*/
class BuffComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::BUFF;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BUFF;
explicit BuffComponent(Entity* parent);

View File

@ -16,7 +16,7 @@
*/
class BuildBorderComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::BUILD_BORDER;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::BUILD_BORDER;
BuildBorderComponent(Entity* parent);
~BuildBorderComponent() override;

View File

@ -3,11 +3,13 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
"BuffComponent.cpp"
"BuildBorderComponent.cpp"
"CharacterComponent.cpp"
"CollectibleComponent.cpp"
"Component.cpp"
"ControllablePhysicsComponent.cpp"
"DestroyableComponent.cpp"
"DonationVendorComponent.cpp"
"InventoryComponent.cpp"
"ItemComponent.cpp"
"LevelProgressionComponent.cpp"
"LUPExhibitComponent.cpp"
"MissionComponent.cpp"
@ -42,4 +44,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
"SwitchComponent.cpp"
"TriggerComponent.cpp"
"VehiclePhysicsComponent.cpp"
"VendorComponent.cpp" PARENT_SCOPE)
"VendorComponent.cpp"
"ZoneControlComponent.cpp"
PARENT_SCOPE
)

View File

@ -62,7 +62,7 @@ enum StatisticID {
*/
class CharacterComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER;
CharacterComponent(Entity* parent, Character* character);
~CharacterComponent() override;

View File

@ -0,0 +1,5 @@
#include "CollectibleComponent.h"
void CollectibleComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
outBitStream->Write(GetCollectibleId());
}

View File

@ -0,0 +1,18 @@
#ifndef __COLLECTIBLECOMPONENT__H__
#define __COLLECTIBLECOMPONENT__H__
#include "Component.h"
#include "eReplicaComponentType.h"
class CollectibleComponent : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::COLLECTIBLE;
CollectibleComponent(Entity* parentEntity, int32_t collectibleId) : Component(parentEntity), m_CollectibleId(collectibleId) {}
int16_t GetCollectibleId() const { return m_CollectibleId; }
void Serialize(RakNet::BitStream* outBitStream, bool isConstruction) override;
private:
int16_t m_CollectibleId = 0;
};
#endif //!__COLLECTIBLECOMPONENT__H__

View File

@ -21,7 +21,7 @@ enum class eStateChangeType : uint32_t;
*/
class ControllablePhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
ControllablePhysicsComponent(Entity* entity);
~ControllablePhysicsComponent() override;

View File

@ -19,7 +19,7 @@ enum class eStateChangeType : uint32_t;
*/
class DestroyableComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
DestroyableComponent(Entity* parentEntity);
~DestroyableComponent() override;

View File

@ -38,7 +38,7 @@ enum class eItemType : int32_t;
class InventoryComponent : public Component
{
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
void Update(float deltaTime) override;

View File

@ -0,0 +1,5 @@
#include "ItemComponent.h"
void ItemComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
outBitStream->Write0();
}

View File

@ -0,0 +1,16 @@
#ifndef __ITEMCOMPONENT__H__
#define __ITEMCOMPONENT__H__
#include "Component.h"
#include "eReplicaComponentType.h"
class ItemComponent : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ITEM;
ItemComponent(Entity* entity) : Component(entity) {}
void Serialize(RakNet::BitStream* bitStream, bool isConstruction) override;
};
#endif //!__ITEMCOMPONENT__H__

View File

@ -11,7 +11,7 @@
class LUPExhibitComponent : public Component
{
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::EXHIBIT;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::EXHIBIT;
LUPExhibitComponent(Entity* parent);
~LUPExhibitComponent();

View File

@ -13,7 +13,7 @@
class LevelProgressionComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION;
/**
* Constructor for this component

View File

@ -27,7 +27,7 @@ class AchievementCacheKey;
class MissionComponent : public Component
{
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION;
explicit MissionComponent(Entity* parent);
~MissionComponent() override;

View File

@ -61,7 +61,7 @@ private:
*/
class MissionOfferComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
MissionOfferComponent(Entity* parent, LOT parentLot);
~MissionOfferComponent() override;

View File

@ -13,7 +13,7 @@ class Entity;
*/
class ModelComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::MODEL;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MODEL;
ModelComponent(Entity* parent);

View File

@ -12,7 +12,7 @@
*/
class ModuleAssemblyComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
ModuleAssemblyComponent(Entity* parent);
~ModuleAssemblyComponent() override;

View File

@ -57,7 +57,7 @@ struct MovementAIInfo {
*/
class MovementAIComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);

View File

@ -106,7 +106,7 @@ public:
*/
class MovingPlatformComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM;
MovingPlatformComponent(Entity* parent, const std::string& pathName);
~MovingPlatformComponent() override;

View File

@ -10,7 +10,7 @@
*/
class MultiZoneEntranceComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::MULTI_ZONE_ENTRANCE;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MULTI_ZONE_ENTRANCE;
/**
* Constructor for this component, builds the m_LUPWorlds vector

View File

@ -21,7 +21,7 @@ enum class PetAbilityType
class PetComponent : public Component
{
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PET;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PET;
explicit PetComponent(Entity* parentEntity, uint32_t componentId);
~PetComponent() override;

View File

@ -27,7 +27,7 @@ enum class ePhysicsEffectType : uint32_t ;
*/
class PhantomPhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
PhantomPhysicsComponent(Entity* parent);
~PhantomPhysicsComponent() override;

View File

@ -10,7 +10,7 @@
*/
class PlayerForcedMovementComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PLAYER_FORCED_MOVEMENT;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PLAYER_FORCED_MOVEMENT;
/**
* Constructor for this component

View File

@ -14,7 +14,7 @@
*/
class PossessableComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE;
PossessableComponent(Entity* parentEntity, uint32_t componentId);

View File

@ -18,7 +18,7 @@ enum class ePossessionType : uint8_t {
*/
class PossessorComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR;
PossessorComponent(Entity* parent);
~PossessorComponent() override;

View File

@ -22,7 +22,7 @@ struct PropertyState {
*/
class PropertyComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY;
explicit PropertyComponent(Entity* parentEntity);
~PropertyComponent() override;
[[nodiscard]] PropertyState* GetPropertyState() const { return m_PropertyState; };

View File

@ -15,7 +15,7 @@
#include "eObjectBits.h"
#include "eGameMasterLevel.h"
PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entity* parent) : Component(parent) {
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) {
this->propertyQueries = {};
auto table = CDClientManager::Instance().GetTable<CDPropertyEntranceComponentTable>();

View File

@ -13,8 +13,8 @@
*/
class PropertyEntranceComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE;
explicit PropertyEntranceComponent(uint32_t componentID, Entity* parent);
explicit PropertyEntranceComponent(Entity* parent, uint32_t componentID);
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE;
/**
* Handles an OnUse request for some other entity, rendering the property browse menu

View File

@ -32,7 +32,7 @@ enum class PropertyPrivacyOption
class PropertyManagementComponent : public Component
{
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT;
PropertyManagementComponent(Entity* parent);
static PropertyManagementComponent* Instance();

View File

@ -10,7 +10,7 @@
class PropertyVendorComponent : public Component
{
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR;
explicit PropertyVendorComponent(Entity* parent);
/**

View File

@ -19,7 +19,7 @@
*/
class ProximityMonitorComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
ProximityMonitorComponent(Entity* parentEntity, int smallRadius = -1, int largeRadius = -1);
~ProximityMonitorComponent() override;

View File

@ -105,7 +105,7 @@ struct RacingPlayerInfo {
*/
class RacingControlComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL;
RacingControlComponent(Entity* parentEntity);
~RacingControlComponent();

View File

@ -0,0 +1,14 @@
#ifndef __RACINGSTATSCOMPONENT__H__
#define __RACINGSTATSCOMPONENT__H__
#include "Component.h"
#include "eReplicaComponentType.h"
class RacingStatsComponent final : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_STATS;
RacingStatsComponent(Entity* parent) : Component(parent) {}
};
#endif //!__RACINGSTATSCOMPONENT__H__

View File

@ -15,7 +15,7 @@ public:
explicit RailActivatorComponent(Entity* parent, int32_t componentID);
~RailActivatorComponent() override;
static const eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR;
/**
* Handles the OnUse event from some entity, initiates the rail movement

View File

@ -22,7 +22,7 @@ enum class eQuickBuildFailReason : uint32_t;
*/
class RebuildComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD;
RebuildComponent(Entity* entity);
~RebuildComponent() override;

View File

@ -56,7 +56,7 @@ struct Effect {
*/
class RenderComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::RENDER;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RENDER;
RenderComponent(Entity* entity, int32_t componentId = -1);
~RenderComponent() override;

View File

@ -19,7 +19,7 @@
*/
class RigidbodyPhantomPhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
RigidbodyPhantomPhysicsComponent(Entity* parent);

View File

@ -18,7 +18,7 @@ class PreconditionExpression;
*/
class RocketLaunchpadControlComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH;
RocketLaunchpadControlComponent(Entity* parent, int rocketId);
~RocketLaunchpadControlComponent() override;

View File

@ -156,7 +156,7 @@ struct ActivityPlayer {
*/
class ScriptedActivityComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY;
ScriptedActivityComponent(Entity* parent, int activityID);
~ScriptedActivityComponent() override;

View File

@ -73,7 +73,7 @@ struct StaticShootingGalleryParams {
*/
class ShootingGalleryComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY;
explicit ShootingGalleryComponent(Entity* parent);
~ShootingGalleryComponent();

View File

@ -13,7 +13,7 @@
#include "Entity.h"
SimplePhysicsComponent::SimplePhysicsComponent(uint32_t componentID, Entity* parent) : PhysicsComponent(parent) {
SimplePhysicsComponent::SimplePhysicsComponent(Entity* parent, uint32_t componentID) : PhysicsComponent(parent) {
m_Position = m_Parent->GetDefaultPosition();
m_Rotation = m_Parent->GetDefaultRotation();

View File

@ -28,9 +28,9 @@ enum class eClimbableType : int32_t {
*/
class SimplePhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS;
SimplePhysicsComponent(uint32_t componentID, Entity* parent);
SimplePhysicsComponent(Entity* parent, uint32_t componentID);
~SimplePhysicsComponent() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;

View File

@ -59,7 +59,7 @@ struct SkillExecutionResult {
*/
class SkillComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::SKILL;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SKILL;
explicit SkillComponent(Entity* parent);
~SkillComponent() override;

View File

@ -58,7 +58,7 @@ struct MixerProgram{
class SoundTriggerComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER;
explicit SoundTriggerComponent(Entity* parent);
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate) override;
void ActivateMusicCue(const std::string& name, float bordemTime = -1.0);

View File

@ -16,7 +16,7 @@
*/
class SwitchComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH;
SwitchComponent(Entity* parent);
~SwitchComponent() override;

View File

@ -7,7 +7,7 @@
class TriggerComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::TRIGGER;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::TRIGGER;
explicit TriggerComponent(Entity* parent, const std::string triggerInfo);

View File

@ -28,7 +28,7 @@ struct RemoteInputInfo {
*/
class VehiclePhysicsComponent : public PhysicsComponent {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::VEHICLE_PHYSICS;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::VEHICLE_PHYSICS;
VehiclePhysicsComponent(Entity* parentEntity);

View File

@ -0,0 +1,5 @@
#include "ZoneControlComponent.h"
void ZoneControlComponent::Serialize(RakNet::BitStream* outBitStream, bool isConstruction) {
outBitStream->Write<uint32_t>(0x40000000);
}

View File

@ -0,0 +1,15 @@
#ifndef __ZONECONTROLCOMPONENT__H__
#define __ZONECONTROLCOMPONENT__H__
#include "Component.h"
#include "eReplicaComponentType.h"
class ZoneControlComponent final : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::ZONE_CONTROL;
ZoneControlComponent(Entity* parent) : Component(parent) {}
void Serialize(RakNet::BitStream* outBitStream, bool isConstruction);
};
#endif //!__ZONECONTROLCOMPONENT__H__

View File

@ -15,8 +15,7 @@ void NtFactionSpyServer::OnStartup(Entity* self) {
// Set the proximity to sense later
auto* proximityMonitor = self->GetComponent<ProximityMonitorComponent>();
if (proximityMonitor == nullptr) {
proximityMonitor = new ProximityMonitorComponent(self, -1, -1);
self->AddComponent(eReplicaComponentType::PROXIMITY_MONITOR, proximityMonitor);
self->AddComponent<ProximityMonitorComponent>(-1, -1);
}
proximityMonitor->SetProximityRadius(self->GetVar<float_t>(m_SpyProximityVariable), m_ProximityName);

View File

@ -19,7 +19,7 @@ class Entity;
*/
class ScriptComponent : public Component {
public:
static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPT;
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPT;
ScriptComponent(Entity* parent, std::string scriptName, bool serialized, bool client = false);
~ScriptComponent() override;

View File

@ -12,6 +12,5 @@ void AgStromlingProperty::OnStartup(Entity* self) {
4
};
auto* movementAIComponent = new MovementAIComponent(self, movementInfo);
self->AddComponent(eReplicaComponentType::MOVEMENT_AI, movementAIComponent);
self->AddComponent<MovementAIComponent>(movementInfo);
}

View File

@ -302,9 +302,7 @@ void SGCannon::DoSpawnTimerFunc(Entity* self, const std::string& name) {
auto* enemy = Game::entityManager->CreateEntity(info, nullptr, self);
Game::entityManager->ConstructEntity(enemy);
auto* movementAI = new MovementAIComponent(enemy, {});
enemy->AddComponent(eReplicaComponentType::MOVEMENT_AI, movementAI);
auto* movementAI = enemy->AddComponent<MovementAIComponent>(MovementAIInfo{});
movementAI->SetMaxSpeed(toSpawn.initialSpeed);
movementAI->SetCurrentSpeed(toSpawn.initialSpeed);

View File

@ -16,8 +16,7 @@ protected:
void SetUp() override {
SetUpDependencies();
baseEntity = new Entity(15, GameDependenciesTest::info);
destroyableComponent = new DestroyableComponent(baseEntity);
baseEntity->AddComponent(eReplicaComponentType::DESTROYABLE, destroyableComponent);
destroyableComponent = baseEntity->AddComponent<DestroyableComponent>();
// Initialize some values to be not default
destroyableComponent->SetMaxHealth(12345.0f);
destroyableComponent->SetHealth(23);
@ -37,6 +36,14 @@ protected:
}
};
TEST_F(DestroyableTest, PlacementNewAddComponentTest) {
ASSERT_NE(destroyableComponent, nullptr);
ASSERT_EQ(destroyableComponent->GetArmor(), 7);
baseEntity->AddComponent<DestroyableComponent>();
ASSERT_NE(baseEntity->GetComponent<DestroyableComponent>(), nullptr);
ASSERT_EQ(destroyableComponent->GetArmor(), 0);
}
/**
* Test Construction of a DestroyableComponent
*/
@ -318,9 +325,7 @@ TEST_F(DestroyableTest, DestroyableComponentFactionTest) {
TEST_F(DestroyableTest, DestroyableComponentValiditiyTest) {
auto* enemyEntity = new Entity(19, info);
auto* enemyDestroyableComponent = new DestroyableComponent(enemyEntity);
enemyEntity->AddComponent(eReplicaComponentType::DESTROYABLE, enemyDestroyableComponent);
enemyDestroyableComponent->AddFactionNoLookup(16);
enemyEntity->AddComponent<DestroyableComponent>()->AddFactionNoLookup(16);
destroyableComponent->AddEnemyFaction(16);
EXPECT_TRUE(destroyableComponent->IsEnemy(enemyEntity));
EXPECT_FALSE(destroyableComponent->IsFriend(enemyEntity));

View File

@ -15,8 +15,7 @@ protected:
void SetUp() override {
SetUpDependencies();
baseEntity = std::make_unique<Entity>(15, GameDependenciesTest::info);
simplePhysicsComponent = new SimplePhysicsComponent(1, baseEntity.get());
baseEntity->AddComponent(SimplePhysicsComponent::ComponentType, simplePhysicsComponent);
simplePhysicsComponent = baseEntity->AddComponent<SimplePhysicsComponent>(1);
simplePhysicsComponent->SetClimbableType(eClimbableType::CLIMBABLE_TYPE_WALL);
simplePhysicsComponent->SetPosition(NiPoint3(1.0f, 2.0f, 3.0f));
simplePhysicsComponent->SetRotation(NiQuaternion(1.0f, 2.0f, 3.0f, 4.0f));