mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-02-27 05:09:49 +00:00
Merge branch 'main' into npc-pathing
This commit is contained in:
45
dGame/dComponents/AchievementCacheKey.h
Normal file
45
dGame/dComponents/AchievementCacheKey.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "eMissionTaskType.h"
|
||||
|
||||
#ifndef __ACHIEVEMENTCACHEKEY__H__
|
||||
#define __ACHIEVEMENTCACHEKEY__H__
|
||||
|
||||
class AchievementCacheKey {
|
||||
public:
|
||||
AchievementCacheKey() {
|
||||
targets = "";
|
||||
value = 0;
|
||||
type = eMissionTaskType::UNKNOWN;
|
||||
};
|
||||
|
||||
bool operator==(const AchievementCacheKey& point) const {
|
||||
return this->targets == point.targets && this->value == point.value && this->type == point.type;
|
||||
};
|
||||
void SetTargets(const std::string value) { this->targets = value; };
|
||||
void SetValue(uint32_t value) { this->value = value; };
|
||||
void SetType(eMissionTaskType value) { this->type = value; };
|
||||
|
||||
std::string GetTargets() const { return this->targets; };
|
||||
uint32_t GetValue() const { return this->value; };
|
||||
eMissionTaskType GetType() const { return this->type; };
|
||||
private:
|
||||
std::string targets;
|
||||
uint32_t value;
|
||||
eMissionTaskType type;
|
||||
|
||||
};
|
||||
|
||||
// Specialization of hash for the above class
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<AchievementCacheKey> {
|
||||
size_t operator()(const AchievementCacheKey& key) const {
|
||||
size_t hash = 0;
|
||||
GeneralUtils::hash_combine(hash, key.GetType());
|
||||
GeneralUtils::hash_combine(hash, key.GetValue());
|
||||
GeneralUtils::hash_combine(hash, key.GetTargets());
|
||||
return hash;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
#endif //!__ACHIEVEMENTCACHEKEY__H__
|
||||
@@ -22,10 +22,13 @@
|
||||
#include "SkillComponent.h"
|
||||
#include "RebuildComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "Metrics.hpp"
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDPhysicsComponentTable.h"
|
||||
|
||||
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id) : Component(parent) {
|
||||
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id): Component(parent) {
|
||||
m_Target = LWOOBJID_EMPTY;
|
||||
m_State = AiState::spawn;
|
||||
SetAiState(AiState::spawn);
|
||||
m_Timer = 1.0f;
|
||||
m_StartPosition = parent->GetPosition();
|
||||
m_MovementAI = nullptr;
|
||||
@@ -104,10 +107,10 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
|
||||
|
||||
int32_t collisionGroup = (COLLISION_GROUP_DYNAMIC | COLLISION_GROUP_ENEMY);
|
||||
|
||||
CDComponentsRegistryTable* componentRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
auto componentID = componentRegistryTable->GetByIDAndType(parent->GetLOT(), COMPONENT_TYPE_CONTROLLABLE_PHYSICS);
|
||||
CDComponentsRegistryTable* componentRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
auto componentID = componentRegistryTable->GetByIDAndType(parent->GetLOT(), eReplicaComponentType::CONTROLLABLE_PHYSICS);
|
||||
|
||||
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::Instance()->GetTable<CDPhysicsComponentTable>("PhysicsComponent");
|
||||
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::Instance().GetTable<CDPhysicsComponentTable>();
|
||||
|
||||
if (physicsComponentTable != nullptr) {
|
||||
auto* info = physicsComponentTable->GetByID(componentID);
|
||||
@@ -179,7 +182,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
|
||||
|
||||
if (m_Disabled || m_Parent->GetIsDead())
|
||||
return;
|
||||
|
||||
bool stunnedThisFrame = m_Stunned;
|
||||
CalculateCombat(deltaTime); // Putting this here for now
|
||||
|
||||
if (m_StartPosition == NiPoint3::ZERO) {
|
||||
@@ -192,7 +195,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Stunned) {
|
||||
if (stunnedThisFrame) {
|
||||
m_MovementAI->Stop();
|
||||
|
||||
return;
|
||||
@@ -206,7 +209,7 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
|
||||
switch (m_State) {
|
||||
case AiState::spawn:
|
||||
Stun(2.0f);
|
||||
m_State = AiState::idle;
|
||||
SetAiState(AiState::idle);
|
||||
break;
|
||||
|
||||
case AiState::idle:
|
||||
@@ -228,6 +231,18 @@ void BaseCombatAIComponent::Update(const float deltaTime) {
|
||||
|
||||
|
||||
void BaseCombatAIComponent::CalculateCombat(const float deltaTime) {
|
||||
bool hasSkillToCast = false;
|
||||
for (auto& entry : m_SkillEntries) {
|
||||
if (entry.cooldown > 0.0f) {
|
||||
entry.cooldown -= deltaTime;
|
||||
} else {
|
||||
hasSkillToCast = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool hadRemainingDowntime = m_SkillTime > 0.0f;
|
||||
if (m_SkillTime > 0.0f) m_SkillTime -= deltaTime;
|
||||
|
||||
auto* rebuild = m_Parent->GetComponent<RebuildComponent>();
|
||||
|
||||
if (rebuild != nullptr) {
|
||||
@@ -248,19 +263,17 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) {
|
||||
|
||||
if (m_Disabled) return;
|
||||
|
||||
if (m_StunTime > 0.0f) {
|
||||
if (m_Stunned) {
|
||||
m_StunTime -= deltaTime;
|
||||
|
||||
if (m_StunTime > 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_StunTime = 0.0f;
|
||||
m_Stunned = false;
|
||||
}
|
||||
|
||||
if (m_Stunned) {
|
||||
return;
|
||||
}
|
||||
if (m_Stunned || hadRemainingDowntime) return;
|
||||
|
||||
auto newTarget = FindTarget();
|
||||
|
||||
@@ -320,41 +333,19 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) {
|
||||
m_Timer = 0;
|
||||
}
|
||||
|
||||
m_State = AiState::aggro;
|
||||
SetAiState(AiState::aggro);
|
||||
} else {
|
||||
m_State = AiState::idle;
|
||||
SetAiState(AiState::idle);
|
||||
}
|
||||
|
||||
for (auto i = 0; i < m_SkillEntries.size(); ++i) {
|
||||
auto entry = m_SkillEntries.at(i);
|
||||
|
||||
if (entry.cooldown > 0) {
|
||||
entry.cooldown -= deltaTime;
|
||||
|
||||
m_SkillEntries[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_SkillTime > 0) {
|
||||
m_SkillTime -= deltaTime;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_Downtime > 0) {
|
||||
m_Downtime -= deltaTime;
|
||||
|
||||
return;
|
||||
}
|
||||
if (!hasSkillToCast) return;
|
||||
|
||||
if (m_Target == LWOOBJID_EMPTY) {
|
||||
m_State = AiState::idle;
|
||||
SetAiState(AiState::idle);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_Downtime = 0.5f;
|
||||
|
||||
auto* target = GetTargetEntity();
|
||||
|
||||
if (target != nullptr) {
|
||||
@@ -375,7 +366,7 @@ void BaseCombatAIComponent::CalculateCombat(const float deltaTime) {
|
||||
m_MovementAI->Stop();
|
||||
}
|
||||
|
||||
m_State = AiState::aggro;
|
||||
SetAiState(AiState::aggro);
|
||||
|
||||
m_Timer = 0;
|
||||
|
||||
@@ -532,11 +523,20 @@ bool BaseCombatAIComponent::IsMech() {
|
||||
|
||||
|
||||
void BaseCombatAIComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||
outBitStream->Write1();
|
||||
outBitStream->Write(uint32_t(m_State));
|
||||
outBitStream->Write(m_Target);
|
||||
outBitStream->Write(m_DirtyStateOrTarget || bIsInitialUpdate);
|
||||
if (m_DirtyStateOrTarget || bIsInitialUpdate) {
|
||||
outBitStream->Write(uint32_t(m_State));
|
||||
outBitStream->Write(m_Target);
|
||||
m_DirtyStateOrTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseCombatAIComponent::SetAiState(AiState newState) {
|
||||
if (newState == this->m_State) return;
|
||||
this->m_State = newState;
|
||||
m_DirtyStateOrTarget = true;
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const {
|
||||
auto* entity = EntityManager::Instance()->GetEntity(target);
|
||||
@@ -585,7 +585,10 @@ bool BaseCombatAIComponent::IsEnemy(LWOOBJID target) const {
|
||||
}
|
||||
|
||||
void BaseCombatAIComponent::SetTarget(const LWOOBJID target) {
|
||||
if (this->m_Target == target) return;
|
||||
m_Target = target;
|
||||
m_DirtyStateOrTarget = true;
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
Entity* BaseCombatAIComponent::GetTargetEntity() const {
|
||||
@@ -700,7 +703,7 @@ void BaseCombatAIComponent::OnAggro() {
|
||||
|
||||
m_MovementAI->SetDestination(targetPos);
|
||||
|
||||
m_State = AiState::tether;
|
||||
SetAiState(AiState::tether);
|
||||
}
|
||||
|
||||
m_Timer += 0.5f;
|
||||
@@ -726,7 +729,7 @@ void BaseCombatAIComponent::OnTether() {
|
||||
|
||||
m_MovementAI->SetDestination(m_StartPosition);
|
||||
|
||||
m_State = AiState::aggro;
|
||||
SetAiState(AiState::aggro);
|
||||
} else {
|
||||
if (IsMech() && Vector3::DistanceSquared(targetPos, currentPos) > m_AttackRadius * m_AttackRadius * 3 * 3) return;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "dpWorld.h"
|
||||
#include "dpEntity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@@ -46,7 +47,7 @@ struct AiSkillEntry
|
||||
*/
|
||||
class BaseCombatAIComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_BASE_COMBAT_AI;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI;
|
||||
|
||||
BaseCombatAIComponent(Entity* parentEntity, uint32_t id);
|
||||
~BaseCombatAIComponent() override;
|
||||
@@ -243,6 +244,12 @@ private:
|
||||
*/
|
||||
std::vector<LWOOBJID> GetTargetWithinAggroRange() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the AiState and prepares the entity for serialization next frame.
|
||||
*
|
||||
*/
|
||||
void SetAiState(AiState newState);
|
||||
|
||||
/**
|
||||
* The current state of the AI
|
||||
*/
|
||||
@@ -334,11 +341,6 @@ private:
|
||||
*/
|
||||
bool m_StunImmune = false;
|
||||
|
||||
/**
|
||||
* Time taken between actions
|
||||
*/
|
||||
float m_Downtime = 0;
|
||||
|
||||
/**
|
||||
* How long this entity needs to execute its skill
|
||||
*/
|
||||
@@ -374,6 +376,12 @@ private:
|
||||
*/
|
||||
bool m_DirtyThreat = false;
|
||||
|
||||
/**
|
||||
* Whether or not the Component has dirty information and should update next frame
|
||||
*
|
||||
*/
|
||||
bool m_DirtyStateOrTarget = false;
|
||||
|
||||
/**
|
||||
* Whether the current entity is a mech enemy, needed as mechs tether radius works differently
|
||||
* @return whether this entity is a mech
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "dLogger.h"
|
||||
#include "GameMessages.h"
|
||||
#include <BitStream.h>
|
||||
#include "eTriggerEventType.h"
|
||||
|
||||
BouncerComponent::BouncerComponent(Entity* parent) : Component(parent) {
|
||||
m_PetEnabled = false;
|
||||
@@ -46,8 +47,10 @@ void BouncerComponent::SetPetBouncerEnabled(bool value) {
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
|
||||
if (value) {
|
||||
m_Parent->TriggerEvent(eTriggerEventType::PET_ON_SWITCH, m_Parent);
|
||||
GameMessages::SendPlayFXEffect(m_Parent->GetObjectID(), 1513, u"create", "PetOnSwitch", LWOOBJID_EMPTY, 1, 1, true);
|
||||
} else {
|
||||
m_Parent->TriggerEvent(eTriggerEventType::PET_OFF_SWITCH, m_Parent);
|
||||
GameMessages::SendStopFXEffect(m_Parent, true, "PetOnSwitch");
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
#include "RakNetTypes.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Attached to bouncer entities, allowing other entities to bounce off of it
|
||||
*/
|
||||
class BouncerComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_BOUNCER;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER;
|
||||
|
||||
BouncerComponent(Entity* parentEntity);
|
||||
~BouncerComponent() override;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "SkillComponent.h"
|
||||
#include "ControllablePhysicsComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "CDClientManager.h"
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
|
||||
std::unordered_map<int32_t, std::vector<BuffParameter>> BuffComponent::m_Cache{};
|
||||
|
||||
@@ -100,7 +102,7 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO
|
||||
const auto& parameters = GetBuffParameters(id);
|
||||
for (const auto& parameter : parameters) {
|
||||
if (parameter.name == "overtime") {
|
||||
auto* behaviorTemplateTable = CDClientManager::Instance()->GetTable<CDSkillBehaviorTable>("SkillBehavior");
|
||||
auto* behaviorTemplateTable = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
||||
|
||||
behaviorID = behaviorTemplateTable->GetSkillByID(parameter.values[0]).behaviorID;
|
||||
stacks = static_cast<int32_t>(parameter.values[1]);
|
||||
@@ -123,13 +125,15 @@ void BuffComponent::ApplyBuff(const int32_t id, const float duration, const LWOO
|
||||
m_Buffs.emplace(id, buff);
|
||||
}
|
||||
|
||||
void BuffComponent::RemoveBuff(int32_t id) {
|
||||
void BuffComponent::RemoveBuff(int32_t id, bool fromUnEquip, bool removeImmunity) {
|
||||
const auto& iter = m_Buffs.find(id);
|
||||
|
||||
if (iter == m_Buffs.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameMessages::SendRemoveBuff(m_Parent, fromUnEquip, removeImmunity, id);
|
||||
|
||||
m_Buffs.erase(iter);
|
||||
|
||||
RemoveBuffEffect(id);
|
||||
@@ -167,17 +171,10 @@ void BuffComponent::ApplyBuffEffect(int32_t id) {
|
||||
|
||||
destroyable->SetMaxImagination(destroyable->GetMaxImagination() + maxImagination);
|
||||
} else if (parameter.name == "speed") {
|
||||
const auto speed = parameter.value;
|
||||
|
||||
auto* controllablePhysicsComponent = this->GetParent()->GetComponent<ControllablePhysicsComponent>();
|
||||
|
||||
if (controllablePhysicsComponent == nullptr) return;
|
||||
|
||||
const auto current = controllablePhysicsComponent->GetSpeedMultiplier();
|
||||
|
||||
controllablePhysicsComponent->SetSpeedMultiplier(current + ((speed - 500.0f) / 500.0f));
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(this->GetParent());
|
||||
if (!controllablePhysicsComponent) return;
|
||||
const auto speed = parameter.value;
|
||||
controllablePhysicsComponent->AddSpeedboost(speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,17 +207,10 @@ void BuffComponent::RemoveBuffEffect(int32_t id) {
|
||||
|
||||
destroyable->SetMaxImagination(destroyable->GetMaxImagination() - maxImagination);
|
||||
} else if (parameter.name == "speed") {
|
||||
const auto speed = parameter.value;
|
||||
|
||||
auto* controllablePhysicsComponent = this->GetParent()->GetComponent<ControllablePhysicsComponent>();
|
||||
|
||||
if (controllablePhysicsComponent == nullptr) return;
|
||||
|
||||
const auto current = controllablePhysicsComponent->GetSpeedMultiplier();
|
||||
|
||||
controllablePhysicsComponent->SetSpeedMultiplier(current - ((speed - 500.0f) / 500.0f));
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(this->GetParent());
|
||||
if (!controllablePhysicsComponent) return;
|
||||
const auto speed = parameter.value;
|
||||
controllablePhysicsComponent->RemoveSpeedboost(speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Entity;
|
||||
|
||||
@@ -41,7 +42,7 @@ struct Buff
|
||||
*/
|
||||
class BuffComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_BUFF;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::BUFF;
|
||||
|
||||
explicit BuffComponent(Entity* parent);
|
||||
|
||||
@@ -78,8 +79,9 @@ public:
|
||||
/**
|
||||
* Removes a buff from the parent entity, reversing its effects
|
||||
* @param id the id of the buff to remove
|
||||
* @param removeImmunity whether or not to remove immunity on removing the buff
|
||||
*/
|
||||
void RemoveBuff(int32_t id);
|
||||
void RemoveBuff(int32_t id, bool fromUnEquip = false, bool removeImmunity = false);
|
||||
|
||||
/**
|
||||
* Returns whether or not the entity has a buff identified by `id`
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Component for the build border, allowing the user to start building when interacting with it
|
||||
*/
|
||||
class BuildBorderComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_BUILD_BORDER;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::BUILD_BORDER;
|
||||
|
||||
BuildBorderComponent(Entity* parent);
|
||||
~BuildBorderComponent() override;
|
||||
|
||||
@@ -38,5 +38,6 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
|
||||
"SkillComponent.cpp"
|
||||
"SoundTriggerComponent.cpp"
|
||||
"SwitchComponent.cpp"
|
||||
"TriggerComponent.cpp"
|
||||
"VehiclePhysicsComponent.cpp"
|
||||
"VendorComponent.cpp" PARENT_SCOPE)
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "VehiclePhysicsComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Item.h"
|
||||
#include "AMFFormat.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) {
|
||||
m_Character = character;
|
||||
@@ -42,7 +44,6 @@ bool CharacterComponent::LandingAnimDisabled(int zoneID) {
|
||||
switch (zoneID) {
|
||||
case 0:
|
||||
case 556:
|
||||
case 1001:
|
||||
case 1101:
|
||||
case 1202:
|
||||
case 1203:
|
||||
@@ -165,9 +166,9 @@ void CharacterComponent::SetPvpEnabled(const bool value) {
|
||||
m_PvpEnabled = value;
|
||||
}
|
||||
|
||||
void CharacterComponent::SetGMLevel(int gmlevel) {
|
||||
void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
|
||||
m_DirtyGMInfo = true;
|
||||
if (gmlevel > 0) m_IsGM = true;
|
||||
if (gmlevel > eGameMasterLevel::CIVILIAN) m_IsGM = true;
|
||||
else m_IsGM = false;
|
||||
m_GMLevel = gmlevel;
|
||||
}
|
||||
@@ -239,7 +240,7 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||
// End custom attributes
|
||||
//
|
||||
|
||||
if (m_GMLevel > 0) {
|
||||
if (m_GMLevel > eGameMasterLevel::CIVILIAN) {
|
||||
m_IsGM = true;
|
||||
m_DirtyGMInfo = true;
|
||||
m_EditorLevel = m_GMLevel;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
#include "CDMissionsTable.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* The statistics that can be achieved per zone
|
||||
@@ -59,7 +60,7 @@ enum StatisticID {
|
||||
*/
|
||||
class CharacterComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_CHARACTER;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER;
|
||||
|
||||
CharacterComponent(Entity* parent, Character* character);
|
||||
~CharacterComponent() override;
|
||||
@@ -177,7 +178,7 @@ public:
|
||||
* Sets the GM level of the character, should be called in the entity. Here it's set for serialization
|
||||
* @param gmlevel the gm level to set
|
||||
*/
|
||||
void SetGMLevel(int gmlevel);
|
||||
void SetGMLevel(eGameMasterLevel gmlevel);
|
||||
|
||||
/**
|
||||
* Initializes the player statistics from the string stored in the XML
|
||||
@@ -332,7 +333,7 @@ private:
|
||||
/**
|
||||
* The current GM level of this character (anything > 0 counts as a GM)
|
||||
*/
|
||||
unsigned char m_GMLevel;
|
||||
eGameMasterLevel m_GMLevel;
|
||||
|
||||
/**
|
||||
* Whether the character has HF enabled
|
||||
@@ -342,7 +343,7 @@ private:
|
||||
/**
|
||||
* The level of the character in HF
|
||||
*/
|
||||
unsigned char m_EditorLevel;
|
||||
eGameMasterLevel m_EditorLevel;
|
||||
|
||||
/**
|
||||
* Whether the currently active activity has been changed
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "EntityManager.h"
|
||||
#include "Character.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "LevelProgressionComponent.h"
|
||||
|
||||
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Component(entity) {
|
||||
m_Position = {};
|
||||
@@ -30,10 +31,25 @@ ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity) : Com
|
||||
m_GravityScale = 1;
|
||||
m_DirtyCheats = false;
|
||||
m_IgnoreMultipliers = false;
|
||||
|
||||
m_DirtyEquippedItemInfo = true;
|
||||
m_PickupRadius = 0.0f;
|
||||
m_DirtyPickupRadiusScale = true;
|
||||
|
||||
m_DirtyBubble = false;
|
||||
m_IsInBubble = false;
|
||||
m_SpecialAnims = false;
|
||||
m_BubbleType = eBubbleType::DEFAULT;
|
||||
|
||||
m_IsTeleporting = false;
|
||||
|
||||
m_ImmuneToStunAttackCount = 0;
|
||||
m_ImmuneToStunEquipCount = 0;
|
||||
m_ImmuneToStunInteractCount = 0;
|
||||
m_ImmuneToStunJumpCount = 0;
|
||||
m_ImmuneToStunMoveCount = 0;
|
||||
m_ImmuneToStunTurnCount = 0;
|
||||
m_ImmuneToStunUseItemCount = 0;
|
||||
|
||||
if (entity->GetLOT() != 1) // Other physics entities we care about will be added by BaseCombatAI
|
||||
return;
|
||||
|
||||
@@ -70,16 +86,17 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bo
|
||||
outBitStream->Write(m_JetpackBypassChecks);
|
||||
}
|
||||
|
||||
outBitStream->Write0(); //This contains info about immunities, but for now I'm leaving it out.
|
||||
outBitStream->Write1(); // always write these on construction
|
||||
outBitStream->Write(m_ImmuneToStunMoveCount);
|
||||
outBitStream->Write(m_ImmuneToStunJumpCount);
|
||||
outBitStream->Write(m_ImmuneToStunTurnCount);
|
||||
outBitStream->Write(m_ImmuneToStunAttackCount);
|
||||
outBitStream->Write(m_ImmuneToStunUseItemCount);
|
||||
outBitStream->Write(m_ImmuneToStunEquipCount);
|
||||
outBitStream->Write(m_ImmuneToStunInteractCount);
|
||||
}
|
||||
|
||||
if (m_SpeedMultiplier < 1.0f) {
|
||||
m_DirtyCheats = false;
|
||||
}
|
||||
|
||||
if (m_IgnoreMultipliers) {
|
||||
m_DirtyCheats = false;
|
||||
}
|
||||
if (m_IgnoreMultipliers) m_DirtyCheats = false;
|
||||
|
||||
outBitStream->Write(m_DirtyCheats);
|
||||
if (m_DirtyCheats) {
|
||||
@@ -89,14 +106,22 @@ void ControllablePhysicsComponent::Serialize(RakNet::BitStream* outBitStream, bo
|
||||
m_DirtyCheats = false;
|
||||
}
|
||||
|
||||
outBitStream->Write(m_DirtyPickupRadiusScale);
|
||||
if (m_DirtyPickupRadiusScale) {
|
||||
outBitStream->Write(m_DirtyEquippedItemInfo);
|
||||
if (m_DirtyEquippedItemInfo) {
|
||||
outBitStream->Write(m_PickupRadius);
|
||||
outBitStream->Write0(); //No clue what this is so im leaving it false.
|
||||
m_DirtyPickupRadiusScale = false;
|
||||
outBitStream->Write(m_InJetpackMode);
|
||||
m_DirtyEquippedItemInfo = false;
|
||||
}
|
||||
|
||||
outBitStream->Write0();
|
||||
outBitStream->Write(m_DirtyBubble);
|
||||
if (m_DirtyBubble) {
|
||||
outBitStream->Write(m_IsInBubble);
|
||||
if (m_IsInBubble) {
|
||||
outBitStream->Write(m_BubbleType);
|
||||
outBitStream->Write(m_SpecialAnims);
|
||||
}
|
||||
m_DirtyBubble = false;
|
||||
}
|
||||
|
||||
outBitStream->Write(m_DirtyPosition || bIsInitialUpdate);
|
||||
if (m_DirtyPosition || bIsInitialUpdate) {
|
||||
@@ -253,7 +278,7 @@ void ControllablePhysicsComponent::AddPickupRadiusScale(float value) {
|
||||
m_ActivePickupRadiusScales.push_back(value);
|
||||
if (value > m_PickupRadius) {
|
||||
m_PickupRadius = value;
|
||||
m_DirtyPickupRadiusScale = true;
|
||||
m_DirtyEquippedItemInfo = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,16 +288,102 @@ void ControllablePhysicsComponent::RemovePickupRadiusScale(float value) {
|
||||
if (pos != m_ActivePickupRadiusScales.end()) {
|
||||
m_ActivePickupRadiusScales.erase(pos);
|
||||
} else {
|
||||
Game::logger->Log("ControllablePhysicsComponent", "Warning: Could not find pickup radius %f in list of active radii. List has %i active radii.", value, m_ActivePickupRadiusScales.size());
|
||||
Game::logger->LogDebug("ControllablePhysicsComponent", "Warning: Could not find pickup radius %f in list of active radii. List has %i active radii.", value, m_ActivePickupRadiusScales.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Recalculate pickup radius since we removed one by now
|
||||
m_PickupRadius = 0.0f;
|
||||
m_DirtyPickupRadiusScale = true;
|
||||
m_DirtyEquippedItemInfo = true;
|
||||
for (uint32_t i = 0; i < m_ActivePickupRadiusScales.size(); i++) {
|
||||
auto candidateRadius = m_ActivePickupRadiusScales[i];
|
||||
if (m_PickupRadius < candidateRadius) m_PickupRadius = candidateRadius;
|
||||
}
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
void ControllablePhysicsComponent::AddSpeedboost(float value) {
|
||||
m_ActiveSpeedBoosts.push_back(value);
|
||||
m_SpeedBoost = value;
|
||||
SetSpeedMultiplier(value / 500.0f); // 500 being the base speed
|
||||
}
|
||||
|
||||
void ControllablePhysicsComponent::RemoveSpeedboost(float value) {
|
||||
const auto pos = std::find(m_ActiveSpeedBoosts.begin(), m_ActiveSpeedBoosts.end(), value);
|
||||
if (pos != m_ActiveSpeedBoosts.end()) {
|
||||
m_ActiveSpeedBoosts.erase(pos);
|
||||
} else {
|
||||
Game::logger->LogDebug("ControllablePhysicsComponent", "Warning: Could not find speedboost %f in list of active speedboosts. List has %i active speedboosts.", value, m_ActiveSpeedBoosts.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Recalculate speedboost since we removed one
|
||||
m_SpeedBoost = 0.0f;
|
||||
if (m_ActiveSpeedBoosts.size() == 0) { // no active speed boosts left, so return to base speed
|
||||
auto* levelProgressionComponent = m_Parent->GetComponent<LevelProgressionComponent>();
|
||||
if (levelProgressionComponent) m_SpeedBoost = levelProgressionComponent->GetSpeedBase();
|
||||
} else { // Used the last applied speedboost
|
||||
m_SpeedBoost = m_ActiveSpeedBoosts.back();
|
||||
}
|
||||
SetSpeedMultiplier(m_SpeedBoost / 500.0f); // 500 being the base speed
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
void ControllablePhysicsComponent::ActivateBubbleBuff(eBubbleType bubbleType, bool specialAnims){
|
||||
if (m_IsInBubble) {
|
||||
Game::logger->Log("ControllablePhysicsComponent", "Already in bubble");
|
||||
return;
|
||||
}
|
||||
m_BubbleType = bubbleType;
|
||||
m_IsInBubble = true;
|
||||
m_DirtyBubble = true;
|
||||
m_SpecialAnims = specialAnims;
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
void ControllablePhysicsComponent::DeactivateBubbleBuff(){
|
||||
m_DirtyBubble = true;
|
||||
m_IsInBubble = false;
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
};
|
||||
|
||||
void ControllablePhysicsComponent::SetStunImmunity(
|
||||
const eStateChangeType state,
|
||||
const LWOOBJID originator,
|
||||
const bool bImmuneToStunAttack,
|
||||
const bool bImmuneToStunEquip,
|
||||
const bool bImmuneToStunInteract,
|
||||
const bool bImmuneToStunJump,
|
||||
const bool bImmuneToStunMove,
|
||||
const bool bImmuneToStunTurn,
|
||||
const bool bImmuneToStunUseItem){
|
||||
|
||||
if (state == eStateChangeType::POP){
|
||||
if (bImmuneToStunAttack && m_ImmuneToStunAttackCount > 0) m_ImmuneToStunAttackCount -= 1;
|
||||
if (bImmuneToStunEquip && m_ImmuneToStunEquipCount > 0) m_ImmuneToStunEquipCount -= 1;
|
||||
if (bImmuneToStunInteract && m_ImmuneToStunInteractCount > 0) m_ImmuneToStunInteractCount -= 1;
|
||||
if (bImmuneToStunJump && m_ImmuneToStunJumpCount > 0) m_ImmuneToStunJumpCount -= 1;
|
||||
if (bImmuneToStunMove && m_ImmuneToStunMoveCount > 0) m_ImmuneToStunMoveCount -= 1;
|
||||
if (bImmuneToStunTurn && m_ImmuneToStunTurnCount > 0) m_ImmuneToStunTurnCount -= 1;
|
||||
if (bImmuneToStunUseItem && m_ImmuneToStunUseItemCount > 0) m_ImmuneToStunUseItemCount -= 1;
|
||||
} else if (state == eStateChangeType::PUSH) {
|
||||
if (bImmuneToStunAttack) m_ImmuneToStunAttackCount += 1;
|
||||
if (bImmuneToStunEquip) m_ImmuneToStunEquipCount += 1;
|
||||
if (bImmuneToStunInteract) m_ImmuneToStunInteractCount += 1;
|
||||
if (bImmuneToStunJump) m_ImmuneToStunJumpCount += 1;
|
||||
if (bImmuneToStunMove) m_ImmuneToStunMoveCount += 1;
|
||||
if (bImmuneToStunTurn) m_ImmuneToStunTurnCount += 1;
|
||||
if (bImmuneToStunUseItem) m_ImmuneToStunUseItemCount += 1;
|
||||
}
|
||||
|
||||
GameMessages::SendSetStunImmunity(
|
||||
m_Parent->GetObjectID(), state, m_Parent->GetSystemAddress(), originator,
|
||||
bImmuneToStunAttack,
|
||||
bImmuneToStunEquip,
|
||||
bImmuneToStunInteract,
|
||||
bImmuneToStunJump,
|
||||
bImmuneToStunMove,
|
||||
bImmuneToStunTurn,
|
||||
bImmuneToStunUseItem
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "Component.h"
|
||||
#include "dpCollisionChecks.h"
|
||||
#include "PhantomPhysicsComponent.h"
|
||||
#include "eBubbleType.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Entity;
|
||||
class dpEntity;
|
||||
@@ -18,7 +20,7 @@ class dpEntity;
|
||||
*/
|
||||
class ControllablePhysicsComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_CONTROLLABLE_PHYSICS;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
|
||||
|
||||
ControllablePhysicsComponent(Entity* entity);
|
||||
~ControllablePhysicsComponent() override;
|
||||
@@ -257,6 +259,63 @@ public:
|
||||
*/
|
||||
std::vector<float> GetActivePickupRadiusScales() { return m_ActivePickupRadiusScales; };
|
||||
|
||||
/**
|
||||
* Add a Speed boost to the entity
|
||||
* This will recalculate the speed boost based on what is being added
|
||||
*/
|
||||
void AddSpeedboost(float value);
|
||||
|
||||
/**
|
||||
* Remove speed boost from entity
|
||||
* This will recalculate the speed boost based on what is the last one in te vector
|
||||
*/
|
||||
void RemoveSpeedboost(float value);
|
||||
|
||||
/**
|
||||
* The speed boosts of this component.
|
||||
* @return All active Speed boosts for this component.
|
||||
*/
|
||||
std::vector<float> GetActiveSpeedboosts() { return m_ActivePickupRadiusScales; };
|
||||
|
||||
/**
|
||||
* Activates the Bubble Buff
|
||||
*/
|
||||
void ActivateBubbleBuff(eBubbleType bubbleType = eBubbleType::DEFAULT, bool specialAnims = true);
|
||||
|
||||
/**
|
||||
* Deactivates the Bubble Buff
|
||||
*/
|
||||
void DeactivateBubbleBuff();
|
||||
|
||||
/**
|
||||
* Gets if the Entity is in a bubble
|
||||
*/
|
||||
bool GetIsInBubble(){ return m_IsInBubble; };
|
||||
|
||||
/**
|
||||
* Push or Pop a layer of stun immunity to this entity
|
||||
*/
|
||||
void SetStunImmunity(
|
||||
const eStateChangeType state,
|
||||
const LWOOBJID originator = LWOOBJID_EMPTY,
|
||||
const bool bImmuneToStunAttack = false,
|
||||
const bool bImmuneToStunEquip = false,
|
||||
const bool bImmuneToStunInteract = false,
|
||||
const bool bImmuneToStunJump = false,
|
||||
const bool bImmuneToStunMove = false,
|
||||
const bool bImmuneToStunTurn = false,
|
||||
const bool bImmuneToStunUseItem = false
|
||||
);
|
||||
|
||||
// getters for stun immunities
|
||||
const bool GetImmuneToStunAttack() { return m_ImmuneToStunAttackCount > 0;};
|
||||
const bool GetImmuneToStunEquip() { return m_ImmuneToStunEquipCount > 0;};
|
||||
const bool GetImmuneToStunInteract() { return m_ImmuneToStunInteractCount > 0;};
|
||||
const bool GetImmuneToStunJump() { return m_ImmuneToStunJumpCount > 0;};
|
||||
const bool GetImmuneToStunMove() { return m_ImmuneToStunMoveCount > 0;};
|
||||
const bool GetImmuneToStunTurn() { return m_ImmuneToStunTurnCount > 0;};
|
||||
const bool GetImmuneToStunUseItem() { return m_ImmuneToStunUseItemCount > 0;};
|
||||
|
||||
private:
|
||||
/**
|
||||
* The entity that owns this component
|
||||
@@ -356,7 +415,7 @@ private:
|
||||
/**
|
||||
* Whether the pickup scale is dirty.
|
||||
*/
|
||||
bool m_DirtyPickupRadiusScale;
|
||||
bool m_DirtyEquippedItemInfo;
|
||||
|
||||
/**
|
||||
* The list of pickup radius scales for this entity
|
||||
@@ -372,6 +431,47 @@ private:
|
||||
* If the entity is teleporting
|
||||
*/
|
||||
bool m_IsTeleporting;
|
||||
|
||||
/**
|
||||
* The list of speed boosts for this entity
|
||||
*/
|
||||
std::vector<float> m_ActiveSpeedBoosts;
|
||||
|
||||
/**
|
||||
* The active speed boost for this entity
|
||||
*/
|
||||
float m_SpeedBoost;
|
||||
|
||||
/*
|
||||
* If Bubble info is dirty
|
||||
*/
|
||||
bool m_DirtyBubble;
|
||||
|
||||
/*
|
||||
* If the entity is in a bubble
|
||||
*/
|
||||
bool m_IsInBubble;
|
||||
|
||||
/*
|
||||
* The type of bubble the entity has
|
||||
*/
|
||||
eBubbleType m_BubbleType;
|
||||
|
||||
/*
|
||||
* If the entity should be using the special animations
|
||||
*/
|
||||
bool m_SpecialAnims;
|
||||
|
||||
/**
|
||||
* stun immunity counters
|
||||
*/
|
||||
int32_t m_ImmuneToStunAttackCount;
|
||||
int32_t m_ImmuneToStunEquipCount;
|
||||
int32_t m_ImmuneToStunInteractCount;
|
||||
int32_t m_ImmuneToStunJumpCount;
|
||||
int32_t m_ImmuneToStunMoveCount;
|
||||
int32_t m_ImmuneToStunTurnCount;
|
||||
int32_t m_ImmuneToStunUseItemCount;
|
||||
};
|
||||
|
||||
#endif // CONTROLLABLEPHYSICSCOMPONENT_H
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <BitStream.h>
|
||||
#include "dLogger.h"
|
||||
#include "Game.h"
|
||||
#include "dConfig.h"
|
||||
|
||||
#include "AMFFormat.h"
|
||||
#include "AMFFormat_BitStream.h"
|
||||
@@ -28,7 +29,12 @@
|
||||
#include "CharacterComponent.h"
|
||||
#include "PossessableComponent.h"
|
||||
#include "PossessorComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "WorldConfig.h"
|
||||
#include "eMissionTaskType.h"
|
||||
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
|
||||
DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
||||
m_iArmor = 0;
|
||||
@@ -53,26 +59,35 @@ DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
||||
m_LootMatrixID = 0;
|
||||
m_MinCoins = 0;
|
||||
m_MaxCoins = 0;
|
||||
m_ImmuneStacks = 0;
|
||||
m_DamageReduction = 0;
|
||||
|
||||
m_ImmuneToBasicAttackCount = 0;
|
||||
m_ImmuneToDamageOverTimeCount = 0;
|
||||
m_ImmuneToKnockbackCount = 0;
|
||||
m_ImmuneToInterruptCount = 0;
|
||||
m_ImmuneToSpeedCount = 0;
|
||||
m_ImmuneToImaginationGainCount = 0;
|
||||
m_ImmuneToImaginationLossCount = 0;
|
||||
m_ImmuneToQuickbuildInterruptCount = 0;
|
||||
m_ImmuneToPullToPointCount = 0;
|
||||
}
|
||||
|
||||
DestroyableComponent::~DestroyableComponent() {
|
||||
}
|
||||
|
||||
void DestroyableComponent::Reinitialize(LOT templateID) {
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
|
||||
int32_t buffComponentID = compRegistryTable->GetByIDAndType(templateID, COMPONENT_TYPE_BUFF);
|
||||
int32_t collectibleComponentID = compRegistryTable->GetByIDAndType(templateID, COMPONENT_TYPE_COLLECTIBLE);
|
||||
int32_t rebuildComponentID = compRegistryTable->GetByIDAndType(templateID, COMPONENT_TYPE_REBUILD);
|
||||
int32_t buffComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::BUFF);
|
||||
int32_t collectibleComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::COLLECTIBLE);
|
||||
int32_t rebuildComponentID = compRegistryTable->GetByIDAndType(templateID, eReplicaComponentType::QUICK_BUILD);
|
||||
|
||||
int32_t componentID = 0;
|
||||
if (collectibleComponentID > 0) componentID = collectibleComponentID;
|
||||
if (rebuildComponentID > 0) componentID = rebuildComponentID;
|
||||
if (buffComponentID > 0) componentID = buffComponentID;
|
||||
|
||||
CDDestructibleComponentTable* destCompTable = CDClientManager::Instance()->GetTable<CDDestructibleComponentTable>("DestructibleComponent");
|
||||
CDDestructibleComponentTable* destCompTable = CDClientManager::Instance().GetTable<CDDestructibleComponentTable>();
|
||||
std::vector<CDDestructibleComponent> destCompData = destCompTable->Query([=](CDDestructibleComponent entry) { return (entry.id == componentID); });
|
||||
|
||||
if (componentID > 0) {
|
||||
@@ -104,7 +119,16 @@ void DestroyableComponent::Reinitialize(LOT templateID) {
|
||||
|
||||
void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) {
|
||||
if (bIsInitialUpdate) {
|
||||
outBitStream->Write0(); //Contains info about immunities this object has, but it's left out for now.
|
||||
outBitStream->Write1(); // always write these on construction
|
||||
outBitStream->Write(m_ImmuneToBasicAttackCount);
|
||||
outBitStream->Write(m_ImmuneToDamageOverTimeCount);
|
||||
outBitStream->Write(m_ImmuneToKnockbackCount);
|
||||
outBitStream->Write(m_ImmuneToInterruptCount);
|
||||
outBitStream->Write(m_ImmuneToSpeedCount);
|
||||
outBitStream->Write(m_ImmuneToImaginationGainCount);
|
||||
outBitStream->Write(m_ImmuneToImaginationLossCount);
|
||||
outBitStream->Write(m_ImmuneToQuickbuildInterruptCount);
|
||||
outBitStream->Write(m_ImmuneToPullToPointCount);
|
||||
}
|
||||
|
||||
outBitStream->Write(m_DirtyHealth || bIsInitialUpdate);
|
||||
@@ -138,25 +162,17 @@ void DestroyableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIn
|
||||
|
||||
if (m_IsSmashable) {
|
||||
outBitStream->Write(m_HasBricks);
|
||||
|
||||
if (m_ExplodeFactor != 1.0f) {
|
||||
outBitStream->Write1();
|
||||
outBitStream->Write(m_ExplodeFactor);
|
||||
} else {
|
||||
outBitStream->Write0();
|
||||
}
|
||||
outBitStream->Write(m_ExplodeFactor != 1.0f);
|
||||
if (m_ExplodeFactor != 1.0f) outBitStream->Write(m_ExplodeFactor);
|
||||
}
|
||||
}
|
||||
|
||||
m_DirtyHealth = false;
|
||||
}
|
||||
|
||||
outBitStream->Write(m_DirtyThreatList || bIsInitialUpdate);
|
||||
if (m_DirtyThreatList || bIsInitialUpdate) {
|
||||
outBitStream->Write1();
|
||||
outBitStream->Write(m_HasThreats);
|
||||
m_DirtyThreatList = false;
|
||||
} else {
|
||||
outBitStream->Write0();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +358,7 @@ void DestroyableComponent::SetDamageReduction(int32_t value) {
|
||||
|
||||
void DestroyableComponent::SetIsImmune(bool value) {
|
||||
m_DirtyHealth = true;
|
||||
m_ImmuneStacks = value ? 1 : 0;
|
||||
m_ImmuneToBasicAttackCount = value ? 1 : 0;
|
||||
}
|
||||
|
||||
void DestroyableComponent::SetIsGMImmune(bool value) {
|
||||
@@ -438,7 +454,6 @@ void DestroyableComponent::AddEnemyFaction(int32_t factionID) {
|
||||
void DestroyableComponent::SetIsSmashable(bool value) {
|
||||
m_DirtyHealth = true;
|
||||
m_IsSmashable = value;
|
||||
//m_HasBricks = value;
|
||||
}
|
||||
|
||||
void DestroyableComponent::SetAttacksToBlock(const uint32_t value) {
|
||||
@@ -446,7 +461,7 @@ void DestroyableComponent::SetAttacksToBlock(const uint32_t value) {
|
||||
}
|
||||
|
||||
bool DestroyableComponent::IsImmune() const {
|
||||
return m_ImmuneStacks > 0 || m_IsGMImmune;
|
||||
return m_IsGMImmune || m_ImmuneToBasicAttackCount > 0;
|
||||
}
|
||||
|
||||
bool DestroyableComponent::IsKnockbackImmune() const {
|
||||
@@ -455,9 +470,9 @@ bool DestroyableComponent::IsKnockbackImmune() const {
|
||||
|
||||
if (characterComponent != nullptr && inventoryComponent != nullptr && characterComponent->GetCurrentActivity() == eGameActivities::ACTIVITY_QUICKBUILDING) {
|
||||
const auto hasPassive = inventoryComponent->HasAnyPassive({
|
||||
ItemSetPassiveAbilityID::EngineerRank2, ItemSetPassiveAbilityID::EngineerRank3,
|
||||
ItemSetPassiveAbilityID::SummonerRank2, ItemSetPassiveAbilityID::SummonerRank3,
|
||||
ItemSetPassiveAbilityID::InventorRank2, ItemSetPassiveAbilityID::InventorRank3,
|
||||
eItemSetPassiveAbilityID::EngineerRank2, eItemSetPassiveAbilityID::EngineerRank3,
|
||||
eItemSetPassiveAbilityID::SummonerRank2, eItemSetPassiveAbilityID::SummonerRank3,
|
||||
eItemSetPassiveAbilityID::InventorRank2, eItemSetPassiveAbilityID::InventorRank3,
|
||||
}, 5);
|
||||
|
||||
if (hasPassive) {
|
||||
@@ -639,6 +654,7 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
||||
auto* attacker = EntityManager::Instance()->GetEntity(source);
|
||||
m_Parent->OnHit(attacker);
|
||||
m_Parent->OnHitOrHealResult(attacker, sourceDamage);
|
||||
NotifySubscribers(attacker, sourceDamage);
|
||||
|
||||
for (const auto& cb : m_OnHitCallbacks) {
|
||||
cb(attacker);
|
||||
@@ -653,9 +669,38 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//check if hardcore mode is enabled
|
||||
if (EntityManager::Instance()->GetHardcoreMode()) {
|
||||
DoHardcoreModeDrops(source);
|
||||
}
|
||||
|
||||
Smash(source, eKillType::VIOLENT, u"", skillID);
|
||||
}
|
||||
|
||||
void DestroyableComponent::Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd) {
|
||||
m_SubscribedScripts.insert(std::make_pair(scriptObjId, scriptToAdd));
|
||||
Game::logger->LogDebug("DestroyableComponent", "Added script %llu to entity %llu", scriptObjId, m_Parent->GetObjectID());
|
||||
Game::logger->LogDebug("DestroyableComponent", "Number of subscribed scripts %i", m_SubscribedScripts.size());
|
||||
}
|
||||
|
||||
void DestroyableComponent::Unsubscribe(LWOOBJID scriptObjId) {
|
||||
auto foundScript = m_SubscribedScripts.find(scriptObjId);
|
||||
if (foundScript != m_SubscribedScripts.end()) {
|
||||
m_SubscribedScripts.erase(foundScript);
|
||||
Game::logger->LogDebug("DestroyableComponent", "Removed script %llu from entity %llu", scriptObjId, m_Parent->GetObjectID());
|
||||
} else {
|
||||
Game::logger->LogDebug("DestroyableComponent", "Tried to remove a script for Entity %llu but script %llu didnt exist", m_Parent->GetObjectID(), scriptObjId);
|
||||
}
|
||||
Game::logger->LogDebug("DestroyableComponent", "Number of subscribed scripts %i", m_SubscribedScripts.size());
|
||||
}
|
||||
|
||||
void DestroyableComponent::NotifySubscribers(Entity* attacker, uint32_t damage) {
|
||||
for (auto script : m_SubscribedScripts) {
|
||||
script.second->NotifyHitOrHealResult(m_Parent, attacker, damage);
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType, const std::u16string& deathType, uint32_t skillID) {
|
||||
if (m_iHealth > 0) {
|
||||
SetArmor(0);
|
||||
@@ -678,13 +723,13 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
auto* inventoryComponent = owner->GetComponent<InventoryComponent>();
|
||||
|
||||
if (inventoryComponent != nullptr && isEnemy) {
|
||||
inventoryComponent->TriggerPassiveAbility(PassiveAbilityTrigger::EnemySmashed);
|
||||
inventoryComponent->TriggerPassiveAbility(PassiveAbilityTrigger::EnemySmashed, m_Parent);
|
||||
}
|
||||
|
||||
auto* missions = owner->GetComponent<MissionComponent>();
|
||||
|
||||
if (missions != nullptr) {
|
||||
if (team != nullptr && isEnemy) {
|
||||
if (team != nullptr) {
|
||||
for (const auto memberId : team->members) {
|
||||
auto* member = EntityManager::Instance()->GetEntity(memberId);
|
||||
|
||||
@@ -694,12 +739,12 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
|
||||
if (memberMissions == nullptr) continue;
|
||||
|
||||
memberMissions->Progress(MissionTaskType::MISSION_TASK_TYPE_SMASH, m_Parent->GetLOT());
|
||||
memberMissions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, m_Parent->GetLOT(), skillID);
|
||||
memberMissions->Progress(eMissionTaskType::SMASH, m_Parent->GetLOT());
|
||||
memberMissions->Progress(eMissionTaskType::USE_SKILL, m_Parent->GetLOT(), skillID);
|
||||
}
|
||||
} else {
|
||||
missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SMASH, m_Parent->GetLOT());
|
||||
missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, m_Parent->GetLOT(), skillID);
|
||||
missions->Progress(eMissionTaskType::SMASH, m_Parent->GetLOT());
|
||||
missions->Progress(eMissionTaskType::USE_SKILL, m_Parent->GetLOT(), skillID);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -747,22 +792,17 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
if (dZoneManager::Instance()->GetPlayerLoseCoinOnDeath()) {
|
||||
auto* character = m_Parent->GetCharacter();
|
||||
uint64_t coinsTotal = character->GetCoins();
|
||||
const uint64_t minCoinsToLose = dZoneManager::Instance()->GetWorldConfig()->coinsLostOnDeathMin;
|
||||
if (coinsTotal >= minCoinsToLose) {
|
||||
const uint64_t maxCoinsToLose = dZoneManager::Instance()->GetWorldConfig()->coinsLostOnDeathMax;
|
||||
const float coinPercentageToLose = dZoneManager::Instance()->GetWorldConfig()->coinsLostOnDeathPercent;
|
||||
|
||||
if (coinsTotal > 0) {
|
||||
uint64_t coinsToLoose = 1;
|
||||
uint64_t coinsToLose = std::max(static_cast<uint64_t>(coinsTotal * coinPercentageToLose), minCoinsToLose);
|
||||
coinsToLose = std::min(maxCoinsToLose, coinsToLose);
|
||||
|
||||
if (coinsTotal >= 200) {
|
||||
float hundreth = (coinsTotal / 100.0f);
|
||||
coinsToLoose = static_cast<int>(hundreth);
|
||||
}
|
||||
coinsTotal -= coinsToLose;
|
||||
|
||||
if (coinsToLoose > 10000) {
|
||||
coinsToLoose = 10000;
|
||||
}
|
||||
|
||||
coinsTotal -= coinsToLoose;
|
||||
|
||||
LootGenerator::Instance().DropLoot(m_Parent, m_Parent, -1, coinsToLoose, coinsToLoose);
|
||||
LootGenerator::Instance().DropLoot(m_Parent, m_Parent, -1, coinsToLose, coinsToLose);
|
||||
character->SetCoins(coinsTotal, eLootSourceType::LOOT_SOURCE_PICKUP);
|
||||
}
|
||||
}
|
||||
@@ -772,7 +812,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
script->OnPlayerDied(zoneControl, m_Parent);
|
||||
}
|
||||
|
||||
std::vector<Entity*> scriptedActs = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_SCRIPTED_ACTIVITY);
|
||||
std::vector<Entity*> scriptedActs = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::SCRIPTED_ACTIVITY);
|
||||
for (Entity* scriptEntity : scriptedActs) {
|
||||
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
|
||||
@@ -792,12 +832,53 @@ void DestroyableComponent::SetFaction(int32_t factionID, bool ignoreChecks) {
|
||||
AddFaction(factionID, ignoreChecks);
|
||||
}
|
||||
|
||||
void DestroyableComponent::PushImmunity(int32_t stacks) {
|
||||
m_ImmuneStacks += stacks;
|
||||
}
|
||||
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) {
|
||||
|
||||
void DestroyableComponent::PopImmunity(int32_t stacks) {
|
||||
m_ImmuneStacks -= stacks;
|
||||
if (state == eStateChangeType::POP) {
|
||||
if (bImmuneToBasicAttack && m_ImmuneToBasicAttackCount > 0) m_ImmuneToBasicAttackCount -= 1;
|
||||
if (bImmuneToDamageOverTime && m_ImmuneToDamageOverTimeCount > 0) m_ImmuneToDamageOverTimeCount -= 1;
|
||||
if (bImmuneToKnockback && m_ImmuneToKnockbackCount > 0) m_ImmuneToKnockbackCount -= 1;
|
||||
if (bImmuneToInterrupt && m_ImmuneToInterruptCount > 0) m_ImmuneToInterruptCount -= 1;
|
||||
if (bImmuneToSpeed && m_ImmuneToSpeedCount > 0) m_ImmuneToSpeedCount -= 1;
|
||||
if (bImmuneToImaginationGain && m_ImmuneToImaginationGainCount > 0) m_ImmuneToImaginationGainCount -= 1;
|
||||
if (bImmuneToImaginationLoss && m_ImmuneToImaginationLossCount > 0) m_ImmuneToImaginationLossCount -= 1;
|
||||
if (bImmuneToQuickbuildInterrupt && m_ImmuneToQuickbuildInterruptCount > 0) m_ImmuneToQuickbuildInterruptCount -= 1;
|
||||
if (bImmuneToPullToPoint && m_ImmuneToPullToPointCount > 0) m_ImmuneToPullToPointCount -= 1;
|
||||
|
||||
} else if (state == eStateChangeType::PUSH){
|
||||
if (bImmuneToBasicAttack) m_ImmuneToBasicAttackCount += 1;
|
||||
if (bImmuneToDamageOverTime) m_ImmuneToDamageOverTimeCount += 1;
|
||||
if (bImmuneToKnockback) m_ImmuneToKnockbackCount += 1;
|
||||
if (bImmuneToInterrupt) m_ImmuneToInterruptCount += 1;
|
||||
if (bImmuneToSpeed) m_ImmuneToSpeedCount += 1;
|
||||
if (bImmuneToImaginationGain) m_ImmuneToImaginationGainCount += 1;
|
||||
if (bImmuneToImaginationLoss) m_ImmuneToImaginationLossCount += 1;
|
||||
if (bImmuneToQuickbuildInterrupt) m_ImmuneToQuickbuildInterruptCount += 1;
|
||||
if (bImmuneToPullToPoint) m_ImmuneToPullToPointCount += 1;
|
||||
}
|
||||
|
||||
GameMessages::SendSetStatusImmunity(
|
||||
m_Parent->GetObjectID(), state, m_Parent->GetSystemAddress(),
|
||||
bImmuneToBasicAttack,
|
||||
bImmuneToDamageOverTime,
|
||||
bImmuneToKnockback,
|
||||
bImmuneToInterrupt,
|
||||
bImmuneToSpeed,
|
||||
bImmuneToImaginationGain,
|
||||
bImmuneToImaginationLoss,
|
||||
bImmuneToQuickbuildInterrupt,
|
||||
bImmuneToPullToPoint
|
||||
);
|
||||
}
|
||||
|
||||
void DestroyableComponent::FixStats() {
|
||||
@@ -900,3 +981,75 @@ void DestroyableComponent::FixStats() {
|
||||
void DestroyableComponent::AddOnHitCallback(const std::function<void(Entity*)>& callback) {
|
||||
m_OnHitCallbacks.push_back(callback);
|
||||
}
|
||||
|
||||
void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source){
|
||||
//check if this is a player:
|
||||
if (m_Parent->IsPlayer()) {
|
||||
//remove hardcore_lose_uscore_on_death_percent from the player's uscore:
|
||||
auto* character = m_Parent->GetComponent<CharacterComponent>();
|
||||
auto uscore = character->GetUScore();
|
||||
|
||||
auto uscoreToLose = uscore * (EntityManager::Instance()->GetHardcoreLoseUscoreOnDeathPercent() / 100);
|
||||
character->SetUScore(uscore - uscoreToLose);
|
||||
|
||||
GameMessages::SendModifyLEGOScore(m_Parent, m_Parent->GetSystemAddress(), -uscoreToLose, eLootSourceType::LOOT_SOURCE_MISSION);
|
||||
|
||||
if (EntityManager::Instance()->GetHardcoreDropinventoryOnDeath()) {
|
||||
//drop all items from inventory:
|
||||
auto* inventory = m_Parent->GetComponent<InventoryComponent>();
|
||||
if (inventory) {
|
||||
//get the items inventory:
|
||||
auto items = inventory->GetInventory(eInventoryType::ITEMS);
|
||||
if (items){
|
||||
auto itemMap = items->GetItems();
|
||||
if (!itemMap.empty()){
|
||||
for (const auto& item : itemMap) {
|
||||
//drop the item:
|
||||
if (!item.second) continue;
|
||||
// don't drop the thinkng cap
|
||||
if (item.second->GetLot() == 6086) continue;
|
||||
GameMessages::SendDropClientLoot(m_Parent, source, item.second->GetLot(), 0, m_Parent->GetPosition(), item.second->GetCount());
|
||||
item.second->SetCount(0, false, false);
|
||||
}
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//get character:
|
||||
auto* chars = m_Parent->GetCharacter();
|
||||
if (chars) {
|
||||
auto coins = chars->GetCoins();
|
||||
|
||||
//lose all coins:
|
||||
chars->SetCoins(0, eLootSourceType::LOOT_SOURCE_NONE);
|
||||
|
||||
//drop all coins:
|
||||
GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, coins, m_Parent->GetPosition());
|
||||
}
|
||||
|
||||
// Reload the player since we can't normally reduce uscore from the server and we want the UI to update
|
||||
// do this last so we don't get killed.... again
|
||||
EntityManager::Instance()->DestructEntity(m_Parent);
|
||||
EntityManager::Instance()->ConstructEntity(m_Parent);
|
||||
return;
|
||||
}
|
||||
|
||||
//award the player some u-score:
|
||||
auto* player = EntityManager::Instance()->GetEntity(source);
|
||||
if (player && player->IsPlayer()) {
|
||||
auto* playerStats = player->GetComponent<CharacterComponent>();
|
||||
if (playerStats) {
|
||||
//get the maximum health from this enemy:
|
||||
auto maxHealth = GetMaxHealth();
|
||||
|
||||
int uscore = maxHealth * EntityManager::Instance()->GetHardcoreUscoreEnemiesMultiplier();
|
||||
|
||||
playerStats->SetUScore(playerStats->GetUScore() + uscore);
|
||||
GameMessages::SendModifyLEGOScore(player, player->GetSystemAddress(), uscore, eLootSourceType::LOOT_SOURCE_MISSION);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
#include "tinyxml2.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
namespace CppScripts {
|
||||
class Script;
|
||||
}; //! namespace CppScripts
|
||||
|
||||
/**
|
||||
* Represents the stats of an entity, for example its health, imagination and armor. Also handles factions, which
|
||||
@@ -13,7 +18,7 @@
|
||||
*/
|
||||
class DestroyableComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_DESTROYABLE;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
|
||||
|
||||
DestroyableComponent(Entity* parentEntity);
|
||||
~DestroyableComponent() override;
|
||||
@@ -239,7 +244,7 @@ public:
|
||||
* Sets the multiplier for the explosion that's visible when the bricks fly out when this entity is smashed
|
||||
* @param value the multiplier for the explosion that's visible when the bricks fly out when this entity is smashed
|
||||
*/
|
||||
void SetExplodeFactor(float value);
|
||||
void SetExplodeFactor(float value) { m_ExplodeFactor = value; };
|
||||
|
||||
/**
|
||||
* Returns the current multiplier for explosions
|
||||
@@ -392,16 +397,31 @@ public:
|
||||
void Smash(LWOOBJID source, eKillType killType = eKillType::VIOLENT, const std::u16string& deathType = u"", uint32_t skillID = 0);
|
||||
|
||||
/**
|
||||
* Pushes a layer of immunity to this entity, making it immune for longer
|
||||
* @param stacks the amount of immunity to add
|
||||
* Push or Pop a layer of status immunity to this entity
|
||||
*/
|
||||
void PushImmunity(int32_t stacks = 1);
|
||||
void SetStatusImmunity(
|
||||
const eStateChangeType state,
|
||||
const bool bImmuneToBasicAttack = false,
|
||||
const bool bImmuneToDamageOverTime = false,
|
||||
const bool bImmuneToKnockback = false,
|
||||
const bool bImmuneToInterrupt = false,
|
||||
const bool bImmuneToSpeed = false,
|
||||
const bool bImmuneToImaginationGain = false,
|
||||
const bool bImmuneToImaginationLoss = false,
|
||||
const bool bImmuneToQuickbuildInterrupt = false,
|
||||
const bool bImmuneToPullToPoint = false
|
||||
);
|
||||
|
||||
/**
|
||||
* Pops layers of immunity, making it immune for less longer
|
||||
* @param stacks the number of layers of immunity to remove
|
||||
*/
|
||||
void PopImmunity(int32_t stacks = 1);
|
||||
// Getters for status immunities
|
||||
const bool GetImmuneToBasicAttack() {return m_ImmuneToBasicAttackCount > 0;};
|
||||
const bool GetImmuneToDamageOverTime() {return m_ImmuneToDamageOverTimeCount > 0;};
|
||||
const bool GetImmuneToKnockback() {return m_ImmuneToKnockbackCount > 0;};
|
||||
const bool GetImmuneToInterrupt() {return m_ImmuneToInterruptCount > 0;};
|
||||
const bool GetImmuneToSpeed() {return m_ImmuneToSpeedCount > 0;};
|
||||
const bool GetImmuneToImaginationGain() {return m_ImmuneToImaginationGainCount > 0;};
|
||||
const bool GetImmuneToImaginationLoss() {return m_ImmuneToImaginationLossCount > 0;};
|
||||
const bool GetImmuneToQuickbuildInterrupt() {return m_ImmuneToQuickbuildInterruptCount > 0;};
|
||||
const bool GetImmuneToPullToPoint() {return m_ImmuneToPullToPointCount > 0;};
|
||||
|
||||
/**
|
||||
* Utility to reset all stats to the default stats based on items and completed missions
|
||||
@@ -414,6 +434,28 @@ public:
|
||||
*/
|
||||
void AddOnHitCallback(const std::function<void(Entity*)>& callback);
|
||||
|
||||
/**
|
||||
* Pushes a faction back to the list of factions.
|
||||
* @param value Faction to add to list.
|
||||
*
|
||||
* This method should only be used for testing. Use AddFaction(int32_t, bool) for adding a faction properly.
|
||||
*/
|
||||
void AddFactionNoLookup(int32_t faction) { m_FactionIDs.push_back(faction); };
|
||||
|
||||
/**
|
||||
* Notify subscribed scripts of Damage actions.
|
||||
*
|
||||
* @param attacker The attacking Entity
|
||||
* @param damage The amount of damage that was done
|
||||
*/
|
||||
void NotifySubscribers(Entity* attacker, uint32_t damage);
|
||||
|
||||
void Subscribe(LWOOBJID scriptObjId, CppScripts::Script* scriptToAdd);
|
||||
void Unsubscribe(LWOOBJID scriptObjId);
|
||||
|
||||
// handle hardcode mode drops
|
||||
void DoHardcoreModeDrops(const LWOOBJID source);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Whether or not the health should be serialized
|
||||
@@ -470,11 +512,6 @@ private:
|
||||
*/
|
||||
uint32_t m_AttacksToBlock;
|
||||
|
||||
/**
|
||||
* The layers of immunity this entity has left
|
||||
*/
|
||||
int32_t m_ImmuneStacks;
|
||||
|
||||
/**
|
||||
* The amount of damage that should be reduced from every attack
|
||||
*/
|
||||
@@ -549,6 +586,24 @@ private:
|
||||
* The list of callbacks that will be called when this entity gets hit
|
||||
*/
|
||||
std::vector<std::function<void(Entity*)>> m_OnHitCallbacks;
|
||||
|
||||
/**
|
||||
* The list of scripts subscribed to this components actions
|
||||
*/
|
||||
std::map<LWOOBJID, CppScripts::Script*> m_SubscribedScripts;
|
||||
|
||||
/**
|
||||
* status immunity counters
|
||||
*/
|
||||
uint32_t m_ImmuneToBasicAttackCount;
|
||||
uint32_t m_ImmuneToDamageOverTimeCount;
|
||||
uint32_t m_ImmuneToKnockbackCount;
|
||||
uint32_t m_ImmuneToInterruptCount;
|
||||
uint32_t m_ImmuneToSpeedCount;
|
||||
uint32_t m_ImmuneToImaginationGainCount;
|
||||
uint32_t m_ImmuneToImaginationLossCount;
|
||||
uint32_t m_ImmuneToQuickbuildInterruptCount;
|
||||
uint32_t m_ImmuneToPullToPointCount;
|
||||
};
|
||||
|
||||
#endif // DESTROYABLECOMPONENT_H
|
||||
|
||||
@@ -27,8 +27,16 @@
|
||||
#include "dConfig.h"
|
||||
#include "eItemType.h"
|
||||
#include "eUnequippableActiveType.h"
|
||||
#include "CppScripts.h"
|
||||
#include "eMissionTaskType.h"
|
||||
|
||||
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document) : Component(parent) {
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDInventoryComponentTable.h"
|
||||
#include "CDScriptComponentTable.h"
|
||||
#include "CDObjectSkillsTable.h"
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
|
||||
InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document): Component(parent) {
|
||||
this->m_Dirty = true;
|
||||
this->m_Equipped = {};
|
||||
this->m_Pushed = {};
|
||||
@@ -45,10 +53,10 @@ InventoryComponent::InventoryComponent(Entity* parent, tinyxml2::XMLDocument* do
|
||||
return;
|
||||
}
|
||||
|
||||
auto* compRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
const auto componentId = compRegistryTable->GetByIDAndType(lot, COMPONENT_TYPE_INVENTORY);
|
||||
auto* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
const auto componentId = compRegistryTable->GetByIDAndType(lot, eReplicaComponentType::INVENTORY);
|
||||
|
||||
auto* inventoryComponentTable = CDClientManager::Instance()->GetTable<CDInventoryComponentTable>("InventoryComponent");
|
||||
auto* inventoryComponentTable = CDClientManager::Instance().GetTable<CDInventoryComponentTable>();
|
||||
auto items = inventoryComponentTable->Query([=](const CDInventoryComponent entry) { return entry.id == componentId; });
|
||||
|
||||
auto slot = 0u;
|
||||
@@ -179,7 +187,7 @@ void InventoryComponent::AddItem(
|
||||
inventoryType = Inventory::FindInventoryTypeForLot(lot);
|
||||
}
|
||||
|
||||
auto* missions = static_cast<MissionComponent*>(this->m_Parent->GetComponent(COMPONENT_TYPE_MISSION));
|
||||
auto* missions = static_cast<MissionComponent*>(this->m_Parent->GetComponent(eReplicaComponentType::MISSION));
|
||||
|
||||
auto* inventory = GetInventory(inventoryType);
|
||||
|
||||
@@ -195,7 +203,7 @@ void InventoryComponent::AddItem(
|
||||
auto* item = new Item(lot, inventory, slot, count, config, parent, showFlyingLoot, isModMoveAndEquip, subKey, bound, lootSourceType);
|
||||
|
||||
if (missions != nullptr && !IsTransferInventory(inventoryType)) {
|
||||
missions->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, lot, LWOOBJID_EMPTY, "", count, IsTransferInventory(inventorySourceType));
|
||||
missions->Progress(eMissionTaskType::GATHER, lot, LWOOBJID_EMPTY, "", count, IsTransferInventory(inventorySourceType));
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -209,9 +217,11 @@ void InventoryComponent::AddItem(
|
||||
|
||||
auto stack = static_cast<uint32_t>(info.stackSize);
|
||||
|
||||
bool isBrick = inventoryType == eInventoryType::BRICKS || (stack == 0 && info.itemType == 1);
|
||||
|
||||
// info.itemType of 1 is item type brick
|
||||
if (inventoryType == eInventoryType::BRICKS || (stack == 0 && info.itemType == 1)) {
|
||||
stack = 999;
|
||||
if (isBrick) {
|
||||
stack = UINT32_MAX;
|
||||
} else if (stack == 0) {
|
||||
stack = 1;
|
||||
}
|
||||
@@ -232,7 +242,8 @@ void InventoryComponent::AddItem(
|
||||
}
|
||||
}
|
||||
|
||||
while (left > 0) {
|
||||
// If we have some leftover and we aren't bricks, make a new stack
|
||||
while (left > 0 && (!isBrick || (isBrick && !existing))) {
|
||||
const auto size = std::min(left, stack);
|
||||
|
||||
left -= size;
|
||||
@@ -280,7 +291,7 @@ void InventoryComponent::AddItem(
|
||||
}
|
||||
|
||||
if (missions != nullptr && !IsTransferInventory(inventoryType)) {
|
||||
missions->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, lot, LWOOBJID_EMPTY, "", count - outOfSpace, IsTransferInventory(inventorySourceType));
|
||||
missions->Progress(eMissionTaskType::GATHER, lot, LWOOBJID_EMPTY, "", count - outOfSpace, IsTransferInventory(inventorySourceType));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +338,9 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in
|
||||
|
||||
const auto lot = item->GetLot();
|
||||
|
||||
if (item->GetConfig().empty() && !item->GetBound() || (item->GetBound() && item->GetInfo().isBOP)) {
|
||||
const auto subkey = item->GetSubKey();
|
||||
|
||||
if (subkey == LWOOBJID_EMPTY && item->GetConfig().empty() && (!item->GetBound() || (item->GetBound() && item->GetInfo().isBOP))) {
|
||||
auto left = std::min<uint32_t>(count, origin->GetLotCount(lot));
|
||||
|
||||
while (left > 0) {
|
||||
@@ -358,7 +371,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in
|
||||
|
||||
const auto delta = std::min<uint32_t>(item->GetCount(), count);
|
||||
|
||||
AddItem(lot, delta, eLootSourceType::LOOT_SOURCE_NONE, inventory, config, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, LWOOBJID_EMPTY, origin->GetType(), 0, item->GetBound(), preferredSlot);
|
||||
AddItem(lot, delta, eLootSourceType::LOOT_SOURCE_NONE, inventory, config, LWOOBJID_EMPTY, showFlyingLot, isModMoveAndEquip, subkey, origin->GetType(), 0, item->GetBound(), preferredSlot);
|
||||
|
||||
item->SetCount(item->GetCount() - delta, false, false);
|
||||
}
|
||||
@@ -367,7 +380,7 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in
|
||||
|
||||
if (missionComponent != nullptr) {
|
||||
if (IsTransferInventory(inventory)) {
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, lot, LWOOBJID_EMPTY, "", -static_cast<int32_t>(count));
|
||||
missionComponent->Progress(eMissionTaskType::GATHER, lot, LWOOBJID_EMPTY, "", -static_cast<int32_t>(count));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -605,16 +618,17 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Inventory*> inventories;
|
||||
std::vector<Inventory*> inventoriesToSave;
|
||||
|
||||
// Need to prevent some transfer inventories from being saved
|
||||
for (const auto& pair : this->m_Inventories) {
|
||||
auto* inventory = pair.second;
|
||||
|
||||
if (inventory->GetType() == VENDOR_BUYBACK) {
|
||||
if (inventory->GetType() == VENDOR_BUYBACK || inventory->GetType() == eInventoryType::MODELS_IN_BBB) {
|
||||
continue;
|
||||
}
|
||||
|
||||
inventories.push_back(inventory);
|
||||
inventoriesToSave.push_back(inventory);
|
||||
}
|
||||
|
||||
inventoryElement->SetAttribute("csl", m_Consumable);
|
||||
@@ -629,7 +643,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
|
||||
|
||||
bags->DeleteChildren();
|
||||
|
||||
for (const auto* inventory : inventories) {
|
||||
for (const auto* inventory : inventoriesToSave) {
|
||||
auto* bag = document->NewElement("b");
|
||||
|
||||
bag->SetAttribute("t", inventory->GetType());
|
||||
@@ -648,7 +662,7 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument* document) {
|
||||
|
||||
items->DeleteChildren();
|
||||
|
||||
for (auto* inventory : inventories) {
|
||||
for (auto* inventory : inventoriesToSave) {
|
||||
if (inventory->GetSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -810,7 +824,7 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) {
|
||||
if (character != nullptr && !skipChecks) {
|
||||
// Hacky proximity rocket
|
||||
if (item->GetLot() == 6416) {
|
||||
const auto rocketLauchPads = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_ROCKET_LAUNCH);
|
||||
const auto rocketLauchPads = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::ROCKET_LAUNCH);
|
||||
|
||||
const auto position = m_Parent->GetPosition();
|
||||
|
||||
@@ -834,9 +848,9 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) {
|
||||
const auto type = static_cast<eItemType>(item->GetInfo().itemType);
|
||||
|
||||
|
||||
if (!building && (item->GetLot() == 6086 || type == eItemType::ITEM_TYPE_LOOT_MODEL || type == eItemType::ITEM_TYPE_VEHICLE)) return;
|
||||
if (!building && (item->GetLot() == 6086 || type == eItemType::LOOT_MODEL || type == eItemType::VEHICLE)) return;
|
||||
|
||||
if (type != eItemType::ITEM_TYPE_LOOT_MODEL && type != eItemType::ITEM_TYPE_MODEL) {
|
||||
if (type != eItemType::LOOT_MODEL && type != eItemType::MODEL) {
|
||||
if (!item->GetBound() && !item->GetPreconditionExpression()->Check(m_Parent)) {
|
||||
return;
|
||||
}
|
||||
@@ -861,6 +875,8 @@ void InventoryComponent::EquipItem(Item* item, const bool skipChecks) {
|
||||
|
||||
AddItemSkills(item->GetLot());
|
||||
|
||||
EquipScripts(item);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
@@ -889,6 +905,8 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
||||
|
||||
PurgeProxies(item);
|
||||
|
||||
UnequipScripts(item);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
|
||||
// Trigger property event
|
||||
@@ -898,6 +916,37 @@ void InventoryComponent::UnEquipItem(Item* item) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InventoryComponent::EquipScripts(Item* equippedItem) {
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
if (!compRegistryTable) return;
|
||||
int32_t scriptComponentID = compRegistryTable->GetByIDAndType(equippedItem->GetLot(), eReplicaComponentType::SCRIPT, -1);
|
||||
if (scriptComponentID > -1) {
|
||||
CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable<CDScriptComponentTable>();
|
||||
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||
if (!itemScript) {
|
||||
Game::logger->Log("InventoryComponent", "null script?");
|
||||
}
|
||||
itemScript->OnFactionTriggerItemEquipped(m_Parent, equippedItem->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::UnequipScripts(Item* unequippedItem) {
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
if (!compRegistryTable) return;
|
||||
int32_t scriptComponentID = compRegistryTable->GetByIDAndType(unequippedItem->GetLot(), eReplicaComponentType::SCRIPT, -1);
|
||||
if (scriptComponentID > -1) {
|
||||
CDScriptComponentTable* scriptCompTable = CDClientManager::Instance().GetTable<CDScriptComponentTable>();
|
||||
CDScriptComponent scriptCompData = scriptCompTable->GetByID(scriptComponentID);
|
||||
auto* itemScript = CppScripts::GetScript(m_Parent, scriptCompData.script_name);
|
||||
if (!itemScript) {
|
||||
Game::logger->Log("InventoryComponent", "null script?");
|
||||
}
|
||||
itemScript->OnFactionTriggerItemUnequipped(m_Parent, unequippedItem->GetId());
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::HandlePossession(Item* item) {
|
||||
auto* characterComponent = m_Parent->GetComponent<CharacterComponent>();
|
||||
if (!characterComponent) return;
|
||||
@@ -917,7 +966,7 @@ void InventoryComponent::HandlePossession(Item* item) {
|
||||
return;
|
||||
}
|
||||
|
||||
GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStunState::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
|
||||
GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStateChangeType::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
|
||||
|
||||
// Set the mount Item ID so that we know what were handling
|
||||
possessorComponent->SetMountItemID(item->GetId());
|
||||
@@ -985,6 +1034,7 @@ void InventoryComponent::ApplyBuff(Item* item) const {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Something needs to send the remove buff GameMessage as well when it is unequipping items that would remove buffs.
|
||||
void InventoryComponent::RemoveBuff(Item* item) const {
|
||||
const auto buffs = FindBuffs(item, false);
|
||||
|
||||
@@ -1153,20 +1203,20 @@ void InventoryComponent::RemoveItemSkills(const LOT lot) {
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::TriggerPassiveAbility(PassiveAbilityTrigger trigger) {
|
||||
void InventoryComponent::TriggerPassiveAbility(PassiveAbilityTrigger trigger, Entity* target) {
|
||||
for (auto* set : m_Itemsets) {
|
||||
set->TriggerPassiveAbility(trigger);
|
||||
set->TriggerPassiveAbility(trigger, target);
|
||||
}
|
||||
}
|
||||
|
||||
bool InventoryComponent::HasAnyPassive(const std::vector<ItemSetPassiveAbilityID>& passiveIDs, int32_t equipmentRequirement) const {
|
||||
bool InventoryComponent::HasAnyPassive(const std::vector<eItemSetPassiveAbilityID>& passiveIDs, int32_t equipmentRequirement) const {
|
||||
for (auto* set : m_Itemsets) {
|
||||
if (set->GetEquippedCount() < equipmentRequirement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the set has any of the passive abilities
|
||||
if (std::find(passiveIDs.begin(), passiveIDs.end(), static_cast<ItemSetPassiveAbilityID>(set->GetID())) != passiveIDs.end()) {
|
||||
if (std::find(passiveIDs.begin(), passiveIDs.end(), static_cast<eItemSetPassiveAbilityID>(set->GetID())) != passiveIDs.end()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1242,15 +1292,15 @@ void InventoryComponent::RemoveDatabasePet(LWOOBJID id) {
|
||||
|
||||
BehaviorSlot InventoryComponent::FindBehaviorSlot(const eItemType type) {
|
||||
switch (type) {
|
||||
case eItemType::ITEM_TYPE_HAT:
|
||||
case eItemType::HAT:
|
||||
return BehaviorSlot::Head;
|
||||
case eItemType::ITEM_TYPE_NECK:
|
||||
case eItemType::NECK:
|
||||
return BehaviorSlot::Neck;
|
||||
case eItemType::ITEM_TYPE_LEFT_HAND:
|
||||
case eItemType::LEFT_HAND:
|
||||
return BehaviorSlot::Offhand;
|
||||
case eItemType::ITEM_TYPE_RIGHT_HAND:
|
||||
case eItemType::RIGHT_HAND:
|
||||
return BehaviorSlot::Primary;
|
||||
case eItemType::ITEM_TYPE_CONSUMABLE:
|
||||
case eItemType::CONSUMABLE:
|
||||
return BehaviorSlot::Consumable;
|
||||
default:
|
||||
return BehaviorSlot::Invalid;
|
||||
@@ -1258,11 +1308,11 @@ BehaviorSlot InventoryComponent::FindBehaviorSlot(const eItemType type) {
|
||||
}
|
||||
|
||||
bool InventoryComponent::IsTransferInventory(eInventoryType type) {
|
||||
return type == VENDOR_BUYBACK || type == VAULT_ITEMS || type == VAULT_MODELS || type == TEMP_ITEMS || type == TEMP_MODELS;
|
||||
return type == VENDOR_BUYBACK || type == VAULT_ITEMS || type == VAULT_MODELS || type == TEMP_ITEMS || type == TEMP_MODELS || type == MODELS_IN_BBB;
|
||||
}
|
||||
|
||||
uint32_t InventoryComponent::FindSkill(const LOT lot) {
|
||||
auto* table = CDClientManager::Instance()->GetTable<CDObjectSkillsTable>("ObjectSkills");
|
||||
auto* table = CDClientManager::Instance().GetTable<CDObjectSkillsTable>();
|
||||
|
||||
const auto results = table->Query([=](const CDObjectSkills& entry) {
|
||||
return entry.objectTemplate == static_cast<unsigned int>(lot);
|
||||
@@ -1280,14 +1330,14 @@ uint32_t InventoryComponent::FindSkill(const LOT lot) {
|
||||
std::vector<uint32_t> InventoryComponent::FindBuffs(Item* item, bool castOnEquip) const {
|
||||
std::vector<uint32_t> buffs;
|
||||
if (item == nullptr) return buffs;
|
||||
auto* table = CDClientManager::Instance()->GetTable<CDObjectSkillsTable>("ObjectSkills");
|
||||
auto* behaviors = CDClientManager::Instance()->GetTable<CDSkillBehaviorTable>("SkillBehavior");
|
||||
auto* table = CDClientManager::Instance().GetTable<CDObjectSkillsTable>();
|
||||
auto* behaviors = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
||||
|
||||
const auto results = table->Query([=](const CDObjectSkills& entry) {
|
||||
return entry.objectTemplate == static_cast<unsigned int>(item->GetLot());
|
||||
});
|
||||
|
||||
auto* missions = static_cast<MissionComponent*>(m_Parent->GetComponent(COMPONENT_TYPE_MISSION));
|
||||
auto* missions = static_cast<MissionComponent*>(m_Parent->GetComponent(eReplicaComponentType::MISSION));
|
||||
|
||||
for (const auto& result : results) {
|
||||
if (result.castOnType == 1) {
|
||||
@@ -1300,7 +1350,7 @@ std::vector<uint32_t> InventoryComponent::FindBuffs(Item* item, bool castOnEquip
|
||||
}
|
||||
|
||||
if (missions != nullptr && castOnEquip) {
|
||||
missions->Progress(MissionTaskType::MISSION_TASK_TYPE_SKILL, result.skillID);
|
||||
missions->Progress(eMissionTaskType::USE_SKILL, result.skillID);
|
||||
}
|
||||
|
||||
// If item is not a proxy, add its buff to the added buffs.
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
#include "DatabasePet.h"
|
||||
#include "Component.h"
|
||||
#include "ItemSetPassiveAbility.h"
|
||||
#include "ItemSetPassiveAbilityID.h"
|
||||
#include "eItemSetPassiveAbilityID.h"
|
||||
#include "PossessorComponent.h"
|
||||
#include "eInventoryType.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Entity;
|
||||
class ItemSet;
|
||||
@@ -35,7 +37,7 @@ enum class eItemType : int32_t;
|
||||
class InventoryComponent : public Component
|
||||
{
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_INVENTORY;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
||||
explicit InventoryComponent(Entity* parent, tinyxml2::XMLDocument* document = nullptr);
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
@@ -282,7 +284,7 @@ public:
|
||||
* Triggers one of the passive abilities from the equipped item set
|
||||
* @param trigger the trigger to fire
|
||||
*/
|
||||
void TriggerPassiveAbility(PassiveAbilityTrigger trigger);
|
||||
void TriggerPassiveAbility(PassiveAbilityTrigger trigger, Entity* target = nullptr);
|
||||
|
||||
/**
|
||||
* Returns if the entity has any of the passed passive abilities equipped
|
||||
@@ -290,7 +292,7 @@ public:
|
||||
* @param equipmentRequirement the number of equipment required to be allowed to have the ability
|
||||
* @return if the entity has any of the passed passive abilities equipped
|
||||
*/
|
||||
bool HasAnyPassive(const std::vector<ItemSetPassiveAbilityID>& passiveIDs, int32_t equipmentRequirement) const;
|
||||
bool HasAnyPassive(const std::vector<eItemSetPassiveAbilityID>& passiveIDs, int32_t equipmentRequirement) const;
|
||||
|
||||
/**
|
||||
* Despawns the currently active pet, if any
|
||||
@@ -351,6 +353,20 @@ public:
|
||||
*/
|
||||
static uint32_t FindSkill(LOT lot);
|
||||
|
||||
/**
|
||||
* Call this when you equip an item. This calls OnFactionTriggerItemEquipped for any scripts found on the items.
|
||||
*
|
||||
* @param equippedItem The item script to lookup and call equip on
|
||||
*/
|
||||
void EquipScripts(Item* equippedItem);
|
||||
|
||||
/**
|
||||
* Call this when you unequip an item. This calls OnFactionTriggerItemUnequipped for any scripts found on the items.
|
||||
*
|
||||
* @param unequippedItem The item script to lookup and call unequip on
|
||||
*/
|
||||
void UnequipScripts(Item* unequippedItem);
|
||||
|
||||
~InventoryComponent() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Component.h"
|
||||
#include "Entity.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Component that handles the LOT that is shown in the LUP exhibit in the LUP world. Works by setting a timer and
|
||||
@@ -10,7 +11,7 @@
|
||||
class LUPExhibitComponent : public Component
|
||||
{
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_EXHIBIT;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::EXHIBIT;
|
||||
|
||||
LUPExhibitComponent(Entity* parent);
|
||||
~LUPExhibitComponent();
|
||||
|
||||
@@ -4,9 +4,13 @@
|
||||
#include "CharacterComponent.h"
|
||||
#include "tinyxml2.h"
|
||||
|
||||
#include "CDRewardsTable.h"
|
||||
|
||||
LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component(parent) {
|
||||
m_Parent = parent;
|
||||
m_Level = 1;
|
||||
m_SpeedBase = 500.0f;
|
||||
m_CharacterVersion = eCharacterVersion::LIVE;
|
||||
}
|
||||
|
||||
void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
||||
@@ -16,7 +20,8 @@ void LevelProgressionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
||||
return;
|
||||
}
|
||||
level->SetAttribute("l", m_Level);
|
||||
|
||||
level->SetAttribute("sb", m_SpeedBase);
|
||||
level->SetAttribute("cv", static_cast<uint32_t>(m_CharacterVersion));
|
||||
}
|
||||
|
||||
void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||
@@ -26,7 +31,10 @@ void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||
return;
|
||||
}
|
||||
level->QueryAttribute("l", &m_Level);
|
||||
|
||||
level->QueryAttribute("sb", &m_SpeedBase);
|
||||
uint32_t characterVersion;
|
||||
level->QueryAttribute("cv", &characterVersion);
|
||||
m_CharacterVersion = static_cast<eCharacterVersion>(characterVersion);
|
||||
}
|
||||
|
||||
void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||
@@ -36,7 +44,7 @@ void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool
|
||||
}
|
||||
|
||||
void LevelProgressionComponent::HandleLevelUp() {
|
||||
auto* rewardsTable = CDClientManager::Instance()->GetTable<CDRewardsTable>("Rewards");
|
||||
auto* rewardsTable = CDClientManager::Instance().GetTable<CDRewardsTable>();
|
||||
|
||||
const auto& rewards = rewardsTable->GetByLevelID(m_Level);
|
||||
bool rewardingItem = rewards.size() > 0;
|
||||
@@ -60,7 +68,8 @@ void LevelProgressionComponent::HandleLevelUp() {
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
controllablePhysicsComponent->SetSpeedMultiplier(static_cast<float>(reward->value) / 500.0f);
|
||||
SetSpeedBase(static_cast<float>(reward->value) );
|
||||
controllablePhysicsComponent->SetSpeedMultiplier(GetSpeedBase() / 500.0f);
|
||||
break;
|
||||
case 11:
|
||||
case 12:
|
||||
@@ -72,3 +81,9 @@ void LevelProgressionComponent::HandleLevelUp() {
|
||||
// Tell the client we have finished sending level rewards.
|
||||
if (rewardingItem) GameMessages::NotifyLevelRewards(m_Parent->GetObjectID(), m_Parent->GetSystemAddress(), m_Level, !rewardingItem);
|
||||
}
|
||||
|
||||
void LevelProgressionComponent::SetRetroactiveBaseSpeed(){
|
||||
if (m_Level >= 20) m_SpeedBase = 525.0f;
|
||||
auto* controllablePhysicsComponent = m_Parent->GetComponent<ControllablePhysicsComponent>();
|
||||
if (controllablePhysicsComponent) controllablePhysicsComponent->SetSpeedMultiplier(m_SpeedBase / 500.0f);
|
||||
}
|
||||
|
||||
@@ -3,14 +3,17 @@
|
||||
#include "Entity.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Component.h"
|
||||
#include "eCharacterVersion.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Component that handles level progression and serilization.
|
||||
*
|
||||
*/
|
||||
|
||||
class LevelProgressionComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = eReplicaComponentType::COMPONENT_TYPE_LEVEL_PROGRESSION;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION;
|
||||
|
||||
/**
|
||||
* Constructor for this component
|
||||
@@ -44,11 +47,40 @@ public:
|
||||
*/
|
||||
void SetLevel(uint32_t level) { m_Level = level; m_DirtyLevelInfo = true; }
|
||||
|
||||
/**
|
||||
* Gets the current Speed Base of the entity
|
||||
* @return the current Speed Base of the entity
|
||||
*/
|
||||
const uint32_t GetSpeedBase() const { return m_SpeedBase; }
|
||||
|
||||
/**
|
||||
* Sets the Speed Base of the entity
|
||||
* @param SpeedBase the Speed Base to set
|
||||
*/
|
||||
void SetSpeedBase(uint32_t SpeedBase) { m_SpeedBase = SpeedBase; }
|
||||
|
||||
/**
|
||||
* Gives the player rewards for the last level that they leveled up from
|
||||
*/
|
||||
void HandleLevelUp();
|
||||
|
||||
/**
|
||||
* Gets the current Character Version of the entity
|
||||
* @return the current Character Version of the entity
|
||||
*/
|
||||
const eCharacterVersion GetCharacterVersion() const { return m_CharacterVersion; }
|
||||
|
||||
/**
|
||||
* Sets the Character Version of the entity
|
||||
* @param CharacterVersion the Character Version to set
|
||||
*/
|
||||
void SetCharacterVersion(eCharacterVersion CharacterVersion) { m_CharacterVersion = CharacterVersion; }
|
||||
|
||||
/**
|
||||
* Set the Base Speed retroactively of the entity
|
||||
*/
|
||||
void SetRetroactiveBaseSpeed();
|
||||
|
||||
private:
|
||||
/**
|
||||
* whether the level is dirty
|
||||
@@ -59,4 +91,15 @@ private:
|
||||
* Level of the entity
|
||||
*/
|
||||
uint32_t m_Level;
|
||||
|
||||
/**
|
||||
* The base speed of the entity
|
||||
*/
|
||||
float m_SpeedBase;
|
||||
|
||||
/**
|
||||
* The Character format version
|
||||
*/
|
||||
eCharacterVersion m_CharacterVersion;
|
||||
|
||||
};
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
#include "dZoneManager.h"
|
||||
#include "Mail.h"
|
||||
#include "MissionPrerequisites.h"
|
||||
#include "AchievementCacheKey.h"
|
||||
#include "eMissionState.h"
|
||||
|
||||
// MARK: Mission Component
|
||||
|
||||
std::unordered_map<size_t, std::vector<uint32_t>> MissionComponent::m_AchievementCache = {};
|
||||
std::unordered_map<AchievementCacheKey, std::vector<uint32_t>> MissionComponent::m_AchievementCache = {};
|
||||
|
||||
//! Initializer
|
||||
MissionComponent::MissionComponent(Entity* parent) : Component(parent) {
|
||||
@@ -52,11 +54,11 @@ Mission* MissionComponent::GetMission(const uint32_t missionId) const {
|
||||
}
|
||||
|
||||
|
||||
MissionState MissionComponent::GetMissionState(const uint32_t missionId) const {
|
||||
eMissionState MissionComponent::GetMissionState(const uint32_t missionId) const {
|
||||
auto* mission = GetMission(missionId);
|
||||
|
||||
if (mission == nullptr) {
|
||||
return CanAccept(missionId) ? MissionState::MISSION_STATE_AVAILABLE : MissionState::MISSION_STATE_UNKNOWN;
|
||||
return CanAccept(missionId) ? eMissionState::AVAILABLE : eMissionState::UNKNOWN;
|
||||
}
|
||||
|
||||
return mission->GetMissionState();
|
||||
@@ -142,7 +144,7 @@ void MissionComponent::RemoveMission(uint32_t missionId) {
|
||||
m_Missions.erase(missionId);
|
||||
}
|
||||
|
||||
void MissionComponent::Progress(MissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) {
|
||||
void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) {
|
||||
for (const auto& pair : m_Missions) {
|
||||
auto* mission = pair.second;
|
||||
|
||||
@@ -214,7 +216,7 @@ void MissionComponent::ForceProgressTaskType(const uint32_t missionId, const uin
|
||||
}
|
||||
|
||||
for (auto* element : mission->GetTasks()) {
|
||||
if (element->GetType() != static_cast<MissionTaskType>(taskType)) continue;
|
||||
if (element->GetType() != static_cast<eMissionTaskType>(taskType)) continue;
|
||||
|
||||
element->AddProgress(value);
|
||||
}
|
||||
@@ -252,7 +254,7 @@ void MissionComponent::ForceProgressValue(uint32_t missionId, uint32_t taskType,
|
||||
}
|
||||
|
||||
for (auto* element : mission->GetTasks()) {
|
||||
if (element->GetType() != static_cast<MissionTaskType>(taskType) || !element->InAllTargets(value)) continue;
|
||||
if (element->GetType() != static_cast<eMissionTaskType>(taskType) || !element->InAllTargets(value)) continue;
|
||||
|
||||
element->AddProgress(1);
|
||||
}
|
||||
@@ -263,7 +265,7 @@ void MissionComponent::ForceProgressValue(uint32_t missionId, uint32_t taskType,
|
||||
}
|
||||
|
||||
bool MissionComponent::GetMissionInfo(uint32_t missionId, CDMissions& result) {
|
||||
auto* missionsTable = CDClientManager::Instance()->GetTable<CDMissionsTable>("Missions");
|
||||
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
|
||||
|
||||
const auto missions = missionsTable->Query([=](const CDMissions& entry) {
|
||||
return entry.id == static_cast<int>(missionId);
|
||||
@@ -280,7 +282,7 @@ bool MissionComponent::GetMissionInfo(uint32_t missionId, CDMissions& result) {
|
||||
|
||||
#define MISSION_NEW_METHOD
|
||||
|
||||
bool MissionComponent::LookForAchievements(MissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) {
|
||||
bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) {
|
||||
#ifdef MISSION_NEW_METHOD
|
||||
// Query for achievments, using the cache
|
||||
const auto& result = QueryAchievements(type, value, targets);
|
||||
@@ -317,8 +319,8 @@ bool MissionComponent::LookForAchievements(MissionTaskType type, int32_t value,
|
||||
|
||||
return any;
|
||||
#else
|
||||
auto* missionTasksTable = CDClientManager::Instance()->GetTable<CDMissionTasksTable>("MissionTasks");
|
||||
auto* missionsTable = CDClientManager::Instance()->GetTable<CDMissionsTable>("Missions");
|
||||
auto* missionTasksTable = CDClientManager::Instance().GetTable<CDMissionTasksTable>();
|
||||
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
|
||||
|
||||
auto tasks = missionTasksTable->Query([=](const CDMissionTasks& entry) {
|
||||
return entry.taskType == static_cast<unsigned>(type);
|
||||
@@ -389,14 +391,14 @@ bool MissionComponent::LookForAchievements(MissionTaskType type, int32_t value,
|
||||
#endif
|
||||
}
|
||||
|
||||
const std::vector<uint32_t>& MissionComponent::QueryAchievements(MissionTaskType type, int32_t value, const std::string targets) {
|
||||
const std::vector<uint32_t>& MissionComponent::QueryAchievements(eMissionTaskType type, int32_t value, const std::string targets) {
|
||||
// Create a hash which represent this query for achievements
|
||||
size_t hash = 0;
|
||||
GeneralUtils::hash_combine(hash, type);
|
||||
GeneralUtils::hash_combine(hash, value);
|
||||
GeneralUtils::hash_combine(hash, targets);
|
||||
AchievementCacheKey toFind;
|
||||
toFind.SetType(type);
|
||||
toFind.SetValue(value);
|
||||
toFind.SetTargets(targets);
|
||||
|
||||
const std::unordered_map<size_t, std::vector<uint32_t>>::iterator& iter = m_AchievementCache.find(hash);
|
||||
const auto& iter = m_AchievementCache.find(toFind);
|
||||
|
||||
// Check if this query is cached
|
||||
if (iter != m_AchievementCache.end()) {
|
||||
@@ -404,8 +406,8 @@ const std::vector<uint32_t>& MissionComponent::QueryAchievements(MissionTaskType
|
||||
}
|
||||
|
||||
// Find relevent tables
|
||||
auto* missionTasksTable = CDClientManager::Instance()->GetTable<CDMissionTasksTable>("MissionTasks");
|
||||
auto* missionsTable = CDClientManager::Instance()->GetTable<CDMissionsTable>("Missions");
|
||||
auto* missionTasksTable = CDClientManager::Instance().GetTable<CDMissionTasksTable>();
|
||||
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
|
||||
|
||||
std::vector<uint32_t> result;
|
||||
|
||||
@@ -447,11 +449,9 @@ const std::vector<uint32_t>& MissionComponent::QueryAchievements(MissionTaskType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert into cache
|
||||
m_AchievementCache.insert_or_assign(hash, result);
|
||||
|
||||
return m_AchievementCache.find(hash)->second;
|
||||
m_AchievementCache.insert_or_assign(toFind, result);
|
||||
return m_AchievementCache.find(toFind)->second;
|
||||
}
|
||||
|
||||
bool MissionComponent::RequiresItem(const LOT lot) {
|
||||
@@ -485,7 +485,7 @@ bool MissionComponent::RequiresItem(const LOT lot) {
|
||||
}
|
||||
|
||||
for (auto* task : mission->GetTasks()) {
|
||||
if (task->IsComplete() || task->GetType() != MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION) {
|
||||
if (task->IsComplete() || task->GetType() != eMissionTaskType::GATHER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -497,7 +497,7 @@ bool MissionComponent::RequiresItem(const LOT lot) {
|
||||
}
|
||||
}
|
||||
|
||||
const auto required = LookForAchievements(MissionTaskType::MISSION_TASK_TYPE_ITEM_COLLECTION, lot, false);
|
||||
const auto required = LookForAchievements(eMissionTaskType::GATHER, lot, false);
|
||||
|
||||
return required;
|
||||
}
|
||||
|
||||
@@ -16,15 +16,18 @@
|
||||
#include "CDClientManager.h"
|
||||
#include "CDMissionsTable.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class AchievementCacheKey;
|
||||
|
||||
/**
|
||||
* The mission inventory of an entity. Tracks mission state for each mission that can be accepted and allows for
|
||||
* progression of each of the mission task types (see MissionTaskType).
|
||||
* progression of each of the mission task types (see eMissionTaskType).
|
||||
*/
|
||||
class MissionComponent : public Component
|
||||
{
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_MISSION;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION;
|
||||
|
||||
explicit MissionComponent(Entity* parent);
|
||||
~MissionComponent() override;
|
||||
@@ -50,7 +53,7 @@ public:
|
||||
* @param missionId the ID of the mission to get the mission state for
|
||||
* @return the mission state of the mission specified by the ID
|
||||
*/
|
||||
MissionState GetMissionState(uint32_t missionId) const;
|
||||
eMissionState GetMissionState(uint32_t missionId) const;
|
||||
|
||||
/**
|
||||
* Checks if the entity has all the requirements for accepting the mission specified by the ID.
|
||||
@@ -91,7 +94,7 @@ public:
|
||||
* @param count the number to progress by, for example the number of items
|
||||
* @param ignoreAchievements do not progress achievements
|
||||
*/
|
||||
void Progress(MissionTaskType type, int32_t value, LWOOBJID associate = 0, const std::string& targets = "", int32_t count = 1, bool ignoreAchievements = false);
|
||||
void Progress(eMissionTaskType type, int32_t value, LWOOBJID associate = 0, const std::string& targets = "", int32_t count = 1, bool ignoreAchievements = false);
|
||||
|
||||
/**
|
||||
* Forces progression for a mission and task, ignoring checks
|
||||
@@ -138,7 +141,7 @@ public:
|
||||
* @param count the number of values to progress by (differs by task type)
|
||||
* @return true if a achievement was accepted, false otherwise
|
||||
*/
|
||||
bool LookForAchievements(MissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1);
|
||||
bool LookForAchievements(eMissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1);
|
||||
|
||||
/**
|
||||
* Checks if there's a mission active that requires the collection of the specified LOT
|
||||
@@ -186,13 +189,13 @@ private:
|
||||
* @param targets optional targets to progress with
|
||||
* @return list of mission IDs (achievements) that can be progressed for the given parameters
|
||||
*/
|
||||
static const std::vector<uint32_t>& QueryAchievements(MissionTaskType type, int32_t value, const std::string targets);
|
||||
static const std::vector<uint32_t>& QueryAchievements(eMissionTaskType type, int32_t value, const std::string targets);
|
||||
|
||||
/**
|
||||
* As achievements can be hard to query, we here store a list of all the mission IDs that can be unlocked for a
|
||||
* combination of tasks and values, so that they can be easily re-queried later
|
||||
*/
|
||||
static std::unordered_map<size_t, std::vector<uint32_t>> m_AchievementCache;
|
||||
static std::unordered_map<AchievementCacheKey, std::vector<uint32_t>> m_AchievementCache;
|
||||
|
||||
/**
|
||||
* Order of missions in the UI. This value is incremented by 1
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include "dLogger.h"
|
||||
#include "Game.h"
|
||||
#include "MissionPrerequisites.h"
|
||||
#include "eMissionState.h"
|
||||
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
|
||||
OfferedMission::OfferedMission(const uint32_t missionId, const bool offersMission, const bool acceptsMission) {
|
||||
this->missionId = missionId;
|
||||
@@ -37,15 +40,15 @@ bool OfferedMission::GetAcceptMission() const {
|
||||
//------------------------ MissionOfferComponent below ------------------------
|
||||
|
||||
MissionOfferComponent::MissionOfferComponent(Entity* parent, const LOT parentLot) : Component(parent) {
|
||||
auto* compRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
auto* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
|
||||
auto value = compRegistryTable->GetByIDAndType(parentLot, COMPONENT_TYPE_MISSION_OFFER, -1);
|
||||
auto value = compRegistryTable->GetByIDAndType(parentLot, eReplicaComponentType::MISSION_OFFER, -1);
|
||||
|
||||
if (value != -1) {
|
||||
const uint32_t componentId = value;
|
||||
|
||||
// Now lookup the missions in the MissionNPCComponent table
|
||||
auto* missionNpcComponentTable = CDClientManager::Instance()->GetTable<CDMissionNPCComponentTable>("MissionNPCComponent");
|
||||
auto* missionNpcComponentTable = CDClientManager::Instance().GetTable<CDMissionNPCComponentTable>();
|
||||
|
||||
auto missions = missionNpcComponentTable->Query([=](const CDMissionNPCComponent& entry) {
|
||||
return entry.id == static_cast<unsigned>(componentId);
|
||||
@@ -76,7 +79,7 @@ void MissionOfferComponent::OnUse(Entity* originator) {
|
||||
|
||||
void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifiedMissionId) {
|
||||
// First, get the entity's MissionComponent. If there is not one, then we cannot offer missions to this entity.
|
||||
auto* missionComponent = static_cast<MissionComponent*>(entity->GetComponent(COMPONENT_TYPE_MISSION));
|
||||
auto* missionComponent = static_cast<MissionComponent*>(entity->GetComponent(eReplicaComponentType::MISSION));
|
||||
|
||||
if (!missionComponent) {
|
||||
Game::logger->Log("MissionOfferComponent", "Unable to get mission component for Entity %llu", entity->GetObjectID());
|
||||
@@ -170,10 +173,10 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi
|
||||
for (const auto sample : randomMissionPool) {
|
||||
const auto state = missionComponent->GetMissionState(sample);
|
||||
|
||||
if (state == MissionState::MISSION_STATE_ACTIVE ||
|
||||
state == MissionState::MISSION_STATE_COMPLETE_ACTIVE ||
|
||||
state == MissionState::MISSION_STATE_READY_TO_COMPLETE ||
|
||||
state == MissionState::MISSION_STATE_COMPLETE_READY_TO_COMPLETE ||
|
||||
if (state == eMissionState::ACTIVE ||
|
||||
state == eMissionState::COMPLETE_ACTIVE ||
|
||||
state == eMissionState::READY_TO_COMPLETE ||
|
||||
state == eMissionState::COMPLETE_READY_TO_COMPLETE ||
|
||||
sample == specifiedMissionId) {
|
||||
mission = missionComponent->GetMission(sample);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Component.h"
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Entity;
|
||||
|
||||
@@ -60,7 +61,7 @@ private:
|
||||
*/
|
||||
class MissionOfferComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_MISSION_OFFER;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
|
||||
|
||||
MissionOfferComponent(Entity* parent, LOT parentLot);
|
||||
~MissionOfferComponent() override;
|
||||
|
||||
@@ -10,7 +10,7 @@ ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
||||
|
||||
void ModelComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||
// ItemComponent Serialization. Pets do not get this serialization.
|
||||
if (!m_Parent->HasComponent(COMPONENT_TYPE_PET)) {
|
||||
if (!m_Parent->HasComponent(eReplicaComponentType::PET)) {
|
||||
outBitStream->Write1();
|
||||
outBitStream->Write<LWOOBJID>(m_userModelID != LWOOBJID_EMPTY ? m_userModelID : m_Parent->GetObjectID());
|
||||
outBitStream->Write<int>(0);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "NiPoint3.h"
|
||||
#include "NiQuaternion.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Entity;
|
||||
|
||||
@@ -12,7 +13,7 @@ class Entity;
|
||||
*/
|
||||
class ModelComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_MODEL;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::MODEL;
|
||||
|
||||
ModelComponent(Entity* parent);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Component that belongs to an object that may be modularly built, like cars and rockets. Note that this is not the
|
||||
@@ -11,7 +12,7 @@
|
||||
*/
|
||||
class ModuleAssemblyComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_MODULE_ASSEMBLY;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
|
||||
|
||||
ModuleAssemblyComponent(Entity* MSG_CHAT_INTERNAL_PLAYER_REMOVED_NOTIFICATION);
|
||||
~ModuleAssemblyComponent() override;
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
#include "EntityManager.h"
|
||||
#include "SimplePhysicsComponent.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "CDClientManager.h"
|
||||
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDPhysicsComponentTable.h"
|
||||
|
||||
std::map<LOT, float> MovementAIComponent::m_PhysicsSpeedCache = {};
|
||||
|
||||
@@ -19,7 +23,7 @@ MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) :
|
||||
|
||||
m_BaseCombatAI = nullptr;
|
||||
|
||||
m_BaseCombatAI = reinterpret_cast<BaseCombatAIComponent*>(m_Parent->GetComponent(COMPONENT_TYPE_BASE_COMBAT_AI));
|
||||
m_BaseCombatAI = reinterpret_cast<BaseCombatAIComponent*>(m_Parent->GetComponent(eReplicaComponentType::BASE_COMBAT_AI));
|
||||
|
||||
//Try and fix the insane values:
|
||||
if (m_Info.wanderRadius > 5.0f) m_Info.wanderRadius = m_Info.wanderRadius * 0.5f;
|
||||
@@ -132,7 +136,6 @@ void MovementAIComponent::Update(const float deltaTime) {
|
||||
} else if (m_CurrentPath->pathWaypoints.size() > m_WaypointPathIndex) ArrivedAtPathWaypoint();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if (m_HaltDistance > 0) {
|
||||
@@ -421,13 +424,13 @@ float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
CDComponentsRegistryTable* componentRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::Instance()->GetTable<CDPhysicsComponentTable>("PhysicsComponent");
|
||||
CDComponentsRegistryTable* componentRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::Instance().GetTable<CDPhysicsComponentTable>();
|
||||
|
||||
int32_t componentID;
|
||||
CDPhysicsComponent* physicsComponent = nullptr;
|
||||
|
||||
componentID = componentRegistryTable->GetByIDAndType(lot, COMPONENT_TYPE_CONTROLLABLE_PHYSICS, -1);
|
||||
componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::CONTROLLABLE_PHYSICS, -1);
|
||||
|
||||
if (componentID != -1) {
|
||||
physicsComponent = physicsComponentTable->GetByID(componentID);
|
||||
@@ -435,7 +438,7 @@ float MovementAIComponent::GetBaseSpeed(LOT lot) {
|
||||
goto foundComponent;
|
||||
}
|
||||
|
||||
componentID = componentRegistryTable->GetByIDAndType(lot, COMPONENT_TYPE_SIMPLE_PHYSICS, -1);
|
||||
componentID = componentRegistryTable->GetByIDAndType(lot, eReplicaComponentType::SIMPLE_PHYSICS, -1);
|
||||
|
||||
if (componentID != -1) {
|
||||
physicsComponent = physicsComponentTable->GetByID(componentID);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Game.h"
|
||||
#include "dLogger.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include <vector>
|
||||
|
||||
class ControllablePhysicsComponent;
|
||||
@@ -56,7 +57,7 @@ struct MovementAIInfo {
|
||||
*/
|
||||
class MovementAIComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_MOVEMENT_AI;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
|
||||
|
||||
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
|
||||
~MovementAIComponent() override;
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
#include "GameMessages.h"
|
||||
#include "CppScripts.h"
|
||||
#include "SimplePhysicsComponent.h"
|
||||
#include "Zone.h"
|
||||
|
||||
MoverSubComponent::MoverSubComponent(const NiPoint3& startPos) {
|
||||
mPosition = {};
|
||||
|
||||
mState = MovementPlatformState::Stopped;
|
||||
mState = eMovementPlatformState::Stopped;
|
||||
mDesiredWaypointIndex = 0; // -1;
|
||||
mInReverse = false;
|
||||
mShouldStopAtDesiredWaypoint = false;
|
||||
@@ -127,7 +128,7 @@ void MovingPlatformComponent::OnCompleteRebuild() {
|
||||
StartPathing();
|
||||
}
|
||||
|
||||
void MovingPlatformComponent::SetMovementState(MovementPlatformState value) {
|
||||
void MovingPlatformComponent::SetMovementState(eMovementPlatformState value) {
|
||||
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
||||
|
||||
subComponent->mState = value;
|
||||
@@ -152,7 +153,7 @@ void MovingPlatformComponent::StartPathing() {
|
||||
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
||||
|
||||
subComponent->mShouldStopAtDesiredWaypoint = true;
|
||||
subComponent->mState = MovementPlatformState::Stationary;
|
||||
subComponent->mState = eMovementPlatformState::Stationary;
|
||||
|
||||
NiPoint3 targetPosition;
|
||||
|
||||
@@ -174,7 +175,7 @@ void MovingPlatformComponent::StartPathing() {
|
||||
}
|
||||
|
||||
m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] {
|
||||
SetMovementState(MovementPlatformState::Moving);
|
||||
SetMovementState(eMovementPlatformState::Moving);
|
||||
});
|
||||
|
||||
const auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5f;
|
||||
@@ -199,7 +200,7 @@ void MovingPlatformComponent::StartPathing() {
|
||||
void MovingPlatformComponent::ContinuePathing() {
|
||||
auto* subComponent = static_cast<MoverSubComponent*>(m_MoverSubComponent);
|
||||
|
||||
subComponent->mState = MovementPlatformState::Stationary;
|
||||
subComponent->mState = eMovementPlatformState::Stationary;
|
||||
|
||||
subComponent->mCurrentWaypointIndex = subComponent->mNextWaypointIndex;
|
||||
|
||||
@@ -282,7 +283,7 @@ void MovingPlatformComponent::ContinuePathing() {
|
||||
m_Parent->CancelCallbackTimers();
|
||||
|
||||
m_Parent->AddCallbackTimer(subComponent->mWaitTime, [this] {
|
||||
SetMovementState(MovementPlatformState::Moving);
|
||||
SetMovementState(eMovementPlatformState::Moving);
|
||||
});
|
||||
|
||||
auto travelTime = Vector3::Distance(targetPosition, subComponent->mPosition) / subComponent->mSpeed + 1.5;
|
||||
@@ -313,7 +314,7 @@ void MovingPlatformComponent::StopPathing() {
|
||||
|
||||
m_PathingStopped = true;
|
||||
|
||||
subComponent->mState = MovementPlatformState::Stopped;
|
||||
subComponent->mState = eMovementPlatformState::Stopped;
|
||||
subComponent->mDesiredWaypointIndex = -1;
|
||||
subComponent->mShouldStopAtDesiredWaypoint = false;
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#include "dCommonVars.h"
|
||||
#include "EntityManager.h"
|
||||
#include "Component.h"
|
||||
#include "eMovementPlatformState.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Path;
|
||||
|
||||
/**
|
||||
* Different types of available platforms
|
||||
@@ -26,16 +30,6 @@ enum class eMoverSubComponentType : uint32_t {
|
||||
simpleMover = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* The different types of platform movement state, supposedly a bitmap
|
||||
*/
|
||||
enum class MovementPlatformState : uint32_t
|
||||
{
|
||||
Moving = 0b00010,
|
||||
Stationary = 0b11001,
|
||||
Stopped = 0b01100
|
||||
};
|
||||
|
||||
/**
|
||||
* Sub component for moving platforms that determine the actual current movement state
|
||||
*/
|
||||
@@ -49,7 +43,7 @@ public:
|
||||
/**
|
||||
* The state the platform is currently in
|
||||
*/
|
||||
MovementPlatformState mState = MovementPlatformState::Stationary;
|
||||
eMovementPlatformState mState = eMovementPlatformState::Stationary;
|
||||
|
||||
/**
|
||||
* The waypoint this platform currently wants to traverse to
|
||||
@@ -112,7 +106,7 @@ public:
|
||||
*/
|
||||
class MovingPlatformComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_MOVING_PLATFORM;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM;
|
||||
|
||||
MovingPlatformComponent(Entity* parent, const std::string& pathName);
|
||||
~MovingPlatformComponent() override;
|
||||
@@ -133,7 +127,7 @@ public:
|
||||
* Updates the movement state for the moving platform
|
||||
* @param value the movement state to set
|
||||
*/
|
||||
void SetMovementState(MovementPlatformState value);
|
||||
void SetMovementState(eMovementPlatformState value);
|
||||
|
||||
/**
|
||||
* Instructs the moving platform to go to some waypoint
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
#include "dConfig.h"
|
||||
#include "dChatFilter.h"
|
||||
#include "Database.h"
|
||||
#include "EntityInfo.h"
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
std::unordered_map<LOT, PetComponent::PetPuzzleData> PetComponent::buildCache{};
|
||||
std::unordered_map<LWOOBJID, LWOOBJID> PetComponent::currentActivities{};
|
||||
@@ -59,7 +62,7 @@ std::map<LOT, uint32_t> PetComponent::petFlags = {
|
||||
{ 13067, 838 }, // Skeleton dragon
|
||||
};
|
||||
|
||||
PetComponent::PetComponent(Entity* parent, uint32_t componentId) : Component(parent) {
|
||||
PetComponent::PetComponent(Entity* parent, uint32_t componentId): Component(parent) {
|
||||
m_ComponentId = componentId;
|
||||
|
||||
m_Interaction = LWOOBJID_EMPTY;
|
||||
@@ -118,21 +121,23 @@ void PetComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpd
|
||||
outBitStream->Write(m_Owner);
|
||||
}
|
||||
|
||||
outBitStream->Write(tamed);
|
||||
if (tamed) {
|
||||
outBitStream->Write(m_ModerationStatus);
|
||||
if (bIsInitialUpdate) {
|
||||
outBitStream->Write(tamed);
|
||||
if (tamed) {
|
||||
outBitStream->Write(m_ModerationStatus);
|
||||
|
||||
const auto nameData = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
const auto ownerNameData = GeneralUtils::UTF8ToUTF16(m_OwnerName);
|
||||
const auto nameData = GeneralUtils::UTF8ToUTF16(m_Name);
|
||||
const auto ownerNameData = GeneralUtils::UTF8ToUTF16(m_OwnerName);
|
||||
|
||||
outBitStream->Write(static_cast<uint8_t>(nameData.size()));
|
||||
for (const auto c : nameData) {
|
||||
outBitStream->Write(c);
|
||||
}
|
||||
outBitStream->Write(static_cast<uint8_t>(nameData.size()));
|
||||
for (const auto c : nameData) {
|
||||
outBitStream->Write(c);
|
||||
}
|
||||
|
||||
outBitStream->Write(static_cast<uint8_t>(ownerNameData.size()));
|
||||
for (const auto c : ownerNameData) {
|
||||
outBitStream->Write(c);
|
||||
outBitStream->Write(static_cast<uint8_t>(ownerNameData.size()));
|
||||
for (const auto c : ownerNameData) {
|
||||
outBitStream->Write(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -599,7 +604,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
auto* missionComponent = tamer->GetComponent<MissionComponent>();
|
||||
|
||||
if (missionComponent != nullptr) {
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_PET_TAMING, m_Parent->GetLOT());
|
||||
missionComponent->Progress(eMissionTaskType::PET_TAMING, m_Parent->GetLOT());
|
||||
}
|
||||
|
||||
SetStatus(1);
|
||||
@@ -916,16 +921,16 @@ void PetComponent::AddDrainImaginationTimer(Item* item, bool fromTaming) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are out of imagination despawn the pet.
|
||||
if (playerDestroyableComponent->GetImagination() == 0) {
|
||||
this->Deactivate();
|
||||
auto playerEntity = playerDestroyableComponent->GetParent();
|
||||
if (!playerEntity) return;
|
||||
// If we are out of imagination despawn the pet.
|
||||
if (playerDestroyableComponent->GetImagination() == 0) {
|
||||
this->Deactivate();
|
||||
auto playerEntity = playerDestroyableComponent->GetParent();
|
||||
if (!playerEntity) return;
|
||||
|
||||
GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), UseItemResponse::NoImaginationForPet);
|
||||
}
|
||||
GameMessages::SendUseItemRequirementsResponse(playerEntity->GetObjectID(), playerEntity->GetSystemAddress(), UseItemResponse::NoImaginationForPet);
|
||||
}
|
||||
|
||||
this->AddDrainImaginationTimer(item);
|
||||
this->AddDrainImaginationTimer(item);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -983,7 +988,7 @@ void PetComponent::Command(NiPoint3 position, LWOOBJID source, int32_t commandTy
|
||||
// TODO: Go to player
|
||||
}
|
||||
|
||||
if (owner->GetGMLevel() >= GAME_MASTER_LEVEL_DEVELOPER) {
|
||||
if (owner->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
|
||||
ChatPackets::SendSystemMessage(owner->GetSystemAddress(), u"Commmand Type: " + (GeneralUtils::to_u16string(commandType)) + u" - Type Id: " + (GeneralUtils::to_u16string(typeId)));
|
||||
}
|
||||
}
|
||||
@@ -1075,7 +1080,7 @@ void PetComponent::SetPetNameForModeration(const std::string& petName) {
|
||||
int approved = 1; //default, in mod
|
||||
|
||||
//Make sure that the name isn't already auto-approved:
|
||||
if (Game::chatFilter->IsSentenceOkay(petName, 0).empty()) {
|
||||
if (Game::chatFilter->IsSentenceOkay(petName, eGameMasterLevel::CIVILIAN).empty()) {
|
||||
approved = 2; //approved
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "MovementAIComponent.h"
|
||||
#include "Component.h"
|
||||
#include "Preconditions.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
enum class PetAbilityType
|
||||
{
|
||||
@@ -20,7 +21,7 @@ enum class PetAbilityType
|
||||
class PetComponent : public Component
|
||||
{
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PET;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PET;
|
||||
|
||||
explicit PetComponent(Entity* parentEntity, uint32_t componentId);
|
||||
~PetComponent() override;
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
#include "EntityManager.h"
|
||||
#include "ControllablePhysicsComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "ePhysicsEffectType.h"
|
||||
|
||||
#include "CDClientManager.h"
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDPhysicsComponentTable.h"
|
||||
#include "dServer.h"
|
||||
#include "EntityInfo.h"
|
||||
|
||||
#include "dpWorld.h"
|
||||
#include "dpEntity.h"
|
||||
@@ -35,7 +37,7 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : Component(par
|
||||
m_PositionInfoDirty = false;
|
||||
|
||||
m_IsPhysicsEffectActive = false;
|
||||
m_EffectType = 0;
|
||||
m_EffectType = ePhysicsEffectType::PUSH;
|
||||
m_DirectionalMultiplier = 0.0f;
|
||||
|
||||
m_MinMax = false;
|
||||
@@ -142,10 +144,10 @@ PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent) : Component(par
|
||||
*/
|
||||
|
||||
if (!m_HasCreatedPhysics) {
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
auto componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), COMPONENT_TYPE_PHANTOM_PHYSICS);
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
auto componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), eReplicaComponentType::PHANTOM_PHYSICS);
|
||||
|
||||
CDPhysicsComponentTable* physComp = CDClientManager::Instance()->GetTable<CDPhysicsComponentTable>("PhysicsComponent");
|
||||
CDPhysicsComponentTable* physComp = CDClientManager::Instance().GetTable<CDPhysicsComponentTable>();
|
||||
|
||||
if (physComp == nullptr) return;
|
||||
|
||||
@@ -252,10 +254,10 @@ void PhantomPhysicsComponent::CreatePhysics() {
|
||||
y = m_Parent->GetVar<float>(u"primitiveModelValueY");
|
||||
z = m_Parent->GetVar<float>(u"primitiveModelValueZ");
|
||||
} else {
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
auto componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), COMPONENT_TYPE_PHANTOM_PHYSICS);
|
||||
CDComponentsRegistryTable* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
auto componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), eReplicaComponentType::PHANTOM_PHYSICS);
|
||||
|
||||
CDPhysicsComponentTable* physComp = CDClientManager::Instance()->GetTable<CDPhysicsComponentTable>("PhysicsComponent");
|
||||
CDPhysicsComponentTable* physComp = CDClientManager::Instance().GetTable<CDPhysicsComponentTable>();
|
||||
|
||||
if (physComp == nullptr) return;
|
||||
|
||||
@@ -404,7 +406,7 @@ void PhantomPhysicsComponent::SetDirectionalMultiplier(float mul) {
|
||||
m_EffectInfoDirty = true;
|
||||
}
|
||||
|
||||
void PhantomPhysicsComponent::SetEffectType(uint32_t type) {
|
||||
void PhantomPhysicsComponent::SetEffectType(ePhysicsEffectType type) {
|
||||
m_EffectType = type;
|
||||
m_EffectInfoDirty = true;
|
||||
}
|
||||
|
||||
@@ -12,10 +12,12 @@
|
||||
#include "CppScripts.h"
|
||||
#include "InvalidScript.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class LDFBaseData;
|
||||
class Entity;
|
||||
class dpEntity;
|
||||
enum class ePhysicsEffectType : uint32_t ;
|
||||
|
||||
/**
|
||||
* Allows the creation of phantom physics for an entity: a physics object that is generally invisible but can be
|
||||
@@ -25,7 +27,7 @@ class dpEntity;
|
||||
*/
|
||||
class PhantomPhysicsComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PHANTOM_PHYSICS;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
|
||||
|
||||
PhantomPhysicsComponent(Entity* parent);
|
||||
~PhantomPhysicsComponent() override;
|
||||
@@ -102,13 +104,13 @@ public:
|
||||
* Returns the effect that's currently active, defaults to 0
|
||||
* @return the effect that's currently active
|
||||
*/
|
||||
uint32_t GetEffectType() const { return m_EffectType; }
|
||||
ePhysicsEffectType GetEffectType() const { return m_EffectType; }
|
||||
|
||||
/**
|
||||
* Sets the effect that's currently active
|
||||
* @param type the effect to set
|
||||
*/
|
||||
void SetEffectType(uint32_t type);
|
||||
void SetEffectType(ePhysicsEffectType type);
|
||||
|
||||
/**
|
||||
* Returns the Physics entity for the component
|
||||
@@ -167,7 +169,7 @@ private:
|
||||
/**
|
||||
* The physics effect that's currently active, defaults to 0
|
||||
*/
|
||||
uint32_t m_EffectType;
|
||||
ePhysicsEffectType m_EffectType;
|
||||
|
||||
/**
|
||||
* A scaling multiplier to add to the directional vector
|
||||
|
||||
@@ -7,8 +7,8 @@ PlayerForcedMovementComponent::PlayerForcedMovementComponent(Entity* parent) : C
|
||||
PlayerForcedMovementComponent::~PlayerForcedMovementComponent() {}
|
||||
|
||||
void PlayerForcedMovementComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||
outBitStream->Write(m_DirtyInfo);
|
||||
if (m_DirtyInfo) {
|
||||
outBitStream->Write(m_DirtyInfo || bIsInitialUpdate);
|
||||
if (m_DirtyInfo || bIsInitialUpdate) {
|
||||
outBitStream->Write(m_PlayerOnRail);
|
||||
outBitStream->Write(m_ShowBillboard);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Component that handles player forced movement
|
||||
@@ -9,7 +10,7 @@
|
||||
*/
|
||||
class PlayerForcedMovementComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = eReplicaComponentType::COMPONENT_TYPE_PLAYER_FORCED_MOVEMENT;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PLAYER_FORCED_MOVEMENT;
|
||||
|
||||
/**
|
||||
* Constructor for this component
|
||||
|
||||
@@ -34,8 +34,8 @@ void PossessableComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsIn
|
||||
outBitStream->Write(m_Possessor != LWOOBJID_EMPTY);
|
||||
if (m_Possessor != LWOOBJID_EMPTY) outBitStream->Write(m_Possessor);
|
||||
|
||||
outBitStream->Write(m_AnimationFlag != eAnimationFlags::IDLE_INVALID);
|
||||
if (m_AnimationFlag != eAnimationFlags::IDLE_INVALID) outBitStream->Write(m_AnimationFlag);
|
||||
outBitStream->Write(m_AnimationFlag != eAnimationFlags::IDLE_NONE);
|
||||
if (m_AnimationFlag != eAnimationFlags::IDLE_NONE) outBitStream->Write(m_AnimationFlag);
|
||||
|
||||
outBitStream->Write(m_ImmediatelyDepossess);
|
||||
m_ImmediatelyDepossess = false; // reset flag
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "Item.h"
|
||||
#include "PossessorComponent.h"
|
||||
#include "eAninmationFlags.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Represents an entity that can be controlled by some other entity, generally used by cars to indicate that some
|
||||
@@ -13,7 +14,7 @@
|
||||
*/
|
||||
class PossessableComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_POSSESSABLE;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE;
|
||||
|
||||
PossessableComponent(Entity* parentEntity, uint32_t componentId);
|
||||
|
||||
@@ -109,7 +110,7 @@ private:
|
||||
* @brief What animaiton flag to use
|
||||
*
|
||||
*/
|
||||
eAnimationFlags m_AnimationFlag = eAnimationFlags::IDLE_INVALID;
|
||||
eAnimationFlags m_AnimationFlag = eAnimationFlags::IDLE_NONE;
|
||||
|
||||
/**
|
||||
* @brief Should this be immediately depossessed
|
||||
|
||||
@@ -54,7 +54,7 @@ void PossessorComponent::Mount(Entity* mount) {
|
||||
// GM's to send
|
||||
GameMessages::SendSetJetPackMode(m_Parent, false);
|
||||
GameMessages::SendVehicleUnlockInput(mount->GetObjectID(), false, m_Parent->GetSystemAddress());
|
||||
GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStunState::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
|
||||
GameMessages::SendSetStunned(m_Parent->GetObjectID(), eStateChangeType::PUSH, m_Parent->GetSystemAddress(), LWOOBJID_EMPTY, true, false, true, false, false, false, false, true, true, true, true, true, true, true, true, true);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
EntityManager::Instance()->SerializeEntity(mount);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
// possession types
|
||||
enum class ePossessionType : uint8_t {
|
||||
@@ -17,7 +18,7 @@ enum class ePossessionType : uint8_t {
|
||||
*/
|
||||
class PossessorComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_POSSESSOR;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR;
|
||||
|
||||
PossessorComponent(Entity* parent);
|
||||
~PossessorComponent() override;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
struct PropertyState {
|
||||
LWOOBJID ownerID;
|
||||
@@ -21,7 +22,7 @@ struct PropertyState {
|
||||
*/
|
||||
class PropertyComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PROPERTY;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY;
|
||||
explicit PropertyComponent(Entity* parentEntity);
|
||||
~PropertyComponent() override;
|
||||
[[nodiscard]] PropertyState* GetPropertyState() const { return m_PropertyState; };
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
#include "CharacterComponent.h"
|
||||
#include "UserManager.h"
|
||||
#include "dLogger.h"
|
||||
#include "AMFFormat.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
|
||||
PropertyEntranceComponent::PropertyEntranceComponent(uint32_t componentID, Entity* parent) : Component(parent) {
|
||||
this->propertyQueries = {};
|
||||
|
||||
auto table = CDClientManager::Instance()->GetTable<CDPropertyEntranceComponentTable>("PropertyEntranceComponent");
|
||||
auto table = CDClientManager::Instance().GetTable<CDPropertyEntranceComponentTable>();
|
||||
const auto& entry = table->GetByID(componentID);
|
||||
|
||||
this->m_MapID = entry.mapID;
|
||||
@@ -270,7 +272,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
|
||||
|
||||
bool isModeratorApproved = propertyEntry->getBoolean(10);
|
||||
|
||||
if (!isModeratorApproved && entity->GetGMLevel() >= GAME_MASTER_LEVEL_LEAD_MODERATOR) {
|
||||
if (!isModeratorApproved && entity->GetGMLevel() >= eGameMasterLevel::LEAD_MODERATOR) {
|
||||
propertyName = "[AWAITING APPROVAL]";
|
||||
propertyDescription = "[AWAITING APPROVAL]";
|
||||
isModeratorApproved = true;
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
#include "Entity.h"
|
||||
#include "EntityManager.h"
|
||||
#include "GameMessages.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Represents the launch pad that's used to select and browse properties
|
||||
*/
|
||||
class PropertyEntranceComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PROPERTY_ENTRANCE;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE;
|
||||
explicit PropertyEntranceComponent(uint32_t componentID, Entity* parent);
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "Player.h"
|
||||
#include "RocketLaunchpadControlComponent.h"
|
||||
#include "PropertyEntranceComponent.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "eMissionTaskType.h"
|
||||
|
||||
#include <vector>
|
||||
#include "CppScripts.h"
|
||||
@@ -200,6 +202,16 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
|
||||
// If we are not on our clone do not allow us to claim the property
|
||||
if (propertyCloneId != playerCloneId) return false;
|
||||
|
||||
std::string name = zone->GetZoneName();
|
||||
std::string description = "";
|
||||
|
||||
auto prop_path = zone->GetPath(m_Parent->GetVarAsString(u"propertyName"));
|
||||
|
||||
if (prop_path){
|
||||
if (!prop_path->property.displayName.empty()) name = prop_path->property.displayName;
|
||||
description = prop_path->property.displayDesc;
|
||||
}
|
||||
|
||||
SetOwnerId(playerId);
|
||||
|
||||
propertyId = ObjectIDManager::GenerateRandomObjectID();
|
||||
@@ -207,14 +219,15 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
|
||||
auto* insertion = Database::CreatePreppedStmt(
|
||||
"INSERT INTO properties"
|
||||
"(id, owner_id, template_id, clone_id, name, description, rent_amount, rent_due, privacy_option, last_updated, time_claimed, rejection_reason, reputation, zone_id, performance_cost)"
|
||||
"VALUES (?, ?, ?, ?, ?, '', 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?, 0.0)"
|
||||
"VALUES (?, ?, ?, ?, ?, ?, 0, 0, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '', 0, ?, 0.0)"
|
||||
);
|
||||
insertion->setUInt64(1, propertyId);
|
||||
insertion->setUInt64(2, (uint32_t)playerId);
|
||||
insertion->setUInt(3, templateId);
|
||||
insertion->setUInt64(4, playerCloneId);
|
||||
insertion->setString(5, zone->GetZoneName().c_str());
|
||||
insertion->setInt(6, propertyZoneId);
|
||||
insertion->setString(5, name.c_str());
|
||||
insertion->setString(6, description.c_str());
|
||||
insertion->setInt(7, propertyZoneId);
|
||||
|
||||
// Try and execute the query, print an error if it fails.
|
||||
try {
|
||||
@@ -242,7 +255,7 @@ void PropertyManagementComponent::OnStartBuilding() {
|
||||
|
||||
LWOMAPID zoneId = 1100;
|
||||
|
||||
const auto entrance = EntityManager::Instance()->GetEntitiesByComponent(COMPONENT_TYPE_PROPERTY_ENTRANCE);
|
||||
const auto entrance = EntityManager::Instance()->GetEntitiesByComponent(eReplicaComponentType::PROPERTY_ENTRANCE);
|
||||
|
||||
originalPrivacyOption = privacyOption;
|
||||
|
||||
@@ -392,7 +405,7 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
||||
});
|
||||
// Progress place model missions
|
||||
auto missionComponent = entity->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_PLACE_MODEL, 0);
|
||||
if (missionComponent != nullptr) missionComponent->Progress(eMissionTaskType::PLACE_MODEL, 0);
|
||||
}
|
||||
|
||||
void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int deleteReason) {
|
||||
@@ -463,7 +476,7 @@ void PropertyManagementComponent::DeleteModel(const LWOOBJID id, const int delet
|
||||
settings.push_back(propertyObjectID);
|
||||
settings.push_back(modelType);
|
||||
|
||||
inventoryComponent->AddItem(6662, 1, eLootSourceType::LOOT_SOURCE_DELETION, eInventoryType::HIDDEN, settings, LWOOBJID_EMPTY, false, false, spawnerId);
|
||||
inventoryComponent->AddItem(6662, 1, eLootSourceType::LOOT_SOURCE_DELETION, eInventoryType::MODELS_IN_BBB, settings, LWOOBJID_EMPTY, false, false, spawnerId);
|
||||
auto* item = inventoryComponent->FindItemBySubKey(spawnerId);
|
||||
|
||||
if (item == nullptr) {
|
||||
@@ -706,7 +719,7 @@ void PropertyManagementComponent::Save() {
|
||||
insertion->setDouble(9, rotation.y);
|
||||
insertion->setDouble(10, rotation.z);
|
||||
insertion->setDouble(11, rotation.w);
|
||||
insertion->setString(12, "Objects_" + std::to_string(entity->GetLOT()) + "_name"); // Model name. TODO make this customizable
|
||||
insertion->setString(12, ("Objects_" + std::to_string(entity->GetLOT()) + "_name").c_str()); // Model name. TODO make this customizable
|
||||
insertion->setString(13, ""); // Model description. TODO implement this.
|
||||
insertion->setDouble(14, 0); // behavior 1. TODO implement this.
|
||||
insertion->setDouble(15, 0); // behavior 2. TODO implement this.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <chrono>
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Information regarding which players may visit this property
|
||||
@@ -31,7 +32,7 @@ enum class PropertyPrivacyOption
|
||||
class PropertyManagementComponent : public Component
|
||||
{
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PROPERTY_MANAGEMENT;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT;
|
||||
PropertyManagementComponent(Entity* parent);
|
||||
static PropertyManagementComponent* Instance();
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* The property guard that stands on a property before it's claimed, allows entities to attempt claiming this property.
|
||||
@@ -9,7 +10,7 @@
|
||||
class PropertyVendorComponent : public Component
|
||||
{
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PROPERTY_VENDOR;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR;
|
||||
explicit PropertyVendorComponent(Entity* parent);
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "dpWorld.h"
|
||||
#include "dpEntity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Utility component for detecting how close entities are to named proximities for this entity. Allows you to store
|
||||
@@ -18,7 +19,7 @@
|
||||
*/
|
||||
class ProximityMonitorComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PROXIMITY_MONITOR;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
|
||||
|
||||
ProximityMonitorComponent(Entity* parentEntity, int smallRadius = -1, int largeRadius = -1);
|
||||
~ProximityMonitorComponent() override;
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
#include "Player.h"
|
||||
#include "PossessableComponent.h"
|
||||
#include "PossessorComponent.h"
|
||||
#include "RacingTaskParam.h"
|
||||
#include "eRacingTaskParam.h"
|
||||
#include "Spawner.h"
|
||||
#include "VehiclePhysicsComponent.h"
|
||||
#include "dServer.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "dConfig.h"
|
||||
#include "Loot.h"
|
||||
#include "eMissionTaskType.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846264338327950288
|
||||
@@ -98,7 +100,7 @@ void RacingControlComponent::OnPlayerLoaded(Entity* player) {
|
||||
}
|
||||
|
||||
void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
||||
bool initialLoad) {
|
||||
uint32_t positionNumber, bool initialLoad) {
|
||||
// Load the player's vehicle.
|
||||
|
||||
if (player == nullptr) {
|
||||
@@ -126,33 +128,18 @@ void RacingControlComponent::LoadPlayerVehicle(Entity* player,
|
||||
auto* path = dZoneManager::Instance()->GetZone()->GetPath(
|
||||
GeneralUtils::UTF16ToWTF8(m_PathName));
|
||||
|
||||
auto startPosition = path->pathWaypoints[0].position + NiPoint3::UNIT_Y * 3;
|
||||
|
||||
const auto spacing = 15;
|
||||
|
||||
// This sometimes spawns the vehicle out of the map if there are lots of
|
||||
// players loaded.
|
||||
|
||||
const auto range = m_LoadedPlayers * spacing;
|
||||
|
||||
startPosition =
|
||||
startPosition + NiPoint3::UNIT_Z * ((m_LeadingPlayer / 2) +
|
||||
m_RacingPlayers.size() * spacing);
|
||||
|
||||
auto startRotation =
|
||||
NiQuaternion::LookAt(startPosition, startPosition + NiPoint3::UNIT_X);
|
||||
|
||||
auto angles = startRotation.GetEulerAngles();
|
||||
|
||||
angles.y -= M_PI;
|
||||
|
||||
startRotation = NiQuaternion::FromEulerAngles(angles);
|
||||
|
||||
Game::logger->Log("RacingControlComponent",
|
||||
"Start position <%f, %f, %f>, <%f, %f, %f>",
|
||||
startPosition.x, startPosition.y, startPosition.z,
|
||||
angles.x * (180.0f / M_PI), angles.y * (180.0f / M_PI),
|
||||
angles.z * (180.0f / M_PI));
|
||||
auto spawnPointEntities = EntityManager::Instance()->GetEntitiesByLOT(4843);
|
||||
auto startPosition = NiPoint3::ZERO;
|
||||
auto startRotation = NiQuaternion::IDENTITY;
|
||||
const std::string placementAsString = std::to_string(positionNumber);
|
||||
for (auto entity : spawnPointEntities) {
|
||||
if (!entity) continue;
|
||||
if (entity->GetVarAsString(u"placement") == placementAsString) {
|
||||
startPosition = entity->GetPosition();
|
||||
startRotation = entity->GetRotation();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the player is at the correct position.
|
||||
|
||||
@@ -319,30 +306,58 @@ void RacingControlComponent::OnRequestDie(Entity* player) {
|
||||
auto* vehicle =
|
||||
EntityManager::Instance()->GetEntity(racingPlayer.vehicleID);
|
||||
|
||||
if (vehicle == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (!vehicle) return;
|
||||
|
||||
if (!racingPlayer.noSmashOnReload) {
|
||||
racingPlayer.smashedTimes++;
|
||||
GameMessages::SendDie(vehicle, vehicle->GetObjectID(), LWOOBJID_EMPTY, true,
|
||||
VIOLENT, u"", 0, 0, 90.0f, false, true, 0);
|
||||
|
||||
auto* destroyableComponent = vehicle->GetComponent<DestroyableComponent>();
|
||||
uint32_t respawnImagination = 0;
|
||||
// Reset imagination to half its current value, rounded up to the nearest value divisible by 10, as it was done in live.
|
||||
// Do not actually change the value yet. Do that on respawn.
|
||||
if (destroyableComponent) {
|
||||
respawnImagination = static_cast<int32_t>(ceil(destroyableComponent->GetImagination() / 2.0f / 10.0f)) * 10.0f;
|
||||
GameMessages::SendSetResurrectRestoreValues(vehicle, -1, -1, respawnImagination);
|
||||
}
|
||||
|
||||
// Respawn the player in 2 seconds, as was done in live. Not sure if this value is in a setting somewhere else...
|
||||
vehicle->AddCallbackTimer(2.0f, [=]() {
|
||||
if (!vehicle || !this->m_Parent) return;
|
||||
GameMessages::SendRacingResetPlayerToLastReset(
|
||||
m_Parent->GetObjectID(), racingPlayer.playerID,
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendVehicleStopBoost(vehicle, player->GetSystemAddress(), true);
|
||||
|
||||
GameMessages::SendRacingSetPlayerResetInfo(
|
||||
m_Parent->GetObjectID(), racingPlayer.lap,
|
||||
racingPlayer.respawnIndex, player->GetObjectID(),
|
||||
racingPlayer.respawnPosition, racingPlayer.respawnIndex + 1,
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendResurrect(vehicle);
|
||||
auto* destroyableComponent = vehicle->GetComponent<DestroyableComponent>();
|
||||
// Reset imagination to half its current value, rounded up to the nearest value divisible by 10, as it was done in live.
|
||||
if (destroyableComponent) destroyableComponent->SetImagination(respawnImagination);
|
||||
EntityManager::Instance()->SerializeEntity(vehicle);
|
||||
});
|
||||
|
||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
characterComponent->UpdatePlayerStatistic(RacingTimesWrecked);
|
||||
}
|
||||
} else {
|
||||
GameMessages::SendRacingSetPlayerResetInfo(
|
||||
m_Parent->GetObjectID(), racingPlayer.lap,
|
||||
racingPlayer.respawnIndex, player->GetObjectID(),
|
||||
racingPlayer.respawnPosition, racingPlayer.respawnIndex + 1,
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::SendRacingResetPlayerToLastReset(
|
||||
m_Parent->GetObjectID(), racingPlayer.playerID,
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
|
||||
// Reset player to last checkpoint
|
||||
GameMessages::SendRacingSetPlayerResetInfo(
|
||||
m_Parent->GetObjectID(), racingPlayer.lap,
|
||||
racingPlayer.respawnIndex, player->GetObjectID(),
|
||||
racingPlayer.respawnPosition, racingPlayer.respawnIndex + 1,
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::SendRacingResetPlayerToLastReset(
|
||||
m_Parent->GetObjectID(), racingPlayer.playerID,
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
characterComponent->UpdatePlayerStatistic(RacingTimesWrecked);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,19 +376,6 @@ void RacingControlComponent::OnRacingPlayerInfoResetFinished(Entity* player) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!racingPlayer.noSmashOnReload) {
|
||||
GameMessages::SendDie(vehicle, LWOOBJID_EMPTY, LWOOBJID_EMPTY, true,
|
||||
VIOLENT, u"", 0, 0, 0, true, false, 0);
|
||||
|
||||
GameMessages::SendVehicleUnlockInput(racingPlayer.vehicleID, false,
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::SendVehicleSetWheelLockState(
|
||||
racingPlayer.vehicleID, false, false,
|
||||
UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
GameMessages::SendResurrect(vehicle);
|
||||
}
|
||||
|
||||
racingPlayer.noSmashOnReload = false;
|
||||
|
||||
return;
|
||||
@@ -409,18 +411,18 @@ void RacingControlComponent::HandleMessageBoxResponse(Entity* player,
|
||||
|
||||
if (missionComponent == nullptr) return;
|
||||
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, 0, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_COMPETED_IN_RACE); // Progress task for competing in a race
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->smashedTimes, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_SAFE_DRIVER); // Finish a race without being smashed.
|
||||
missionComponent->Progress(eMissionTaskType::RACING, 0, (LWOOBJID)eRacingTaskParam::COMPETED_IN_RACE); // Progress task for competing in a race
|
||||
missionComponent->Progress(eMissionTaskType::RACING, data->smashedTimes, (LWOOBJID)eRacingTaskParam::SAFE_DRIVER); // Finish a race without being smashed.
|
||||
|
||||
// If solo racing is enabled OR if there are 3 players in the race, progress placement tasks.
|
||||
if (m_SoloRacing || m_LoadedPlayers > 2) {
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, data->finished, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FINISH_WITH_PLACEMENT); // Finish in 1st place on a race
|
||||
missionComponent->Progress(eMissionTaskType::RACING, data->finished, (LWOOBJID)eRacingTaskParam::FINISH_WITH_PLACEMENT); // Finish in 1st place on a race
|
||||
if (data->finished == 1) {
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks.
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_WIN_RACE_IN_WORLD); // Finished first place in specific world.
|
||||
missionComponent->Progress(eMissionTaskType::RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::FIRST_PLACE_MULTIPLE_TRACKS); // Finish in 1st place on multiple tracks.
|
||||
missionComponent->Progress(eMissionTaskType::RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::WIN_RACE_IN_WORLD); // Finished first place in specific world.
|
||||
}
|
||||
if (data->finished == m_LoadedPlayers) {
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_LAST_PLACE_FINISH); // Finished first place in specific world.
|
||||
missionComponent->Progress(eMissionTaskType::RACING, dZoneManager::Instance()->GetZone()->GetWorldID(), (LWOOBJID)eRacingTaskParam::LAST_PLACE_FINISH); // Finished first place in specific world.
|
||||
}
|
||||
}
|
||||
} else if (id == "ACT_RACE_EXIT_THE_RACE?" || id == "Exit") {
|
||||
@@ -567,12 +569,12 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
Game::logger->Log("RacingControlComponent",
|
||||
"Loading all players...");
|
||||
|
||||
for (size_t i = 0; i < m_LobbyPlayers.size(); i++) {
|
||||
for (size_t positionNumber = 0; positionNumber < m_LobbyPlayers.size(); positionNumber++) {
|
||||
Game::logger->Log("RacingControlComponent",
|
||||
"Loading player now!");
|
||||
|
||||
auto* player =
|
||||
EntityManager::Instance()->GetEntity(m_LobbyPlayers[i]);
|
||||
EntityManager::Instance()->GetEntity(m_LobbyPlayers[positionNumber]);
|
||||
|
||||
if (player == nullptr) {
|
||||
return;
|
||||
@@ -581,7 +583,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
Game::logger->Log("RacingControlComponent",
|
||||
"Loading player now NOW!");
|
||||
|
||||
LoadPlayerVehicle(player, true);
|
||||
LoadPlayerVehicle(player, positionNumber + 1, true);
|
||||
|
||||
m_Loaded = true;
|
||||
}
|
||||
@@ -842,7 +844,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
if (missionComponent != nullptr) {
|
||||
|
||||
// Progress lap time tasks
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, (lapTime) * 1000, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_LAP_TIME);
|
||||
missionComponent->Progress(eMissionTaskType::RACING, (lapTime) * 1000, (LWOOBJID)eRacingTaskParam::LAP_TIME);
|
||||
|
||||
if (player.lap == 3) {
|
||||
m_Finished++;
|
||||
@@ -858,7 +860,7 @@ void RacingControlComponent::Update(float deltaTime) {
|
||||
raceTime, raceTime * 1000);
|
||||
|
||||
// Entire race time
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_RACING, (raceTime) * 1000, (LWOOBJID)RacingTaskParam::RACING_TASK_PARAM_TOTAL_TRACK_TIME);
|
||||
missionComponent->Progress(eMissionTaskType::RACING, (raceTime) * 1000, (LWOOBJID)eRacingTaskParam::TOTAL_TRACK_TIME);
|
||||
|
||||
auto* characterComponent = playerEntity->GetComponent<CharacterComponent>();
|
||||
if (characterComponent != nullptr) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Information for each player in the race
|
||||
@@ -104,7 +105,7 @@ struct RacingPlayerInfo {
|
||||
*/
|
||||
class RacingControlComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_RACING_CONTROL;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL;
|
||||
|
||||
RacingControlComponent(Entity* parentEntity);
|
||||
~RacingControlComponent();
|
||||
@@ -123,7 +124,7 @@ public:
|
||||
* @param player The player who's vehicle to initialize.
|
||||
* @param initialLoad Is this the first time the player is loading in this race?
|
||||
*/
|
||||
void LoadPlayerVehicle(Entity* player, bool initialLoad = false);
|
||||
void LoadPlayerVehicle(Entity* player, uint32_t positionNumber, bool initialLoad = false);
|
||||
|
||||
/**
|
||||
* Invoked when the client says it has loaded in.
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
|
||||
RailActivatorComponent::RailActivatorComponent(Entity* parent, int32_t componentID) : Component(parent) {
|
||||
m_ComponentID = componentID;
|
||||
const auto tableData = CDClientManager::Instance()
|
||||
->GetTable<CDRailActivatorComponentTable>("RailActivatorComponent")->GetEntryByID(componentID);
|
||||
const auto tableData = CDClientManager::Instance().GetTable<CDRailActivatorComponentTable>()->GetEntryByID(componentID);;
|
||||
|
||||
m_Path = parent->GetVar<std::u16string>(u"rail_path");
|
||||
m_PathDirection = parent->GetVar<bool>(u"rail_path_direction");
|
||||
@@ -95,7 +94,7 @@ void RailActivatorComponent::OnUse(Entity* originator) {
|
||||
|
||||
void RailActivatorComponent::OnRailMovementReady(Entity* originator) const {
|
||||
// Stun the originator
|
||||
GameMessages::SendSetStunned(originator->GetObjectID(), PUSH, originator->GetSystemAddress(), LWOOBJID_EMPTY,
|
||||
GameMessages::SendSetStunned(originator->GetObjectID(), eStateChangeType::PUSH, originator->GetSystemAddress(), LWOOBJID_EMPTY,
|
||||
true, true, true, true, true, true, true
|
||||
);
|
||||
|
||||
@@ -123,7 +122,7 @@ void RailActivatorComponent::OnRailMovementReady(Entity* originator) const {
|
||||
|
||||
void RailActivatorComponent::OnCancelRailMovement(Entity* originator) {
|
||||
// Remove the stun from the originator
|
||||
GameMessages::SendSetStunned(originator->GetObjectID(), POP, originator->GetSystemAddress(), LWOOBJID_EMPTY,
|
||||
GameMessages::SendSetStunned(originator->GetObjectID(), eStateChangeType::POP, originator->GetSystemAddress(), LWOOBJID_EMPTY,
|
||||
true, true, true, true, true, true, true
|
||||
);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include "dCommonVars.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Component that handles the traveling using rails, e.g. the ninjago posts that can be used to travel using Spinjitzu.
|
||||
@@ -14,7 +15,7 @@ public:
|
||||
explicit RailActivatorComponent(Entity* parent, int32_t componentID);
|
||||
~RailActivatorComponent() override;
|
||||
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_RAIL_ACTIVATOR;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR;
|
||||
|
||||
/**
|
||||
* Handles the OnUse event from some entity, initiates the rail movement
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
#include "dLogger.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "MissionTaskType.h"
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eTriggerEventType.h"
|
||||
|
||||
#include "dServer.h"
|
||||
#include "PacketUtils.h"
|
||||
#include "Spawner.h"
|
||||
#include "MovingPlatformComponent.h"
|
||||
#include "Preconditions.h"
|
||||
#include "Loot.h"
|
||||
#include "TeamManager.h"
|
||||
|
||||
#include "CppScripts.h"
|
||||
|
||||
@@ -51,7 +54,7 @@ RebuildComponent::~RebuildComponent() {
|
||||
}
|
||||
|
||||
void RebuildComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||
if (m_Parent->GetComponent(COMPONENT_TYPE_DESTROYABLE) == nullptr) {
|
||||
if (m_Parent->GetComponent(eReplicaComponentType::DESTROYABLE) == nullptr) {
|
||||
if (bIsInitialUpdate) {
|
||||
outBitStream->Write(false);
|
||||
}
|
||||
@@ -464,12 +467,20 @@ void RebuildComponent::CompleteRebuild(Entity* user) {
|
||||
|
||||
auto* builder = GetBuilder();
|
||||
|
||||
if (builder != nullptr) {
|
||||
auto* missionComponent = builder->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) {
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ACTIVITY, m_ActivityId);
|
||||
if (builder) {
|
||||
auto* team = TeamManager::Instance()->GetTeam(builder->GetObjectID());
|
||||
if (team) {
|
||||
for (const auto memberId : team->members) { // progress missions for all team members
|
||||
auto* member = EntityManager::Instance()->GetEntity(memberId);
|
||||
if (member) {
|
||||
auto* missionComponent = member->GetComponent<MissionComponent>();
|
||||
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId);
|
||||
}
|
||||
}
|
||||
} else{
|
||||
auto* missionComponent = builder->GetComponent<MissionComponent>();
|
||||
if (missionComponent) missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityId);
|
||||
}
|
||||
|
||||
LootGenerator::Instance().DropActivityLoot(builder, m_Parent, m_ActivityId, 1);
|
||||
}
|
||||
|
||||
@@ -485,6 +496,8 @@ void RebuildComponent::CompleteRebuild(Entity* user) {
|
||||
for (const auto& callback : m_RebuildCompleteCallbacks)
|
||||
callback(user);
|
||||
|
||||
m_Parent->TriggerEvent(eTriggerEventType::REBUILD_COMPLETE, user);
|
||||
|
||||
auto* movingPlatform = m_Parent->GetComponent<MovingPlatformComponent>();
|
||||
if (movingPlatform != nullptr) {
|
||||
movingPlatform->OnCompleteRebuild();
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "ScriptedActivityComponent.h"
|
||||
#include "Preconditions.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Entity;
|
||||
|
||||
@@ -19,7 +20,7 @@ class Entity;
|
||||
*/
|
||||
class RebuildComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_REBUILD;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD;
|
||||
|
||||
RebuildComponent(Entity* entity);
|
||||
~RebuildComponent() override;
|
||||
|
||||
@@ -20,9 +20,9 @@ RenderComponent::RenderComponent(Entity* parent) : Component(parent) {
|
||||
return;
|
||||
|
||||
/*
|
||||
auto* table = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
auto* table = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
|
||||
const auto entry = table->GetByIDAndType(parent->GetLOT(), COMPONENT_TYPE_RENDER);
|
||||
const auto entry = table->GetByIDAndType(parent->GetLOT(), eReplicaComponentType::RENDER);
|
||||
|
||||
std::stringstream query;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "AMFFormat.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Entity;
|
||||
|
||||
@@ -55,7 +56,7 @@ struct Effect {
|
||||
*/
|
||||
class RenderComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_RENDER;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::RENDER;
|
||||
|
||||
RenderComponent(Entity* entity);
|
||||
~RenderComponent() override;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "NiPoint3.h"
|
||||
#include "NiQuaternion.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Component that handles rigid bodies that can be interacted with, mostly client-side rendered. An example is the
|
||||
@@ -18,7 +19,7 @@
|
||||
*/
|
||||
class RigidbodyPhantomPhysicsComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_PHANTOM_PHYSICS;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
|
||||
|
||||
RigidbodyPhantomPhysicsComponent(Entity* parent);
|
||||
~RigidbodyPhantomPhysicsComponent() override;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Entity.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Component that handles the LUP/WBL rocket launchpad that can be interacted with to travel to WBL worlds.
|
||||
@@ -10,7 +11,7 @@
|
||||
*/
|
||||
class RocketLaunchLupComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = eReplicaComponentType::COMPONENT_TYPE_ROCKET_LAUNCH_LUP;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH_LUP;
|
||||
|
||||
/**
|
||||
* Constructor for this component, builds the m_LUPWorlds vector
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class PreconditionExpression;
|
||||
|
||||
@@ -17,7 +18,7 @@ class PreconditionExpression;
|
||||
*/
|
||||
class RocketLaunchpadControlComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_ROCKET_LAUNCH;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH;
|
||||
|
||||
RocketLaunchpadControlComponent(Entity* parent, int rocketId);
|
||||
~RocketLaunchpadControlComponent() override;
|
||||
|
||||
@@ -16,11 +16,20 @@
|
||||
#include "GeneralUtils.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "dConfig.h"
|
||||
#include "InventoryComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "dMessageIdentifiers.h"
|
||||
#include "Loot.h"
|
||||
#include "eMissionTaskType.h"
|
||||
|
||||
#include "CDCurrencyTableTable.h"
|
||||
#include "CDActivityRewardsTable.h"
|
||||
#include "CDActivitiesTable.h"
|
||||
|
||||
ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activityID) : Component(parent) {
|
||||
CDActivitiesTable* activitiesTable = CDClientManager::Instance()->GetTable<CDActivitiesTable>("Activities");
|
||||
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == activityID); });
|
||||
m_ActivityID = activityID;
|
||||
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
|
||||
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
|
||||
|
||||
for (CDActivities activity : activities) {
|
||||
m_ActivityInfo = activity;
|
||||
@@ -48,7 +57,7 @@ ScriptedActivityComponent::ScriptedActivityComponent(Entity* parent, int activit
|
||||
|
||||
if (destroyableComponent) {
|
||||
// check for LMIs and set the loot LMIs
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::Instance()->GetTable<CDActivityRewardsTable>("ActivityRewards");
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::Instance().GetTable<CDActivityRewardsTable>();
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([=](CDActivityRewards entry) {return (entry.LootMatrixIndex == destroyableComponent->GetLootMatrixID()); });
|
||||
|
||||
uint32_t startingLMI = 0;
|
||||
@@ -88,6 +97,21 @@ void ScriptedActivityComponent::Serialize(RakNet::BitStream* outBitStream, bool
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptedActivityComponent::ReloadConfig() {
|
||||
CDActivitiesTable* activitiesTable = CDClientManager::Instance().GetTable<CDActivitiesTable>();
|
||||
std::vector<CDActivities> activities = activitiesTable->Query([=](CDActivities entry) {return (entry.ActivityID == m_ActivityID); });
|
||||
for (auto activity : activities) {
|
||||
auto mapID = m_ActivityInfo.instanceMapID;
|
||||
if ((mapID == 1203 || mapID == 1261 || mapID == 1303 || mapID == 1403) && Game::config->GetValue("solo_racing") == "1") {
|
||||
m_ActivityInfo.minTeamSize = 1;
|
||||
m_ActivityInfo.minTeams = 1;
|
||||
} else {
|
||||
m_ActivityInfo.minTeamSize = activity.minTeamSize;
|
||||
m_ActivityInfo.minTeams = activity.minTeams;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptedActivityComponent::HandleMessageBoxResponse(Entity* player, const std::string& id) {
|
||||
if (m_ActivityInfo.ActivityID == 103) {
|
||||
return;
|
||||
@@ -117,7 +141,7 @@ void ScriptedActivityComponent::PlayerJoin(Entity* player) {
|
||||
}
|
||||
|
||||
void ScriptedActivityComponent::PlayerJoinLobby(Entity* player) {
|
||||
if (!m_Parent->HasComponent(COMPONENT_TYPE_REBUILD))
|
||||
if (!m_Parent->HasComponent(eReplicaComponentType::QUICK_BUILD))
|
||||
GameMessages::SendMatchResponse(player, player->GetSystemAddress(), 0); // tell the client they joined a lobby
|
||||
LobbyPlayer* newLobbyPlayer = new LobbyPlayer();
|
||||
newLobbyPlayer->entityID = player->GetObjectID();
|
||||
@@ -191,7 +215,7 @@ void ScriptedActivityComponent::PlayerLeave(LWOOBJID playerID) {
|
||||
}
|
||||
|
||||
void ScriptedActivityComponent::Update(float deltaTime) {
|
||||
|
||||
std::vector<Lobby*> lobbiesToRemove{};
|
||||
// Ticks all the lobbies, not applicable for non-instance activities
|
||||
for (Lobby* lobby : m_Queue) {
|
||||
for (LobbyPlayer* player : lobby->players) {
|
||||
@@ -202,6 +226,11 @@ void ScriptedActivityComponent::Update(float deltaTime) {
|
||||
}
|
||||
}
|
||||
|
||||
if (lobby->players.empty()) {
|
||||
lobbiesToRemove.push_back(lobby);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update the match time for all players
|
||||
if (m_ActivityInfo.maxTeamSize != 1 && lobby->players.size() >= m_ActivityInfo.minTeamSize
|
||||
|| m_ActivityInfo.maxTeamSize == 1 && lobby->players.size() >= m_ActivityInfo.minTeams) {
|
||||
@@ -245,13 +274,17 @@ void ScriptedActivityComponent::Update(float deltaTime) {
|
||||
// The timer has elapsed, start the instance
|
||||
if (lobby->timer <= 0.0f) {
|
||||
Game::logger->Log("ScriptedActivityComponent", "Setting up instance.");
|
||||
|
||||
ActivityInstance* instance = NewInstance();
|
||||
LoadPlayersIntoInstance(instance, lobby->players);
|
||||
RemoveLobby(lobby);
|
||||
instance->StartZone();
|
||||
lobbiesToRemove.push_back(lobby);
|
||||
}
|
||||
}
|
||||
|
||||
while (!lobbiesToRemove.empty()) {
|
||||
RemoveLobby(lobbiesToRemove.front());
|
||||
lobbiesToRemove.erase(lobbiesToRemove.begin());
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptedActivityComponent::RemoveLobby(Lobby* lobby) {
|
||||
@@ -270,7 +303,7 @@ bool ScriptedActivityComponent::HasLobby() const {
|
||||
|
||||
bool ScriptedActivityComponent::IsValidActivity(Entity* player) {
|
||||
// Makes it so that scripted activities with an unimplemented map cannot be joined
|
||||
/*if (player->GetGMLevel() < GAME_MASTER_LEVEL_DEVELOPER && (m_ActivityInfo.instanceMapID == 1302 || m_ActivityInfo.instanceMapID == 1301)) {
|
||||
/*if (player->GetGMLevel() < eGameMasterLevel::DEVELOPER && (m_ActivityInfo.instanceMapID == 1302 || m_ActivityInfo.instanceMapID == 1301)) {
|
||||
if (m_Parent->GetLOT() == 4860) {
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
missionComponent->CompleteMission(229);
|
||||
@@ -524,18 +557,18 @@ void ActivityInstance::StartZone() {
|
||||
void ActivityInstance::RewardParticipant(Entity* participant) {
|
||||
auto* missionComponent = participant->GetComponent<MissionComponent>();
|
||||
if (missionComponent) {
|
||||
missionComponent->Progress(MissionTaskType::MISSION_TASK_TYPE_ACTIVITY, m_ActivityInfo.ActivityID);
|
||||
missionComponent->Progress(eMissionTaskType::ACTIVITY, m_ActivityInfo.ActivityID);
|
||||
}
|
||||
|
||||
// First, get the activity data
|
||||
auto* activityRewardsTable = CDClientManager::Instance()->GetTable<CDActivityRewardsTable>("ActivityRewards");
|
||||
auto* activityRewardsTable = CDClientManager::Instance().GetTable<CDActivityRewardsTable>();
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([=](CDActivityRewards entry) { return (entry.objectTemplate == m_ActivityInfo.ActivityID); });
|
||||
|
||||
if (!activityRewards.empty()) {
|
||||
uint32_t minCoins = 0;
|
||||
uint32_t maxCoins = 0;
|
||||
|
||||
auto* currencyTableTable = CDClientManager::Instance()->GetTable<CDCurrencyTableTable>("CurrencyTable");
|
||||
auto* currencyTableTable = CDClientManager::Instance().GetTable<CDCurrencyTableTable>();
|
||||
std::vector<CDCurrencyTable> currencyTable = currencyTableTable->Query([=](CDCurrencyTable entry) { return (entry.currencyIndex == activityRewards[0].CurrencyIndex && entry.npcminlevel == 1); });
|
||||
|
||||
if (!currencyTable.empty()) {
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
#include "CDActivitiesTable.h"
|
||||
|
||||
/**
|
||||
* Represents an instance of an activity, having participants and score
|
||||
@@ -153,7 +156,7 @@ struct ActivityPlayer {
|
||||
*/
|
||||
class ScriptedActivityComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_SCRIPTED_ACTIVITY;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY;
|
||||
|
||||
ScriptedActivityComponent(Entity* parent, int activityID);
|
||||
~ScriptedActivityComponent() override;
|
||||
@@ -276,6 +279,12 @@ public:
|
||||
*/
|
||||
ActivityInstance* GetInstance(const LWOOBJID playerID);
|
||||
|
||||
/**
|
||||
* @brief Reloads the config settings for this component
|
||||
*
|
||||
*/
|
||||
void ReloadConfig();
|
||||
|
||||
/**
|
||||
* Removes all the instances
|
||||
*/
|
||||
@@ -361,6 +370,12 @@ private:
|
||||
* LMIs for team sizes
|
||||
*/
|
||||
std::unordered_map<uint32_t, uint32_t> m_ActivityLootMatrices;
|
||||
|
||||
/**
|
||||
* The activity id
|
||||
*
|
||||
*/
|
||||
int32_t m_ActivityID;
|
||||
};
|
||||
|
||||
#endif // SCRIPTEDACTIVITYCOMPONENT_H
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "NiPoint3.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Parameters for the shooting gallery that change during playtime
|
||||
@@ -72,7 +73,7 @@ struct StaticShootingGalleryParams {
|
||||
*/
|
||||
class ShootingGalleryComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_SHOOTING_GALLERY;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY;
|
||||
|
||||
explicit ShootingGalleryComponent(Entity* parent);
|
||||
~ShootingGalleryComponent();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "NiPoint3.h"
|
||||
#include "NiQuaternion.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class Entity;
|
||||
|
||||
@@ -27,7 +28,7 @@ enum class eClimbableType : int32_t {
|
||||
*/
|
||||
class SimplePhysicsComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_SIMPLE_PHYSICS;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS;
|
||||
|
||||
SimplePhysicsComponent(uint32_t componentID, Entity* parent);
|
||||
~SimplePhysicsComponent() override;
|
||||
|
||||
@@ -19,11 +19,18 @@
|
||||
#include "BaseCombatAIComponent.h"
|
||||
#include "ScriptComponent.h"
|
||||
#include "BuffComponent.h"
|
||||
#include "EchoStartSkill.h"
|
||||
#include "dMessageIdentifiers.h"
|
||||
#include "DoClientProjectileImpact.h"
|
||||
#include "CDClientManager.h"
|
||||
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
|
||||
ProjectileSyncEntry::ProjectileSyncEntry() {
|
||||
}
|
||||
|
||||
std::unordered_map<uint32_t, uint32_t> SkillComponent::m_skillBehaviorCache = {};
|
||||
|
||||
bool SkillComponent::CastPlayerSkill(const uint32_t behaviorId, const uint32_t skillUid, RakNet::BitStream* bitStream, const LWOOBJID target, uint32_t skillID) {
|
||||
auto* context = new BehaviorContext(this->m_Parent->GetObjectID());
|
||||
|
||||
@@ -123,10 +130,14 @@ void SkillComponent::RegisterPlayerProjectile(const LWOOBJID projectileId, Behav
|
||||
}
|
||||
|
||||
void SkillComponent::Update(const float deltaTime) {
|
||||
if (!m_Parent->HasComponent(COMPONENT_TYPE_BASE_COMBAT_AI) && m_Parent->GetLOT() != 1) {
|
||||
if (!m_Parent->HasComponent(eReplicaComponentType::BASE_COMBAT_AI) && m_Parent->GetLOT() != 1) {
|
||||
CalculateUpdate(deltaTime);
|
||||
}
|
||||
|
||||
if (m_Parent->IsPlayer()) {
|
||||
for (const auto& pair : this->m_managedBehaviors) pair.second->UpdatePlayerSyncs(deltaTime);
|
||||
}
|
||||
|
||||
std::map<uint32_t, BehaviorContext*> keep{};
|
||||
|
||||
for (const auto& pair : this->m_managedBehaviors) {
|
||||
@@ -181,17 +192,19 @@ void SkillComponent::Reset() {
|
||||
}
|
||||
|
||||
void SkillComponent::Interrupt() {
|
||||
if (m_Parent->IsPlayer()) return;
|
||||
|
||||
// TODO: need to check immunities on the destroyable component, but they aren't implemented
|
||||
auto* combat = m_Parent->GetComponent<BaseCombatAIComponent>();
|
||||
|
||||
if (combat != nullptr && combat->GetStunImmune()) {
|
||||
return;
|
||||
}
|
||||
if (combat != nullptr && combat->GetStunImmune()) return;
|
||||
|
||||
for (const auto& behavior : this->m_managedBehaviors) {
|
||||
for (const auto& behaviorEndEntry : behavior.second->endEntries) {
|
||||
behaviorEndEntry.behavior->End(behavior.second, behaviorEndEntry.branchContext, behaviorEndEntry.second);
|
||||
}
|
||||
behavior.second->endEntries.clear();
|
||||
if (m_Parent->IsPlayer()) continue;
|
||||
behavior.second->Interrupt();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SkillComponent::RegisterCalculatedProjectile(const LWOOBJID projectileId, BehaviorContext* context, const BehaviorBranchContext& branch, const LOT lot, const float maxTime,
|
||||
@@ -214,6 +227,29 @@ void SkillComponent::RegisterCalculatedProjectile(const LWOOBJID projectileId, B
|
||||
this->m_managedProjectiles.push_back(entry);
|
||||
}
|
||||
|
||||
bool SkillComponent::CastSkill(const uint32_t skillId, LWOOBJID target, const LWOOBJID optionalOriginatorID) {
|
||||
uint32_t behaviorId = -1;
|
||||
// try to find it via the cache
|
||||
const auto& pair = m_skillBehaviorCache.find(skillId);
|
||||
|
||||
// if it's not in the cache look it up and cache it
|
||||
if (pair == m_skillBehaviorCache.end()) {
|
||||
auto skillTable = CDClientManager::Instance().GetTable<CDSkillBehaviorTable>();
|
||||
behaviorId = skillTable->GetSkillByID(skillId).behaviorID;
|
||||
m_skillBehaviorCache.insert_or_assign(skillId, behaviorId);
|
||||
} else {
|
||||
behaviorId = pair->second;
|
||||
}
|
||||
|
||||
// check to see if we got back a valid behavior
|
||||
if (behaviorId == -1) {
|
||||
Game::logger->LogDebug("SkillComponent", "Tried to cast skill %i but found no behavior", skillId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CalculateBehavior(skillId, behaviorId, target, false, false, optionalOriginatorID).success;
|
||||
}
|
||||
|
||||
|
||||
SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, const uint32_t behaviorId, const LWOOBJID target, const bool ignoreTarget, const bool clientInitalized, const LWOOBJID originatorOverride) {
|
||||
auto* bitStream = new RakNet::BitStream();
|
||||
@@ -246,12 +282,13 @@ SkillExecutionResult SkillComponent::CalculateBehavior(const uint32_t skillId, c
|
||||
|
||||
if (!clientInitalized) {
|
||||
// Echo start skill
|
||||
GameMessages::EchoStartSkill start;
|
||||
EchoStartSkill start;
|
||||
|
||||
start.iCastType = 0;
|
||||
start.skillID = skillId;
|
||||
start.uiSkillHandle = context->skillUId;
|
||||
start.optionalOriginatorID = context->originator;
|
||||
start.optionalTargetID = target;
|
||||
|
||||
auto* originator = EntityManager::Instance()->GetEntity(context->originator);
|
||||
|
||||
@@ -319,34 +356,7 @@ void SkillComponent::CalculateUpdate(const float deltaTime) {
|
||||
const auto distance = Vector3::DistanceSquared(targetPosition, closestPoint);
|
||||
|
||||
if (distance > 3 * 3) {
|
||||
/*
|
||||
if (entry.TrackTarget && distance <= entry.TrackRadius)
|
||||
{
|
||||
const auto rotation = NiQuaternion::LookAtUnlocked(position, targetPosition);
|
||||
|
||||
const auto speed = entry.Velocity.Length();
|
||||
|
||||
const auto homingTarget = rotation.GetForwardVector() * speed;
|
||||
|
||||
Vector3 homing;
|
||||
|
||||
// Move towards
|
||||
|
||||
const auto difference = homingTarget - entry.Velocity;
|
||||
const auto mag = difference.Length();
|
||||
if (mag <= speed || mag == 0)
|
||||
{
|
||||
homing = homingTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.Velocity + homingTarget / mag * speed;
|
||||
}
|
||||
|
||||
entry.Velocity = homing;
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO There is supposed to be an implementation for homing projectiles here
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -416,7 +426,7 @@ void SkillComponent::SyncProjectileCalculation(const ProjectileSyncEntry& entry)
|
||||
|
||||
behavior->Calculate(entry.context, bitStream, entry.branchContext);
|
||||
|
||||
GameMessages::DoClientProjectileImpact projectileImpact;
|
||||
DoClientProjectileImpact projectileImpact;
|
||||
|
||||
projectileImpact.sBitStream.assign((char*)bitStream->GetData(), bitStream->GetNumberOfBytesUsed());
|
||||
projectileImpact.i64OwnerID = this->m_Parent->GetObjectID();
|
||||
@@ -465,7 +475,7 @@ void SkillComponent::HandleUnCast(const uint32_t behaviorId, const LWOOBJID targ
|
||||
delete context;
|
||||
}
|
||||
|
||||
SkillComponent::SkillComponent(Entity* parent) : Component(parent) {
|
||||
SkillComponent::SkillComponent(Entity* parent): Component(parent) {
|
||||
this->m_skillUid = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Component.h"
|
||||
#include "Entity.h"
|
||||
#include "dLogger.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
struct ProjectileSyncEntry {
|
||||
LWOOBJID id = LWOOBJID_EMPTY;
|
||||
@@ -58,7 +59,7 @@ struct SkillExecutionResult {
|
||||
*/
|
||||
class SkillComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_SKILL;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::SKILL;
|
||||
|
||||
explicit SkillComponent(Entity* parent);
|
||||
~SkillComponent() override;
|
||||
@@ -119,6 +120,15 @@ public:
|
||||
*/
|
||||
void RegisterPlayerProjectile(LWOOBJID projectileId, BehaviorContext* context, const BehaviorBranchContext& branch, LOT lot);
|
||||
|
||||
/**
|
||||
* Wrapper for CalculateBehavior that mimics the call structure in scripts and helps reduce magic numbers
|
||||
* @param skillId the skill to cast
|
||||
* @param target the target of the skill
|
||||
* @param optionalOriginatorID change the originator of the skill
|
||||
* @return if the case succeeded
|
||||
*/
|
||||
bool CastSkill(const uint32_t skillId, LWOOBJID target = LWOOBJID_EMPTY, const LWOOBJID optionalOriginatorID = LWOOBJID_EMPTY);
|
||||
|
||||
/**
|
||||
* Initializes a server-side skill calculation.
|
||||
* @param skillId the skill ID
|
||||
@@ -190,6 +200,11 @@ private:
|
||||
*/
|
||||
uint32_t m_skillUid;
|
||||
|
||||
/**
|
||||
* Cache for looking up a behavior id via a skill ID
|
||||
*/
|
||||
static std::unordered_map<uint32_t, uint32_t> m_skillBehaviorCache;
|
||||
|
||||
/**
|
||||
* Sync a server-side projectile calculation.
|
||||
* @param entry the projectile information
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Entity.h"
|
||||
#include "GUID.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Music that should be played by the client
|
||||
@@ -19,7 +20,7 @@ struct MusicCue {
|
||||
*/
|
||||
class SoundTriggerComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_SOUND_TRIGGER;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER;
|
||||
|
||||
explicit SoundTriggerComponent(Entity* parent);
|
||||
~SoundTriggerComponent() override;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "SwitchComponent.h"
|
||||
#include "EntityManager.h"
|
||||
#include "eTriggerEventType.h"
|
||||
|
||||
std::vector<SwitchComponent*> SwitchComponent::petSwitches;
|
||||
|
||||
@@ -42,7 +43,7 @@ void SwitchComponent::EntityEnter(Entity* entity) {
|
||||
}
|
||||
m_Active = true;
|
||||
if (!m_Parent) return;
|
||||
m_Parent->TriggerEvent("OnActivated");
|
||||
m_Parent->TriggerEvent(eTriggerEventType::ACTIVATED, entity);
|
||||
|
||||
const auto grpName = m_Parent->GetVarAsString(u"grp_name");
|
||||
|
||||
@@ -78,7 +79,7 @@ void SwitchComponent::Update(float deltaTime) {
|
||||
if (m_Timer <= 0.0f) {
|
||||
m_Active = false;
|
||||
if (!m_Parent) return;
|
||||
m_Parent->TriggerEvent("OnDectivated");
|
||||
m_Parent->TriggerEvent(eTriggerEventType::DEACTIVATED, m_Parent);
|
||||
|
||||
const auto grpName = m_Parent->GetVarAsString(u"grp_name");
|
||||
|
||||
|
||||
@@ -9,13 +9,14 @@
|
||||
#include "BouncerComponent.h"
|
||||
#include <algorithm>
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* A component for switches in game, including pet triggered switches.
|
||||
*/
|
||||
class SwitchComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_SWITCH;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH;
|
||||
|
||||
SwitchComponent(Entity* parent);
|
||||
~SwitchComponent() override;
|
||||
|
||||
423
dGame/dComponents/TriggerComponent.cpp
Normal file
423
dGame/dComponents/TriggerComponent.cpp
Normal file
@@ -0,0 +1,423 @@
|
||||
#include "TriggerComponent.h"
|
||||
#include "dZoneManager.h"
|
||||
#include "TeamManager.h"
|
||||
#include "eTriggerCommandType.h"
|
||||
#include "eMissionTaskType.h"
|
||||
#include "ePhysicsEffectType.h"
|
||||
|
||||
#include "CharacterComponent.h"
|
||||
#include "ControllablePhysicsComponent.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "PhantomPhysicsComponent.h"
|
||||
#include "Player.h"
|
||||
#include "RebuildComponent.h"
|
||||
#include "SkillComponent.h"
|
||||
#include "eEndBehavior.h"
|
||||
|
||||
|
||||
TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo): Component(parent) {
|
||||
m_Parent = parent;
|
||||
m_Trigger = nullptr;
|
||||
|
||||
std::vector<std::string> tokens = GeneralUtils::SplitString(triggerInfo, ':');
|
||||
|
||||
uint32_t sceneID;
|
||||
GeneralUtils::TryParse<uint32_t>(tokens.at(0), sceneID);
|
||||
uint32_t triggerID;
|
||||
GeneralUtils::TryParse<uint32_t>(tokens.at(1), triggerID);
|
||||
|
||||
m_Trigger = dZoneManager::Instance()->GetZone()->GetTrigger(sceneID, triggerID);
|
||||
|
||||
if (!m_Trigger) m_Trigger = new LUTriggers::Trigger();
|
||||
}
|
||||
|
||||
void TriggerComponent::TriggerEvent(eTriggerEventType event, Entity* optionalTarget) {
|
||||
if (m_Trigger && m_Trigger->enabled) {
|
||||
for (LUTriggers::Event* triggerEvent : m_Trigger->events) {
|
||||
if (triggerEvent->id == event) {
|
||||
for (LUTriggers::Command* command : triggerEvent->commands) {
|
||||
HandleTriggerCommand(command, optionalTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget) {
|
||||
auto argArray = GeneralUtils::SplitString(command->args, ',');
|
||||
|
||||
// determine targets
|
||||
std::vector<Entity*> targetEntities = GatherTargets(command, optionalTarget);
|
||||
|
||||
// if we have no targets, then we are done
|
||||
if (targetEntities.empty()) return;
|
||||
|
||||
for (Entity* targetEntity : targetEntities) {
|
||||
if (!targetEntity) continue;
|
||||
|
||||
switch (command->id) {
|
||||
case eTriggerCommandType::ZONE_PLAYER: break;
|
||||
case eTriggerCommandType::FIRE_EVENT:
|
||||
HandleFireEvent(targetEntity, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::DESTROY_OBJ:
|
||||
HandleDestroyObject(targetEntity, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::TOGGLE_TRIGGER:
|
||||
HandleToggleTrigger(targetEntity, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::RESET_REBUILD:
|
||||
HandleResetRebuild(targetEntity, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::SET_PATH: break;
|
||||
case eTriggerCommandType::SET_PICK_TYPE: break;
|
||||
case eTriggerCommandType::MOVE_OBJECT:
|
||||
HandleMoveObject(targetEntity, argArray);
|
||||
break;
|
||||
case eTriggerCommandType::ROTATE_OBJECT:
|
||||
HandleRotateObject(targetEntity, argArray);
|
||||
break;
|
||||
case eTriggerCommandType::PUSH_OBJECT:
|
||||
HandlePushObject(targetEntity, argArray);
|
||||
break;
|
||||
case eTriggerCommandType::REPEL_OBJECT:
|
||||
HandleRepelObject(targetEntity, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::SET_TIMER: break;
|
||||
case eTriggerCommandType::CANCEL_TIMER: break;
|
||||
case eTriggerCommandType::PLAY_CINEMATIC:
|
||||
HandlePlayCinematic(targetEntity, argArray);
|
||||
break;
|
||||
case eTriggerCommandType::TOGGLE_BBB:
|
||||
HandleToggleBBB(targetEntity, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::UPDATE_MISSION:
|
||||
HandleUpdateMission(targetEntity, argArray);
|
||||
break;
|
||||
case eTriggerCommandType::SET_BOUNCER_STATE: break;
|
||||
case eTriggerCommandType::BOUNCE_ALL_ON_BOUNCER: break;
|
||||
case eTriggerCommandType::TURN_AROUND_ON_PATH: break;
|
||||
case eTriggerCommandType::GO_FORWARD_ON_PATH: break;
|
||||
case eTriggerCommandType::GO_BACKWARD_ON_PATH: break;
|
||||
case eTriggerCommandType::STOP_PATHING: break;
|
||||
case eTriggerCommandType::START_PATHING: break;
|
||||
case eTriggerCommandType::LOCK_OR_UNLOCK_CONTROLS: break;
|
||||
case eTriggerCommandType::PLAY_EFFECT:
|
||||
HandlePlayEffect(targetEntity, argArray);
|
||||
break;
|
||||
case eTriggerCommandType::STOP_EFFECT:
|
||||
GameMessages::SendStopFXEffect(targetEntity, true, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::CAST_SKILL:
|
||||
HandleCastSkill(targetEntity, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::DISPLAY_ZONE_SUMMARY:
|
||||
GameMessages::SendDisplayZoneSummary(targetEntity->GetObjectID(), targetEntity->GetSystemAddress(), false, command->args == "1", m_Parent->GetObjectID());
|
||||
break;
|
||||
case eTriggerCommandType::SET_PHYSICS_VOLUME_EFFECT:
|
||||
HandleSetPhysicsVolumeEffect(targetEntity, argArray);
|
||||
break;
|
||||
case eTriggerCommandType::SET_PHYSICS_VOLUME_STATUS:
|
||||
HandleSetPhysicsVolumeStatus(targetEntity, command->args);
|
||||
break;
|
||||
case eTriggerCommandType::SET_MODEL_TO_BUILD: break;
|
||||
case eTriggerCommandType::SPAWN_MODEL_BRICKS: break;
|
||||
case eTriggerCommandType::ACTIVATE_SPAWNER_NETWORK:
|
||||
HandleActivateSpawnerNetwork(command->args);
|
||||
break;
|
||||
case eTriggerCommandType::DEACTIVATE_SPAWNER_NETWORK:
|
||||
HandleDeactivateSpawnerNetwork(command->args);
|
||||
break;
|
||||
case eTriggerCommandType::RESET_SPAWNER_NETWORK:
|
||||
HandleResetSpawnerNetwork(command->args);
|
||||
break;
|
||||
case eTriggerCommandType::DESTROY_SPAWNER_NETWORK_OBJECTS:
|
||||
HandleDestroySpawnerNetworkObjects(command->args);
|
||||
break;
|
||||
case eTriggerCommandType::GO_TO_WAYPOINT: break;
|
||||
case eTriggerCommandType::ACTIVATE_PHYSICS:
|
||||
HandleActivatePhysics(targetEntity, command->args);
|
||||
break;
|
||||
// DEPRECATED BLOCK START
|
||||
case eTriggerCommandType::ACTIVATE_MUSIC_CUE: break;
|
||||
case eTriggerCommandType::DEACTIVATE_MUSIC_CUE: break;
|
||||
case eTriggerCommandType::FLASH_MUSIC_CUE: break;
|
||||
case eTriggerCommandType::SET_MUSIC_PARAMETER: break;
|
||||
case eTriggerCommandType::PLAY_2D_AMBIENT_SOUND: break;
|
||||
case eTriggerCommandType::STOP_2D_AMBIENT_SOUND: break;
|
||||
case eTriggerCommandType::PLAY_3D_AMBIENT_SOUND: break;
|
||||
case eTriggerCommandType::STOP_3D_AMBIENT_SOUND: break;
|
||||
case eTriggerCommandType::ACTIVATE_MIXER_PROGRAM: break;
|
||||
case eTriggerCommandType::DEACTIVATE_MIXER_PROGRAM: break;
|
||||
// DEPRECATED BLOCK END
|
||||
default:
|
||||
Game::logger->LogDebug("TriggerComponent", "Event %i was not handled!", command->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Entity*> TriggerComponent::GatherTargets(LUTriggers::Command* command, Entity* optionalTarget) {
|
||||
std::vector<Entity*> entities = {};
|
||||
|
||||
if (command->target == "self") entities.push_back(m_Parent);
|
||||
else if (command->target == "zone") { /*TODO*/ }
|
||||
else if (command->target == "target" && optionalTarget) entities.push_back(optionalTarget);
|
||||
else if (command->target == "targetTeam" && optionalTarget) {
|
||||
auto* team = TeamManager::Instance()->GetTeam(optionalTarget->GetObjectID());
|
||||
for (const auto memberId : team->members) {
|
||||
auto* member = EntityManager::Instance()->GetEntity(memberId);
|
||||
if (member) entities.push_back(member);
|
||||
}
|
||||
} else if (command->target == "objGroup") entities = EntityManager::Instance()->GetEntitiesInGroup(command->targetName);
|
||||
else if (command->target == "allPlayers") {
|
||||
for (auto* player : Player::GetAllPlayers()) {
|
||||
entities.push_back(player);
|
||||
}
|
||||
} else if (command->target == "allNPCs") { /*UNUSED*/ }
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleFireEvent(Entity* targetEntity, std::string args) {
|
||||
for (CppScripts::Script* script : CppScripts::GetEntityScripts(targetEntity)) {
|
||||
script->OnFireEventServerSide(targetEntity, m_Parent, args, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleDestroyObject(Entity* targetEntity, std::string args){
|
||||
uint32_t killType;
|
||||
GeneralUtils::TryParse<uint32_t>(args, killType);
|
||||
targetEntity->Smash(m_Parent->GetObjectID(), static_cast<eKillType>(killType));
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleToggleTrigger(Entity* targetEntity, std::string args){
|
||||
auto* triggerComponent = targetEntity->GetComponent<TriggerComponent>();
|
||||
if (!triggerComponent) {
|
||||
Game::logger->Log("TriggerComponent::HandleToggleTrigger", "Trigger component not found!");
|
||||
return;
|
||||
}
|
||||
triggerComponent->SetTriggerEnabled(args == "1");
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleResetRebuild(Entity* targetEntity, std::string args){
|
||||
auto* rebuildComponent = targetEntity->GetComponent<RebuildComponent>();
|
||||
if (!rebuildComponent) {
|
||||
Game::logger->Log("TriggerComponent::HandleResetRebuild", "Rebuild component not found!");
|
||||
return;
|
||||
}
|
||||
rebuildComponent->ResetRebuild(args == "1");
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleMoveObject(Entity* targetEntity, std::vector<std::string> argArray){
|
||||
if (argArray.size() <= 2) return;
|
||||
|
||||
auto position = targetEntity->GetPosition();
|
||||
NiPoint3 offset = NiPoint3::ZERO;
|
||||
GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), offset);
|
||||
|
||||
position += offset;
|
||||
targetEntity->SetPosition(position);
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray){
|
||||
if (argArray.size() <= 2) return;
|
||||
|
||||
NiPoint3 vector = NiPoint3::ZERO;
|
||||
GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), vector);
|
||||
|
||||
NiQuaternion rotation = NiQuaternion::FromEulerAngles(vector);
|
||||
targetEntity->SetRotation(rotation);
|
||||
}
|
||||
|
||||
void TriggerComponent::HandlePushObject(Entity* targetEntity, std::vector<std::string> argArray){
|
||||
auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>();
|
||||
if (!phantomPhysicsComponent) {
|
||||
Game::logger->Log("TriggerComponent::HandlePushObject", "Phantom Physics component not found!");
|
||||
return;
|
||||
}
|
||||
phantomPhysicsComponent->SetPhysicsEffectActive(true);
|
||||
phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::PUSH);
|
||||
phantomPhysicsComponent->SetDirectionalMultiplier(1);
|
||||
NiPoint3 direction = NiPoint3::ZERO;
|
||||
GeneralUtils::TryParse(argArray.at(0), argArray.at(1), argArray.at(2), direction);
|
||||
phantomPhysicsComponent->SetDirection(direction);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
|
||||
void TriggerComponent::HandleRepelObject(Entity* targetEntity, std::string args){
|
||||
auto* phantomPhysicsComponent = m_Parent->GetComponent<PhantomPhysicsComponent>();
|
||||
if (!phantomPhysicsComponent) {
|
||||
Game::logger->Log("TriggerComponent::HandleRepelObject", "Phantom Physics component not found!");
|
||||
return;
|
||||
}
|
||||
float forceMultiplier;
|
||||
GeneralUtils::TryParse<float>(args, forceMultiplier);
|
||||
phantomPhysicsComponent->SetPhysicsEffectActive(true);
|
||||
phantomPhysicsComponent->SetEffectType(ePhysicsEffectType::REPULSE);
|
||||
phantomPhysicsComponent->SetDirectionalMultiplier(forceMultiplier);
|
||||
|
||||
auto triggerPos = m_Parent->GetPosition();
|
||||
auto targetPos = targetEntity->GetPosition();
|
||||
|
||||
// normalize the vectors to get the direction
|
||||
auto delta = targetPos - triggerPos;
|
||||
auto length = delta.Length();
|
||||
NiPoint3 direction = delta / length;
|
||||
phantomPhysicsComponent->SetDirection(direction);
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
void TriggerComponent::HandlePlayCinematic(Entity* targetEntity, std::vector<std::string> argArray) {
|
||||
float leadIn = -1.0;
|
||||
auto wait = eEndBehavior::RETURN;
|
||||
bool unlock = true;
|
||||
bool leaveLocked = false;
|
||||
bool hidePlayer = false;
|
||||
|
||||
if (argArray.size() >= 2) {
|
||||
GeneralUtils::TryParse<float>(argArray.at(1), leadIn);
|
||||
if (argArray.size() >= 3 && argArray.at(2) == "wait") {
|
||||
wait = eEndBehavior::WAIT;
|
||||
if (argArray.size() >= 4 && argArray.at(3) == "unlock") {
|
||||
unlock = false;
|
||||
if (argArray.size() >= 5 && argArray.at(4) == "leavelocked") {
|
||||
leaveLocked = true;
|
||||
if (argArray.size() >= 6 && argArray.at(5) == "hideplayer") {
|
||||
hidePlayer = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GameMessages::SendPlayCinematic(targetEntity->GetObjectID(), GeneralUtils::UTF8ToUTF16(argArray.at(0)), targetEntity->GetSystemAddress(), true, true, false, false, wait, hidePlayer, leadIn, leaveLocked, unlock);
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleToggleBBB(Entity* targetEntity, std::string args) {
|
||||
auto* character = targetEntity->GetCharacter();
|
||||
if (!character) {
|
||||
Game::logger->Log("TriggerComponent::HandleToggleBBB", "Character was not found!");
|
||||
return;
|
||||
}
|
||||
bool buildMode = !(character->GetBuildMode());
|
||||
if (args == "enter") buildMode = true;
|
||||
else if (args == "exit") buildMode = false;
|
||||
character->SetBuildMode(buildMode);
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleUpdateMission(Entity* targetEntity, std::vector<std::string> argArray) {
|
||||
// there are only explore tasks used
|
||||
// If others need to be implemented for modding
|
||||
// then we need a good way to convert this from a string to that enum
|
||||
if (argArray.at(0) != "exploretask") return;
|
||||
MissionComponent* missionComponent = targetEntity->GetComponent<MissionComponent>();
|
||||
if (!missionComponent){
|
||||
Game::logger->Log("TriggerComponent::HandleUpdateMission", "Mission component not found!");
|
||||
return;
|
||||
}
|
||||
missionComponent->Progress(eMissionTaskType::EXPLORE, 0, 0, argArray.at(4));
|
||||
}
|
||||
|
||||
void TriggerComponent::HandlePlayEffect(Entity* targetEntity, std::vector<std::string> argArray) {
|
||||
if (argArray.size() < 3) return;
|
||||
int32_t effectID = 0;
|
||||
if (!GeneralUtils::TryParse<int32_t>(argArray.at(1), effectID)) return;
|
||||
std::u16string effectType = GeneralUtils::UTF8ToUTF16(argArray.at(2));
|
||||
float priority = 1;
|
||||
if (argArray.size() == 4) GeneralUtils::TryParse<float>(argArray.at(3), priority);
|
||||
GameMessages::SendPlayFXEffect(targetEntity, effectID, effectType, argArray.at(0), LWOOBJID_EMPTY, priority);
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleCastSkill(Entity* targetEntity, std::string args){
|
||||
auto* skillComponent = targetEntity->GetComponent<SkillComponent>();
|
||||
if (!skillComponent) {
|
||||
Game::logger->Log("TriggerComponent::HandleCastSkill", "Skill component not found!");
|
||||
return;
|
||||
}
|
||||
uint32_t skillId;
|
||||
GeneralUtils::TryParse<uint32_t>(args, skillId);
|
||||
skillComponent->CastSkill(skillId, targetEntity->GetObjectID());
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleSetPhysicsVolumeEffect(Entity* targetEntity, std::vector<std::string> argArray) {
|
||||
auto* phantomPhysicsComponent = targetEntity->GetComponent<PhantomPhysicsComponent>();
|
||||
if (!phantomPhysicsComponent) {
|
||||
Game::logger->Log("TriggerComponent::HandleSetPhysicsVolumeEffect", "Phantom Physics component not found!");
|
||||
return;
|
||||
}
|
||||
phantomPhysicsComponent->SetPhysicsEffectActive(true);
|
||||
ePhysicsEffectType effectType = ePhysicsEffectType::PUSH;
|
||||
std::transform(argArray.at(0).begin(), argArray.at(0).end(), argArray.at(0).begin(), ::tolower); //Transform to lowercase
|
||||
if (argArray.at(0) == "push") effectType = ePhysicsEffectType::PUSH;
|
||||
else if (argArray.at(0) == "attract") effectType = ePhysicsEffectType::ATTRACT;
|
||||
else if (argArray.at(0) == "repulse") effectType = ePhysicsEffectType::REPULSE;
|
||||
else if (argArray.at(0) == "gravity") effectType = ePhysicsEffectType::GRAVITY_SCALE;
|
||||
else if (argArray.at(0) == "friction") effectType = ePhysicsEffectType::FRICTION;
|
||||
|
||||
phantomPhysicsComponent->SetEffectType(effectType);
|
||||
phantomPhysicsComponent->SetDirectionalMultiplier(std::stof(argArray.at(1)));
|
||||
if (argArray.size() > 4) {
|
||||
NiPoint3 direction = NiPoint3::ZERO;
|
||||
GeneralUtils::TryParse(argArray.at(2), argArray.at(3), argArray.at(4), direction);
|
||||
phantomPhysicsComponent->SetDirection(direction);
|
||||
}
|
||||
if (argArray.size() > 5) {
|
||||
uint32_t min;
|
||||
GeneralUtils::TryParse<uint32_t>(argArray.at(6), min);
|
||||
phantomPhysicsComponent->SetMin(min);
|
||||
|
||||
uint32_t max;
|
||||
GeneralUtils::TryParse<uint32_t>(argArray.at(7), max);
|
||||
phantomPhysicsComponent->SetMax(max);
|
||||
}
|
||||
|
||||
EntityManager::Instance()->SerializeEntity(targetEntity);
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleSetPhysicsVolumeStatus(Entity* targetEntity, std::string args) {
|
||||
auto* phantomPhysicsComponent = targetEntity->GetComponent<PhantomPhysicsComponent>();
|
||||
if (!phantomPhysicsComponent) {
|
||||
Game::logger->Log("TriggerComponent::HandleSetPhysicsVolumeEffect", "Phantom Physics component not found!");
|
||||
return;
|
||||
}
|
||||
phantomPhysicsComponent->SetPhysicsEffectActive(args == "On");
|
||||
EntityManager::Instance()->SerializeEntity(targetEntity);
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleActivateSpawnerNetwork(std::string args){
|
||||
for (auto* spawner : dZoneManager::Instance()->GetSpawnersByName(args)) {
|
||||
if (spawner) spawner->Activate();
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleDeactivateSpawnerNetwork(std::string args){
|
||||
for (auto* spawner : dZoneManager::Instance()->GetSpawnersByName(args)) {
|
||||
if (spawner) spawner->Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleResetSpawnerNetwork(std::string args){
|
||||
for (auto* spawner : dZoneManager::Instance()->GetSpawnersByName(args)) {
|
||||
if (spawner) spawner->Reset();
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleDestroySpawnerNetworkObjects(std::string args){
|
||||
for (auto* spawner : dZoneManager::Instance()->GetSpawnersByName(args)) {
|
||||
if (spawner) spawner->DestroyAllEntities();
|
||||
}
|
||||
}
|
||||
|
||||
void TriggerComponent::HandleActivatePhysics(Entity* targetEntity, std::string args) {
|
||||
if (args == "true") {
|
||||
// TODO add physics entity if there isn't one
|
||||
} else if (args == "false"){
|
||||
// TODO remove Phsyics entity if there is one
|
||||
} else {
|
||||
Game::logger->LogDebug("TriggerComponent", "Invalid argument for ActivatePhysics Trigger: %s", args.c_str());
|
||||
}
|
||||
}
|
||||
48
dGame/dComponents/TriggerComponent.h
Normal file
48
dGame/dComponents/TriggerComponent.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef __TRIGGERCOMPONENT__H__
|
||||
#define __TRIGGERCOMPONENT__H__
|
||||
|
||||
#include "Component.h"
|
||||
#include "LUTriggers.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
class TriggerComponent : public Component {
|
||||
public:
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::TRIGGER;
|
||||
|
||||
explicit TriggerComponent(Entity* parent, const std::string triggerInfo);
|
||||
|
||||
void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr);
|
||||
LUTriggers::Trigger* GetTrigger() const { return m_Trigger; }
|
||||
void SetTriggerEnabled(bool enabled){ m_Trigger->enabled = enabled; };
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void HandleTriggerCommand(LUTriggers::Command* command, Entity* optionalTarget);
|
||||
std::vector<Entity*> GatherTargets(LUTriggers::Command* command, Entity* optionalTarget);
|
||||
|
||||
// Trigger Event Handlers
|
||||
void HandleFireEvent(Entity* targetEntity, std::string args);
|
||||
void HandleDestroyObject(Entity* targetEntity, std::string args);
|
||||
void HandleToggleTrigger(Entity* targetEntity, std::string args);
|
||||
void HandleResetRebuild(Entity* targetEntity, std::string args);
|
||||
void HandleMoveObject(Entity* targetEntity, std::vector<std::string> argArray);
|
||||
void HandleRotateObject(Entity* targetEntity, std::vector<std::string> argArray);
|
||||
void HandlePushObject(Entity* targetEntity, std::vector<std::string> argArray);
|
||||
void HandleRepelObject(Entity* targetEntity, std::string args);
|
||||
void HandlePlayCinematic(Entity* targetEntity, std::vector<std::string> argArray);
|
||||
void HandleToggleBBB(Entity* targetEntity, std::string args);
|
||||
void HandleUpdateMission(Entity* targetEntity, std::vector<std::string> argArray);
|
||||
void HandlePlayEffect(Entity* targetEntity, std::vector<std::string> argArray);
|
||||
void HandleCastSkill(Entity* targetEntity, std::string args);
|
||||
void HandleSetPhysicsVolumeEffect(Entity* targetEntity, std::vector<std::string> argArray);
|
||||
void HandleSetPhysicsVolumeStatus(Entity* targetEntity, std::string args);
|
||||
void HandleActivateSpawnerNetwork(std::string args);
|
||||
void HandleDeactivateSpawnerNetwork(std::string args);
|
||||
void HandleResetSpawnerNetwork(std::string args);
|
||||
void HandleDestroySpawnerNetworkObjects(std::string args);
|
||||
void HandleActivatePhysics(Entity* targetEntity, std::string args);
|
||||
|
||||
LUTriggers::Trigger* m_Trigger;
|
||||
};
|
||||
#endif //!__TRIGGERCOMPONENT__H__
|
||||
@@ -3,13 +3,14 @@
|
||||
#include "BitStream.h"
|
||||
#include "Entity.h"
|
||||
#include "Component.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* Physics component for vehicles.
|
||||
*/
|
||||
class VehiclePhysicsComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_VEHICLE_PHYSICS;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::VEHICLE_PHYSICS;
|
||||
|
||||
VehiclePhysicsComponent(Entity* parentEntity);
|
||||
~VehiclePhysicsComponent() override;
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
#include "Game.h"
|
||||
#include "dServer.h"
|
||||
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDVendorComponentTable.h"
|
||||
#include "CDLootMatrixTable.h"
|
||||
#include "CDLootTableTable.h"
|
||||
|
||||
VendorComponent::VendorComponent(Entity* parent) : Component(parent) {
|
||||
SetupConstants();
|
||||
RefreshInventory(true);
|
||||
@@ -59,13 +64,13 @@ void VendorComponent::RefreshInventory(bool isCreation) {
|
||||
return;
|
||||
}
|
||||
m_Inventory.clear();
|
||||
auto* lootMatrixTable = CDClientManager::Instance()->GetTable<CDLootMatrixTable>("LootMatrix");
|
||||
auto* lootMatrixTable = CDClientManager::Instance().GetTable<CDLootMatrixTable>();
|
||||
std::vector<CDLootMatrix> lootMatrices = lootMatrixTable->Query([=](CDLootMatrix entry) { return (entry.LootMatrixIndex == m_LootMatrixID); });
|
||||
|
||||
if (lootMatrices.empty()) return;
|
||||
// Done with lootMatrix table
|
||||
|
||||
auto* lootTableTable = CDClientManager::Instance()->GetTable<CDLootTableTable>("LootTable");
|
||||
auto* lootTableTable = CDClientManager::Instance().GetTable<CDLootTableTable>();
|
||||
|
||||
for (const auto& lootMatrix : lootMatrices) {
|
||||
int lootTableID = lootMatrix.LootTableIndex;
|
||||
@@ -118,10 +123,10 @@ void VendorComponent::RefreshInventory(bool isCreation) {
|
||||
}
|
||||
|
||||
void VendorComponent::SetupConstants() {
|
||||
auto* compRegistryTable = CDClientManager::Instance()->GetTable<CDComponentsRegistryTable>("ComponentsRegistry");
|
||||
int componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), COMPONENT_TYPE_VENDOR);
|
||||
auto* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
||||
int componentID = compRegistryTable->GetByIDAndType(m_Parent->GetLOT(), eReplicaComponentType::VENDOR);
|
||||
|
||||
auto* vendorComponentTable = CDClientManager::Instance()->GetTable<CDVendorComponentTable>("VendorComponent");
|
||||
auto* vendorComponentTable = CDClientManager::Instance().GetTable<CDVendorComponentTable>();
|
||||
std::vector<CDVendorComponent> vendorComps = vendorComponentTable->Query([=](CDVendorComponent entry) { return (entry.id == componentID); });
|
||||
if (vendorComps.empty()) return;
|
||||
m_BuyScalar = vendorComps[0].buyScalar;
|
||||
|
||||
@@ -7,13 +7,14 @@
|
||||
#include "Entity.h"
|
||||
#include "GameMessages.h"
|
||||
#include "RakNetTypes.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
|
||||
/**
|
||||
* A component for vendor NPCs. A vendor sells items to the player.
|
||||
*/
|
||||
class VendorComponent : public Component {
|
||||
public:
|
||||
static const uint32_t ComponentType = COMPONENT_TYPE_VENDOR;
|
||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR;
|
||||
|
||||
VendorComponent(Entity* parent);
|
||||
~VendorComponent() override;
|
||||
|
||||
Reference in New Issue
Block a user