Fully re-implemented initialize

This commit is contained in:
David Markowitz
2023-06-12 01:29:43 -07:00
parent fc719cbb0a
commit 36c44ecc83
13 changed files with 444 additions and 260 deletions

View File

@@ -37,8 +37,9 @@
#include "eGameActivity.h"
#include "CDComponentsRegistryTable.h"
#include "CDCurrencyTableTable.h"
DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
DestroyableComponent::DestroyableComponent(Entity* parent, int32_t componentId) : Component(parent) {
m_iArmor = 0;
m_fMaxArmor = 0.0f;
m_iImagination = 0;
@@ -62,6 +63,7 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
m_MinCoins = 0;
m_MaxCoins = 0;
m_DamageReduction = 0;
m_ComponentId = componentId;
m_ImmuneToBasicAttackCount = 0;
m_ImmuneToDamageOverTimeCount = 0;
@@ -73,49 +75,71 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
m_ImmuneToQuickbuildInterruptCount = 0;
m_ImmuneToPullToPointCount = 0;
}
void DestroyableComponent::Startup() {
DestroyableComponent::~DestroyableComponent() {
}
void DestroyableComponent::Reinitialize(LOT templateID) {
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
int32_t buffComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::BUFF);
int32_t collectibleComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::COLLECTIBLE);
int32_t quickBuildComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::QUICK_BUILD);
int32_t componentID = 0;
if (collectibleComponentID > 0) componentID = collectibleComponentID;
if (quickBuildComponentID > 0) componentID = quickBuildComponentID;
if (buffComponentID > 0) componentID = buffComponentID;
CDDestructibleComponentTable* destCompTable = CDClientManager::Instance().GetTable<CDDestructibleComponentTable>();
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
if (componentID > 0) {
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
if (destCompData.size() > 0) {
SetHealth(destCompData[0].life);
SetImagination(destCompData[0].imagination);
SetArmor(destCompData[0].armor);
SetMaxHealth(destCompData[0].life);
SetMaxImagination(destCompData[0].imagination);
SetMaxArmor(destCompData[0].armor);
SetIsSmashable(destCompData[0].isSmashable);
}
} else {
void DestroyableComponent::LoadConfigData() {
SetIsSmashable(m_ParentEntity->GetVarAs<int32_t>(u"is_smashable") != 0);
}
void DestroyableComponent::LoadTemplateData() {
[[unlikely]] if (m_ParentEntity->IsPlayer()) return;
auto* destroyableComponentTable = CDClientManager::Instance().GetTable<CDDestructibleComponentTable>();
auto destroyableDataLookup = destroyableComponentTable->Query([this](CDDestructibleComponent entry) { return (entry.id == this->m_ComponentId); });
if (m_ComponentId == -1 || destroyableDataLookup.empty()) {
SetHealth(1);
SetImagination(0);
SetArmor(0);
SetMaxHealth(1);
SetMaxImagination(0);
SetMaxArmor(0);
SetIsSmashable(true);
AddFaction(-1);
AddFaction(6); //Smashables
// A race car has 60 imagination, other entities defaults to 0.
SetImagination(m_ParentEntity->HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0);
SetMaxImagination(m_ParentEntity->HasComponent(eReplicaComponentType::RACING_STATS) ? 60 : 0);
return;
}
auto destroyableData = destroyableDataLookup.at(0);
if (m_ParentEntity->HasComponent(eReplicaComponentType::RACING_STATS)) {
destroyableData.imagination = 60;
}
SetHealth(destroyableData.life);
SetImagination(destroyableData.imagination);
SetArmor(destroyableData.armor);
SetMaxHealth(destroyableData.life);
SetMaxImagination(destroyableData.imagination);
SetMaxArmor(destroyableData.armor);
SetIsSmashable(destroyableData.isSmashable);
SetLootMatrixID(destroyableData.LootMatrixIndex);
// Now get currency information
uint32_t npcMinLevel = destroyableData.level;
uint32_t currencyIndex = destroyableData.CurrencyIndex;
auto* currencyTable = CDClientManager::Instance().GetTable<CDCurrencyTableTable>();
auto currencyValues = currencyTable->Query([=](CDCurrencyTable entry) { return (entry.currencyIndex == currencyIndex && entry.npcminlevel == npcMinLevel); });
if (currencyValues.size() > 0) {
// Set the coins
SetMinCoins(currencyValues.at(0).minvalue);
SetMaxCoins(currencyValues.at(0).maxvalue);
}
AddFaction(destroyableData.faction);
std::stringstream ss(destroyableData.factionList);
std::string tokenStr;
while (std::getline(ss, tokenStr, ',')) {
int32_t factionToAdd = -2;
if (!GeneralUtils::TryParse(tokenStr, factionToAdd) || factionToAdd == -2 || factionToAdd == destroyableData.faction) continue;
AddFaction(factionToAdd);
}
}
@@ -661,9 +685,9 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
}
//check if hardcore mode is enabled
if (EntityManager::Instance()->GetHardcoreMode()) {
if (EntityManager::Instance()->GetHardcoreMode()) {
DoHardcoreModeDrops(source);
}
}
Smash(source, eKillType::VIOLENT, u"", skillID);
}
@@ -823,16 +847,16 @@ void DestroyableComponent::SetFaction(int32_t factionID, bool ignoreChecks) {
}
void DestroyableComponent::SetStatusImmunity(
const eStateChangeType state,
const bool bImmuneToBasicAttack,
const bool bImmuneToDamageOverTime,
const bool bImmuneToKnockback,
const bool bImmuneToInterrupt,
const bool bImmuneToSpeed,
const bool bImmuneToImaginationGain,
const bool bImmuneToImaginationLoss,
const bool bImmuneToQuickbuildInterrupt,
const bool bImmuneToPullToPoint) {
const eStateChangeType state,
const bool bImmuneToBasicAttack,
const bool bImmuneToDamageOverTime,
const bool bImmuneToKnockback,
const bool bImmuneToInterrupt,
const bool bImmuneToSpeed,
const bool bImmuneToImaginationGain,
const bool bImmuneToImaginationLoss,
const bool bImmuneToQuickbuildInterrupt,
const bool bImmuneToPullToPoint) {
if (state == eStateChangeType::POP) {
if (bImmuneToBasicAttack && m_ImmuneToBasicAttackCount > 0) m_ImmuneToBasicAttackCount -= 1;
@@ -845,7 +869,7 @@ void DestroyableComponent::SetStatusImmunity(
if (bImmuneToQuickbuildInterrupt && m_ImmuneToQuickbuildInterruptCount > 0) m_ImmuneToQuickbuildInterruptCount -= 1;
if (bImmuneToPullToPoint && m_ImmuneToPullToPointCount > 0) m_ImmuneToPullToPointCount -= 1;
} else if (state == eStateChangeType::PUSH){
} else if (state == eStateChangeType::PUSH) {
if (bImmuneToBasicAttack) m_ImmuneToBasicAttackCount += 1;
if (bImmuneToDamageOverTime) m_ImmuneToDamageOverTimeCount += 1;
if (bImmuneToKnockback) m_ImmuneToKnockbackCount += 1;
@@ -972,7 +996,7 @@ void DestroyableComponent::AddOnHitCallback(const std::function<void(Entity*)>&
m_OnHitCallbacks.push_back(callback);
}
void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source){
void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
//check if this is a player:
if (m_ParentEntity->IsPlayer()) {
//remove hardcore_lose_uscore_on_death_percent from the player's uscore:
@@ -990,9 +1014,9 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source){
if (inventory) {
//get the items inventory:
auto items = inventory->GetInventory(eInventoryType::ITEMS);
if (items){
if (items) {
auto itemMap = items->GetItems();
if (!itemMap.empty()){
if (!itemMap.empty()) {
for (const auto& item : itemMap) {
//drop the item:
if (!item.second) continue;

View File

@@ -21,19 +21,15 @@ class DestroyableComponent : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
DestroyableComponent(Entity* parentEntity);
~DestroyableComponent() override;
DestroyableComponent(Entity* parentEntity, int32_t componentId = -1);
void Startup() override;
void LoadConfigData() override;
void LoadTemplateData() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags);
void LoadFromXml(tinyxml2::XMLDocument* doc) override;
void UpdateXml(tinyxml2::XMLDocument* doc) override;
/**
* Initializes the component using a different LOT
* @param templateID the ID to use for initialization
*/
void Reinitialize(LOT templateID);
/**
* Sets the health of this entity. Makes sure this is serialized on the next tick and if this is a character its
* stats will also update.
@@ -458,6 +454,8 @@ public:
void DoHardcoreModeDrops(const LWOOBJID source);
private:
// The ID of this component
int32_t m_ComponentId;
/**
* Whether or not the health should be serialized
*/

View File

@@ -35,6 +35,10 @@ void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
uint32_t characterVersion;
level->QueryAttribute("cv", &characterVersion);
m_CharacterVersion = static_cast<eCharacterVersion>(characterVersion);
auto* controllablePhysicsComponent = m_ParentEntity->GetComponent<ControllablePhysicsComponent>();
if (!controllablePhysicsComponent) return;
controllablePhysicsComponent->SetSpeedMultiplier(GetSpeedBase() / 500.0f);
}
void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
@@ -68,7 +72,7 @@ void LevelProgressionComponent::HandleLevelUp() {
}
break;
case 9:
SetSpeedBase(static_cast<float>(reward->value) );
SetSpeedBase(static_cast<float>(reward->value));
controllablePhysicsComponent->SetSpeedMultiplier(GetSpeedBase() / 500.0f);
break;
case 11:
@@ -82,7 +86,7 @@ void LevelProgressionComponent::HandleLevelUp() {
if (rewardingItem) GameMessages::NotifyLevelRewards(m_ParentEntity->GetObjectID(), m_ParentEntity->GetSystemAddress(), m_Level, !rewardingItem);
}
void LevelProgressionComponent::SetRetroactiveBaseSpeed(){
void LevelProgressionComponent::SetRetroactiveBaseSpeed() {
if (m_Level >= 20) m_SpeedBase = 525.0f;
auto* controllablePhysicsComponent = m_ParentEntity->GetComponent<ControllablePhysicsComponent>();
if (controllablePhysicsComponent) controllablePhysicsComponent->SetSpeedMultiplier(m_SpeedBase / 500.0f);

View File

@@ -13,22 +13,18 @@
#include "CDComponentsRegistryTable.h"
#include "CDPhysicsComponentTable.h"
#include "CDMovementAIComponentTable.h"
std::map<LOT, float> MovementAIComponent::m_PhysicsSpeedCache = {};
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
m_Info = std::move(info);
MovementAIComponent::MovementAIComponent(Entity* parent, int32_t componentId) : Component(parent) {
m_ComponentId = componentId;
m_Done = true;
m_BaseCombatAI = nullptr;
m_BaseCombatAI = m_ParentEntity->GetComponent<BaseCombatAIComponent>();
//Try and fix the insane values:
if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius = m_Info.wanderRadius * 0.5f;
if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f;
if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed = m_Info.wanderSpeed * 0.5f;
m_BaseSpeed = GetBaseSpeed(m_ParentEntity->GetLOT());
m_NextWaypoint = GetCurrentPosition();
@@ -43,7 +39,48 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
m_LockRotation = false;
}
MovementAIComponent::~MovementAIComponent() = default;
void MovementAIComponent::Startup() {
}
void MovementAIComponent::LoadConfigData() {
bool useWanderDB = m_ParentEntity->GetVar<bool>(u"usewanderdb");
if (!useWanderDB) {
const auto wanderOverride = m_ParentEntity->GetVarAs<float>(u"wanderRadius");
if (wanderOverride != 0.0f) {
m_Info.wanderRadius = wanderOverride;
}
}
}
void MovementAIComponent::LoadTemplateData() {
if (m_ComponentId == -1) return;
auto* movementAiComponentTable = CDClientManager::Instance().GetTable<CDMovementAIComponentTable>();
auto movementEntries = movementAiComponentTable->Query([this](CDMovementAIComponent entry) {return (entry.id == this->m_ComponentId); });
if (movementEntries.empty()) return;
auto movementEntry = movementEntries.at(0);
MovementAIInfo moveInfo{};
moveInfo.movementType = movementEntry.MovementType;
moveInfo.wanderChance = movementEntry.WanderChance;
moveInfo.wanderRadius = movementEntry.WanderRadius;
moveInfo.wanderSpeed = movementEntry.WanderSpeed;
moveInfo.wanderDelayMax = movementEntry.WanderDelayMax;
moveInfo.wanderDelayMin = movementEntry.WanderDelayMin;
this->SetMoveInfo(moveInfo);
}
void MovementAIComponent::SetMoveInfo(const MovementAIInfo& info) {
m_Info = info;
//Try and fix the insane values:
if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius *= 0.5f;
if (m_Info.wanderRadius > 8.0f) m_Info.wanderRadius = 8.0f;
if (m_Info.wanderSpeed > 0.5f) m_Info.wanderSpeed *= 0.5f;
}
void MovementAIComponent::Update(const float deltaTime) {
if (m_Interrupted) {

View File

@@ -23,6 +23,10 @@ class BaseCombatAIComponent;
* Information that describes the different variables used to make an entity move around
*/
struct MovementAIInfo {
// copy assignment
MovementAIInfo& operator=(const MovementAIInfo& other) = default;
std::string movementType;
/**
@@ -59,8 +63,10 @@ class MovementAIComponent : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
~MovementAIComponent() override;
MovementAIComponent(Entity* parentEntity, int32_t componentId = -1);
void Startup() override;
void LoadTemplateData() override;
void LoadConfigData() override;
void Update(float deltaTime) override;
@@ -217,6 +223,7 @@ public:
*/
static float GetBaseSpeed(LOT lot);
void SetMoveInfo(const MovementAIInfo& value);
private:
/**
@@ -326,6 +333,8 @@ private:
* Cache of all lots and their respective speeds
*/
static std::map<LOT, float> m_PhysicsSpeedCache;
int32_t m_ComponentId;
};
#endif // MOVEMENTAICOMPONENT_H

View File

@@ -4,14 +4,13 @@
#include "ControllablePhysicsComponent.h"
#include "EntityManager.h"
#include "SimplePhysicsComponent.h"
#include "CDClientManager.h"
#include "CDProximityMonitorComponentTable.h"
const std::map<LWOOBJID, dpEntity*> ProximityMonitorComponent::m_EmptyObjectMap = {};
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int radiusSmall, int radiusLarge) : Component(parent) {
if (radiusSmall != -1 && radiusLarge != -1) {
SetProximityRadius(radiusSmall, "rocketSmall");
SetProximityRadius(radiusLarge, "rocketLarge");
}
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int32_t componentId) : Component(parent) {
m_ComponentId = componentId;
}
ProximityMonitorComponent::~ProximityMonitorComponent() {
@@ -24,6 +23,25 @@ ProximityMonitorComponent::~ProximityMonitorComponent() {
m_ProximitiesData.clear();
}
void ProximityMonitorComponent::LoadTemplateData() {
if (m_ComponentId == -1) return;
auto* proxCompTable = CDClientManager::Instance().GetTable<CDProximityMonitorComponentTable>();
auto proxCompData = proxCompTable->Query([this](CDProximityMonitorComponent entry) { return (entry.id == this->m_ComponentId); });
if (!proxCompData.empty()) {
float radiusSmall = -1.0f;
float radiusLarge = -1.0f;
auto proximitySplit = GeneralUtils::SplitString(proxCompData[0].Proximities, ',');
if (proximitySplit.size() < 2) return;
GeneralUtils::TryParse(proximitySplit.at(0), radiusSmall);
GeneralUtils::TryParse(proximitySplit.at(1), radiusLarge);
if (radiusSmall != -1.0f && radiusLarge != -1.0f) {
SetProximityRadius(radiusSmall, "rocketSmall");
SetProximityRadius(radiusLarge, "rocketLarge");
}
}
}
void ProximityMonitorComponent::SetProximityRadius(float proxRadius, const std::string& name) {
dpEntity* en = new dpEntity(m_ParentEntity->GetObjectID(), proxRadius);
en->SetPosition(m_ParentEntity->GetPosition());

View File

@@ -21,8 +21,10 @@ class ProximityMonitorComponent : public Component {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
ProximityMonitorComponent(Entity* parentEntity, int smallRadius = -1, int largeRadius = -1);
ProximityMonitorComponent(Entity* parentEntity, int32_t componentId = -1);
~ProximityMonitorComponent() override;
void LoadTemplateData() override;
void Update(float deltaTime) override;
/**
@@ -71,6 +73,8 @@ private:
* Default value for the proximity data
*/
static const std::map<LWOOBJID, dpEntity*> m_EmptyObjectMap;
int32_t m_ComponentId = 0;
};
#endif // PROXIMITYMONITORCOMPONENT_H