mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-12 11:08:27 +00:00
Merge branch 'main' into rotation-behaviors
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
#include "UserManager.h"
|
||||
#include "CDMissionsTable.h"
|
||||
|
||||
AchievementVendorComponent::AchievementVendorComponent(Entity* parent) : VendorComponent(parent) {
|
||||
AchievementVendorComponent::AchievementVendorComponent(Entity* parent, const int32_t componentID) : VendorComponent(parent, componentID) {
|
||||
RefreshInventory(true);
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ class Entity;
|
||||
class AchievementVendorComponent final : public VendorComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ACHIEVEMENT_VENDOR;
|
||||
AchievementVendorComponent(Entity* parent);
|
||||
AchievementVendorComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
void RefreshInventory(bool isCreation = false) override;
|
||||
bool SellsItem(Entity* buyer, const LOT lot);
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "CharacterComponent.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Component(parent) {
|
||||
ActivityComponent::ActivityComponent(Entity* parent, int32_t componentID) : Component(parent, componentID) {
|
||||
using namespace GameMessages;
|
||||
RegisterMsg<GetObjectReportInfo>(this, &ActivityComponent::OnGetObjectReportInfo);
|
||||
/*
|
||||
@@ -39,39 +39,12 @@ ActivityComponent::ActivityComponent(Entity* parent, int32_t activityID) : Compo
|
||||
* if activityID is specified and if that column exists in the activities table, update the activity info with that data.
|
||||
*/
|
||||
|
||||
m_ActivityID = activityID;
|
||||
LoadActivityData(activityID);
|
||||
m_ActivityID = componentID;
|
||||
LoadActivityData(componentID);
|
||||
if (m_Parent->HasVar(u"activityID")) {
|
||||
m_ActivityID = parent->GetVar<int32_t>(u"activityID");
|
||||
LoadActivityData(m_ActivityID);
|
||||
}
|
||||
|
||||
auto* destroyableComponent = m_Parent->GetComponent<DestroyableComponent>();
|
||||
|
||||
if (destroyableComponent) {
|
||||
// First lookup the loot matrix id for this component id.
|
||||
CDActivityRewardsTable* activityRewardsTable = CDClientManager::GetTable<CDActivityRewardsTable>();
|
||||
std::vector<CDActivityRewards> activityRewards = activityRewardsTable->Query([=](CDActivityRewards entry) {return (entry.LootMatrixIndex == destroyableComponent->GetLootMatrixID()); });
|
||||
|
||||
uint32_t startingLMI = 0;
|
||||
|
||||
// If we have one, set the starting loot matrix id to that.
|
||||
if (activityRewards.size() > 0) {
|
||||
startingLMI = activityRewards[0].LootMatrixIndex;
|
||||
}
|
||||
|
||||
if (startingLMI > 0) {
|
||||
// We may have more than 1 loot matrix index to use depending ont the size of the team that is looting the activity.
|
||||
// So this logic will get the rest of the loot matrix indices for this activity.
|
||||
|
||||
std::vector<CDActivityRewards> objectTemplateActivities = activityRewardsTable->Query([=](CDActivityRewards entry) {return (activityRewards[0].objectTemplate == entry.objectTemplate); });
|
||||
for (const auto& item : objectTemplateActivities) {
|
||||
if (item.activityRating > 0 && item.activityRating < 5) {
|
||||
m_ActivityLootMatrices.insert({ item.activityRating, item.LootMatrixIndex });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void ActivityComponent::LoadActivityData(const int32_t activityId) {
|
||||
CDActivitiesTable* activitiesTable = CDClientManager::GetTable<CDActivitiesTable>();
|
||||
@@ -698,10 +671,6 @@ bool ActivityComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
}
|
||||
}
|
||||
|
||||
auto& lootMatrices = activityInfo.PushDebug("Loot Matrices");
|
||||
for (const auto& [activityRating, lootMatrixID] : m_ActivityLootMatrices) {
|
||||
lootMatrices.PushDebug<AMFIntValue>("Loot Matrix " + std::to_string(activityRating)) = lootMatrixID;
|
||||
}
|
||||
activityInfo.PushDebug<AMFIntValue>("ActivityID") = m_ActivityID;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -341,19 +341,13 @@ public:
|
||||
*/
|
||||
void SetInstanceMapID(uint32_t mapID) { m_ActivityInfo.instanceMapID = mapID; };
|
||||
|
||||
/**
|
||||
* Returns the LMI that this activity points to for a team size
|
||||
* @param teamSize the team size to get the LMI for
|
||||
* @return the LMI that this activity points to for a team size
|
||||
*/
|
||||
uint32_t GetLootMatrixForTeamSize(uint32_t teamSize) { return m_ActivityLootMatrices[teamSize]; }
|
||||
private:
|
||||
|
||||
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
/**
|
||||
* The database information for this activity
|
||||
*/
|
||||
CDActivities m_ActivityInfo;
|
||||
CDActivities m_ActivityInfo{};
|
||||
|
||||
/**
|
||||
* All the active instances of this activity
|
||||
@@ -370,11 +364,6 @@ private:
|
||||
*/
|
||||
std::vector<ActivityPlayer*> m_ActivityPlayers;
|
||||
|
||||
/**
|
||||
* LMIs for team sizes
|
||||
*/
|
||||
std::unordered_map<uint32_t, uint32_t> m_ActivityLootMatrices;
|
||||
|
||||
/**
|
||||
* The activity id
|
||||
*/
|
||||
|
||||
@@ -27,8 +27,13 @@
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
#include "CDPhysicsComponentTable.h"
|
||||
#include "dNavMesh.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id) : Component(parent) {
|
||||
BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
{
|
||||
using namespace GameMessages;
|
||||
RegisterMsg<GetObjectReportInfo>(this, &BaseCombatAIComponent::MsgGetObjectReportInfo);
|
||||
}
|
||||
m_Target = LWOOBJID_EMPTY;
|
||||
m_DirtyStateOrTarget = true;
|
||||
m_State = AiState::spawn;
|
||||
@@ -43,7 +48,7 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
|
||||
//Grab the aggro information from BaseCombatAI:
|
||||
auto componentQuery = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT aggroRadius, tetherSpeed, pursuitSpeed, softTetherRadius, hardTetherRadius FROM BaseCombatAIComponent WHERE id = ?;");
|
||||
componentQuery.bind(1, static_cast<int>(id));
|
||||
componentQuery.bind(1, static_cast<int>(componentID));
|
||||
|
||||
auto componentResult = componentQuery.execQuery();
|
||||
|
||||
@@ -111,12 +116,12 @@ BaseCombatAIComponent::BaseCombatAIComponent(Entity* parent, const uint32_t id)
|
||||
int32_t collisionGroup = (COLLISION_GROUP_DYNAMIC | COLLISION_GROUP_ENEMY);
|
||||
|
||||
CDComponentsRegistryTable* componentRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
|
||||
auto componentID = componentRegistryTable->GetByIDAndType(parent->GetLOT(), eReplicaComponentType::CONTROLLABLE_PHYSICS);
|
||||
const auto controllablePhysicsID = componentRegistryTable->GetByIDAndType(parent->GetLOT(), eReplicaComponentType::CONTROLLABLE_PHYSICS);
|
||||
|
||||
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::GetTable<CDPhysicsComponentTable>();
|
||||
|
||||
if (physicsComponentTable != nullptr) {
|
||||
auto* info = physicsComponentTable->GetByID(componentID);
|
||||
auto* info = physicsComponentTable->GetByID(controllablePhysicsID);
|
||||
if (info != nullptr) {
|
||||
collisionGroup = info->bStatic ? COLLISION_GROUP_NEUTRAL : info->collisionGroup;
|
||||
}
|
||||
@@ -839,3 +844,73 @@ void BaseCombatAIComponent::IgnoreThreat(const LWOOBJID threat, const float valu
|
||||
SetThreat(threat, 0.0f);
|
||||
m_Target = LWOOBJID_EMPTY;
|
||||
}
|
||||
|
||||
bool BaseCombatAIComponent::MsgGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
using enum AiState;
|
||||
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
auto& cmptType = reportMsg.info->PushDebug("Base Combat AI");
|
||||
cmptType.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
|
||||
auto& targetInfo = cmptType.PushDebug("Current Target Info");
|
||||
targetInfo.PushDebug<AMFStringValue>("Current Target ID") = std::to_string(m_Target);
|
||||
// if (m_Target != LWOOBJID_EMPTY) {
|
||||
// LWOGameMessages::ObjGetName nameMsg(m_CurrentTarget);
|
||||
// SEND_GAMEOBJ_MSG(nameMsg);
|
||||
// if (!nameMsg.msg.name.empty()) targetInfo.PushDebug("Name") = nameMsg.msg.name;
|
||||
// }
|
||||
|
||||
auto& roundInfo = cmptType.PushDebug("Round Info");
|
||||
// roundInfo.PushDebug<AMFDoubleValue>("Combat Round Time") = m_CombatRoundLength;
|
||||
// roundInfo.PushDebug<AMFDoubleValue>("Minimum Time") = m_MinRoundLength;
|
||||
// roundInfo.PushDebug<AMFDoubleValue>("Maximum Time") = m_MaxRoundLength;
|
||||
// roundInfo.PushDebug<AMFDoubleValue>("Selected Time") = m_SelectedTime;
|
||||
// roundInfo.PushDebug<AMFDoubleValue>("Combat Start Delay") = m_CombatStartDelay;
|
||||
std::string curState;
|
||||
switch (m_State) {
|
||||
case idle: curState = "Idling"; break;
|
||||
case aggro: curState = "Aggroed"; break;
|
||||
case tether: curState = "Returning to Tether"; break;
|
||||
case spawn: curState = "Spawn"; break;
|
||||
case dead: curState = "Dead"; break;
|
||||
default: curState = "Unknown or Undefined"; break;
|
||||
}
|
||||
cmptType.PushDebug<AMFStringValue>("Current Combat State") = curState;
|
||||
|
||||
//switch (m_CombatBehaviorType) {
|
||||
// case 0: curState = "Passive"; break;
|
||||
// case 1: curState = "Aggressive"; break;
|
||||
// case 2: curState = "Passive (Turret)"; break;
|
||||
// case 3: curState = "Aggressive (Turret)"; break;
|
||||
// default: curState = "Unknown or Undefined"; break;
|
||||
//}
|
||||
//cmptType.PushDebug("Current Combat Behavior State") = curState;
|
||||
|
||||
//switch (m_CombatRole) {
|
||||
// case 0: curState = "Melee"; break;
|
||||
// case 1: curState = "Ranged"; break;
|
||||
// case 2: curState = "Support"; break;
|
||||
// default: curState = "Unknown or Undefined"; break;
|
||||
//}
|
||||
//cmptType.PushDebug("Current Combat Role") = curState;
|
||||
|
||||
auto& tetherPoint = cmptType.PushDebug("Tether Point");
|
||||
tetherPoint.PushDebug<AMFDoubleValue>("X") = m_StartPosition.x;
|
||||
tetherPoint.PushDebug<AMFDoubleValue>("Y") = m_StartPosition.y;
|
||||
tetherPoint.PushDebug<AMFDoubleValue>("Z") = m_StartPosition.z;
|
||||
cmptType.PushDebug<AMFDoubleValue>("Hard Tether Radius") = m_HardTetherRadius;
|
||||
cmptType.PushDebug<AMFDoubleValue>("Soft Tether Radius") = m_SoftTetherRadius;
|
||||
cmptType.PushDebug<AMFDoubleValue>("Aggro Radius") = m_AggroRadius;
|
||||
cmptType.PushDebug<AMFDoubleValue>("Tether Speed") = m_TetherSpeed;
|
||||
cmptType.PushDebug<AMFDoubleValue>("Aggro Speed") = m_TetherSpeed;
|
||||
// cmptType.PushDebug<AMFDoubleValue>("Specified Min Range") = m_SpecificMinRange;
|
||||
// cmptType.PushDebug<AMFDoubleValue>("Specified Max Range") = m_SpecificMaxRange;
|
||||
auto& threats = cmptType.PushDebug("Target Threats");
|
||||
for (const auto& [id, threat] : m_ThreatEntries) {
|
||||
threats.PushDebug<AMFDoubleValue>(std::to_string(id)) = threat;
|
||||
}
|
||||
|
||||
auto& ignoredThreats = cmptType.PushDebug("Temp Ignored Threats");
|
||||
for (const auto& [id, threat] : m_ThreatEntries) {
|
||||
ignoredThreats.PushDebug<AMFDoubleValue>(std::to_string(id) + " - Time") = threat;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class BaseCombatAIComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BASE_COMBAT_AI;
|
||||
|
||||
BaseCombatAIComponent(Entity* parentEntity, uint32_t id);
|
||||
BaseCombatAIComponent(Entity* parentEntity, int32_t componentID);
|
||||
~BaseCombatAIComponent() override;
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
@@ -234,6 +234,8 @@ public:
|
||||
// Ignore a threat for a certain amount of time
|
||||
void IgnoreThreat(const LWOOBJID target, const float time);
|
||||
|
||||
bool MsgGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Returns the current target or the target that currently is the largest threat to this entity
|
||||
|
||||
@@ -8,15 +8,33 @@
|
||||
#include "GameMessages.h"
|
||||
#include "BitStream.h"
|
||||
#include "eTriggerEventType.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
BouncerComponent::BouncerComponent(Entity* parent) : Component(parent) {
|
||||
BouncerComponent::BouncerComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_PetEnabled = false;
|
||||
m_PetBouncerEnabled = false;
|
||||
m_PetSwitchLoaded = false;
|
||||
m_Destination = GeneralUtils::TryParse<NiPoint3>(
|
||||
GeneralUtils::SplitString(m_Parent->GetVarAsString(u"bouncer_destination"), '\x1f'))
|
||||
.value_or(NiPoint3Constant::ZERO);
|
||||
m_Speed = GeneralUtils::TryParse<float>(m_Parent->GetVarAsString(u"bouncer_speed")).value_or(-1.0f);
|
||||
m_UsesHighArc = GeneralUtils::TryParse<bool>(m_Parent->GetVarAsString(u"bouncer_uses_high_arc")).value_or(false);
|
||||
m_LockControls = GeneralUtils::TryParse<bool>(m_Parent->GetVarAsString(u"lock_controls")).value_or(false);
|
||||
m_IgnoreCollision = !GeneralUtils::TryParse<bool>(m_Parent->GetVarAsString(u"ignore_collision")).value_or(true);
|
||||
m_StickLanding = GeneralUtils::TryParse<bool>(m_Parent->GetVarAsString(u"stickLanding")).value_or(false);
|
||||
m_UsesGroupName = GeneralUtils::TryParse<bool>(m_Parent->GetVarAsString(u"uses_group_name")).value_or(false);
|
||||
m_GroupName = m_Parent->GetVarAsString(u"grp_name");
|
||||
m_MinNumTargets = GeneralUtils::TryParse<int32_t>(m_Parent->GetVarAsString(u"num_targets_to_activate")).value_or(1);
|
||||
m_CinematicPath = m_Parent->GetVarAsString(u"attached_cinematic_path");
|
||||
|
||||
if (parent->GetLOT() == 7625) {
|
||||
LookupPetSwitch();
|
||||
}
|
||||
|
||||
{
|
||||
using namespace GameMessages;
|
||||
RegisterMsg<GetObjectReportInfo>(this, &BouncerComponent::MsgGetObjectReportInfo);
|
||||
}
|
||||
}
|
||||
|
||||
BouncerComponent::~BouncerComponent() {
|
||||
@@ -94,3 +112,54 @@ void BouncerComponent::LookupPetSwitch() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool BouncerComponent::MsgGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
auto& cmptType = reportMsg.info->PushDebug("Bouncer");
|
||||
cmptType.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
|
||||
auto& destPos = cmptType.PushDebug("Destination Position");
|
||||
if (m_Destination != NiPoint3Constant::ZERO) {
|
||||
destPos.PushDebug(m_Destination);
|
||||
} else {
|
||||
destPos.PushDebug("<font color=\'#FF0000\'>WARNING:</font> Bouncer has no target position, is likely missing config data");
|
||||
}
|
||||
|
||||
|
||||
if (m_Speed == -1.0f) {
|
||||
cmptType.PushDebug("<font color=\'#FF0000\'>WARNING:</font> Bouncer has no speed value, is likely missing config data");
|
||||
} else {
|
||||
cmptType.PushDebug<AMFDoubleValue>("Bounce Speed") = m_Speed;
|
||||
}
|
||||
cmptType.PushDebug<AMFStringValue>("Bounce trajectory arc") = m_UsesHighArc ? "High Arc" : "Low Arc";
|
||||
cmptType.PushDebug<AMFBoolValue>("Collision Enabled") = m_IgnoreCollision;
|
||||
cmptType.PushDebug<AMFBoolValue>("Stick Landing") = m_StickLanding;
|
||||
cmptType.PushDebug<AMFBoolValue>("Locks character's controls") = m_LockControls;
|
||||
if (!m_CinematicPath.empty()) cmptType.PushDebug<AMFStringValue>("Cinematic Camera Path (plays during bounce)") = m_CinematicPath;
|
||||
|
||||
auto* switchComponent = m_Parent->GetComponent<SwitchComponent>();
|
||||
auto& respondsToFactions = cmptType.PushDebug("Responds to Factions");
|
||||
if (!switchComponent || switchComponent->GetFactionsToRespondTo().empty()) respondsToFactions.PushDebug("Faction 1");
|
||||
else {
|
||||
for (const auto faction : switchComponent->GetFactionsToRespondTo()) {
|
||||
respondsToFactions.PushDebug(("Faction " + std::to_string(faction)));
|
||||
}
|
||||
}
|
||||
|
||||
cmptType.PushDebug<AMFBoolValue>("Uses a group name for interactions") = m_UsesGroupName;
|
||||
if (!m_UsesGroupName) {
|
||||
if (m_MinNumTargets > 1) {
|
||||
cmptType.PushDebug("<font color=\'#FF0000\'>WARNING:</font> Bouncer has a required number of objects to activate, but no group for interactions.");
|
||||
}
|
||||
|
||||
if (!m_GroupName.empty()) {
|
||||
cmptType.PushDebug("<font color=\'#FF0000\'>WARNING:</font> Has a group name for interactions , but is marked to not use that name.");
|
||||
}
|
||||
} else {
|
||||
if (m_GroupName.empty()) {
|
||||
cmptType.PushDebug("<font color=\'#FF0000\'>WARNING:</font> Set to use a group name for inter actions, but no group name is assigned");
|
||||
}
|
||||
cmptType.PushDebug<AMFIntValue>("Number of interactions to activate bouncer") = m_MinNumTargets;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class BouncerComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BOUNCER;
|
||||
|
||||
BouncerComponent(Entity* parentEntity);
|
||||
BouncerComponent(Entity* parentEntity, const int32_t componentID);
|
||||
~BouncerComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
@@ -51,6 +51,8 @@ public:
|
||||
*/
|
||||
void LookupPetSwitch();
|
||||
|
||||
bool MsgGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Whether this bouncer needs to be activated by a pet
|
||||
@@ -66,6 +68,36 @@ private:
|
||||
* Whether the pet switch for this bouncer has been located
|
||||
*/
|
||||
bool m_PetSwitchLoaded;
|
||||
|
||||
// The bouncer destination
|
||||
NiPoint3 m_Destination;
|
||||
|
||||
// The speed at which the player is bounced
|
||||
float m_Speed{};
|
||||
|
||||
// Whether to use a high arc for the bounce trajectory
|
||||
bool m_UsesHighArc{};
|
||||
|
||||
// Lock controls when bouncing
|
||||
bool m_LockControls{};
|
||||
|
||||
// Ignore collision when bouncing
|
||||
bool m_IgnoreCollision{};
|
||||
|
||||
// Stick the landing afterwards or let the player slide
|
||||
bool m_StickLanding{};
|
||||
|
||||
// Whether or not there is a group name
|
||||
bool m_UsesGroupName{};
|
||||
|
||||
// The group name for targets
|
||||
std::string m_GroupName{};
|
||||
|
||||
// The number of targets to activate the bouncer
|
||||
int32_t m_MinNumTargets{};
|
||||
|
||||
// The cinematic path to play during the bounce
|
||||
std::string m_CinematicPath{};
|
||||
};
|
||||
|
||||
#endif // BOUNCERCOMPONENT_H
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
BuffComponent::BuffComponent(Entity* parent) : Component(parent) {
|
||||
BuffComponent::BuffComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
}
|
||||
|
||||
BuffComponent::~BuffComponent() {
|
||||
|
||||
@@ -51,7 +51,7 @@ class BuffComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BUFF;
|
||||
|
||||
explicit BuffComponent(Entity* parent);
|
||||
explicit BuffComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
~BuffComponent();
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "Item.h"
|
||||
#include "PropertyManagementComponent.h"
|
||||
|
||||
BuildBorderComponent::BuildBorderComponent(Entity* parent) : Component(parent) {
|
||||
BuildBorderComponent::BuildBorderComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
}
|
||||
|
||||
BuildBorderComponent::~BuildBorderComponent() {
|
||||
|
||||
@@ -18,7 +18,7 @@ class BuildBorderComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::BUILD_BORDER;
|
||||
|
||||
BuildBorderComponent(Entity* parent);
|
||||
BuildBorderComponent(Entity* parent, const int32_t componentID);
|
||||
~BuildBorderComponent() override;
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "MessageType/Game.h"
|
||||
#include <ctime>
|
||||
|
||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress) : Component(parent) {
|
||||
CharacterComponent::CharacterComponent(Entity* parent, const int32_t componentID, Character* character, const SystemAddress& systemAddress) : Component(parent, componentID) {
|
||||
m_Character = character;
|
||||
|
||||
m_IsRacing = false;
|
||||
@@ -70,7 +70,7 @@ bool CharacterComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
for (const auto zoneID : m_VisitedLevels) {
|
||||
std::stringstream sstream;
|
||||
sstream << "MapID: " << zoneID.GetMapID() << " CloneID: " << zoneID.GetCloneID();
|
||||
vl.PushDebug<AMFStringValue>(sstream.str()) = "";
|
||||
vl.PushDebug(sstream.str());
|
||||
}
|
||||
|
||||
// visited locations
|
||||
@@ -84,6 +84,30 @@ bool CharacterComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
cmptType.PushDebug<AMFIntValue>("Current Activity Type") = GeneralUtils::ToUnderlying(m_CurrentActivity);
|
||||
cmptType.PushDebug<AMFDoubleValue>("Property Clone ID") = m_Character->GetPropertyCloneID();
|
||||
|
||||
auto& flagCmptType = reportInfo.info->PushDebug("Player Flag");
|
||||
auto& allFlags = flagCmptType.PushDebug("All flags");
|
||||
|
||||
for (const auto& [id, flagChunk] : m_Character->GetPlayerFlags()) {
|
||||
const auto base = id * 64;
|
||||
auto flagChunkCopy = flagChunk;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (static_cast<bool>(flagChunkCopy & 1)) {
|
||||
const int32_t flagId = base + i;
|
||||
std::stringstream stream;
|
||||
stream << "Flag: " << flagId;
|
||||
allFlags.PushDebug(stream.str());
|
||||
}
|
||||
flagChunkCopy >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto& sessionFlags = flagCmptType.PushDebug("Session Only Flags");
|
||||
for (const auto flagId : m_Character->GetSessionFlags()) {
|
||||
std::stringstream stream;
|
||||
stream << "Flag: " << flagId;
|
||||
sessionFlags.PushDebug(stream.str());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -859,7 +883,7 @@ void CharacterComponent::SendToZone(LWOMAPID zoneId, LWOCLONEID cloneId) const {
|
||||
character->SetZoneID(zoneID);
|
||||
character->SetZoneInstance(zoneInstance);
|
||||
character->SetZoneClone(zoneClone);
|
||||
|
||||
|
||||
characterComponent->SetLastRocketConfig(u"");
|
||||
characterComponent->AddVisitedLevel(LWOZONEID(zoneID, LWOINSTANCEID_INVALID, zoneClone));
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ class CharacterComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::CHARACTER;
|
||||
|
||||
CharacterComponent(Entity* parent, Character* character, const SystemAddress& systemAddress);
|
||||
CharacterComponent(Entity* parent, const int32_t componentID, Character* character, const SystemAddress& systemAddress);
|
||||
~CharacterComponent() override;
|
||||
|
||||
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
|
||||
|
||||
@@ -1,5 +1,39 @@
|
||||
#include "CollectibleComponent.h"
|
||||
|
||||
#include "MissionComponent.h"
|
||||
#include "dServer.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
CollectibleComponent::CollectibleComponent(Entity* parentEntity, const int32_t componentID, const int32_t collectibleId) :
|
||||
Component(parentEntity, componentID), m_CollectibleId(collectibleId) {
|
||||
using namespace GameMessages;
|
||||
RegisterMsg<GetObjectReportInfo>(this, &CollectibleComponent::MsgGetObjectReportInfo);
|
||||
}
|
||||
|
||||
void CollectibleComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {
|
||||
outBitStream.Write(GetCollectibleId());
|
||||
}
|
||||
|
||||
bool CollectibleComponent::MsgGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
auto& cmptType = reportMsg.info->PushDebug("Collectible");
|
||||
auto collectibleID = static_cast<uint32_t>(m_CollectibleId) + static_cast<uint32_t>(Game::server->GetZoneID() << 8);
|
||||
|
||||
cmptType.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
|
||||
|
||||
cmptType.PushDebug<AMFIntValue>("Collectible ID") = GetCollectibleId();
|
||||
cmptType.PushDebug<AMFIntValue>("Mission Tracking ID (for save data)") = collectibleID;
|
||||
|
||||
auto* localCharEntity = Game::entityManager->GetEntity(reportMsg.clientID);
|
||||
bool collected = false;
|
||||
if (localCharEntity) {
|
||||
auto* missionComponent = localCharEntity->GetComponent<MissionComponent>();
|
||||
|
||||
if (m_CollectibleId != 0) {
|
||||
collected = missionComponent->HasCollectible(collectibleID);
|
||||
}
|
||||
}
|
||||
|
||||
cmptType.PushDebug<AMFBoolValue>("Has been collected") = collected;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
class CollectibleComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::COLLECTIBLE;
|
||||
CollectibleComponent(Entity* parentEntity, int32_t collectibleId) : Component(parentEntity), m_CollectibleId(collectibleId) {}
|
||||
CollectibleComponent(Entity* parentEntity, const int32_t componentID, const int32_t collectibleId);
|
||||
|
||||
int16_t GetCollectibleId() const { return m_CollectibleId; }
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool isConstruction) override;
|
||||
|
||||
bool MsgGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
private:
|
||||
int16_t m_CollectibleId = 0;
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ class Entity;
|
||||
*/
|
||||
class Component {
|
||||
public:
|
||||
Component(Entity* parent) : m_Parent{ parent } {}
|
||||
Component(Entity* parent, const int32_t componentID) : m_Parent{ parent }, m_ComponentID{componentID} {}
|
||||
virtual ~Component() = default;
|
||||
|
||||
/**
|
||||
@@ -28,6 +28,8 @@ public:
|
||||
*/
|
||||
Entity* GetParent() const { return m_Parent; }
|
||||
|
||||
[[nodiscard]] int32_t GetComponentID() const noexcept { return m_ComponentID; }
|
||||
|
||||
/**
|
||||
* Updates the component in the game loop
|
||||
* @param deltaTime time passed since last update
|
||||
@@ -70,4 +72,11 @@ protected:
|
||||
* The entity that owns this component
|
||||
*/
|
||||
Entity* m_Parent;
|
||||
|
||||
// The component ID, this should never be changed after initialization
|
||||
// This is used in various different ways
|
||||
// 1. To identify which entry this component is in its corresponding table
|
||||
// 2. To mark that an Entity should have the component with no database entry (it will be 0 in this case)
|
||||
// 3. The component exists implicitly due to design (CollectibleComponent always has a DestructibleComponent accompanying it). In this case the ID will be -1.
|
||||
const int32_t m_ComponentID;
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "StringifiedEnum.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity, int32_t componentId) : PhysicsComponent(entity, componentId) {
|
||||
ControllablePhysicsComponent::ControllablePhysicsComponent(Entity* entity, const int32_t componentID) : PhysicsComponent(entity, componentID) {
|
||||
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &ControllablePhysicsComponent::OnGetObjectReportInfo);
|
||||
|
||||
m_Velocity = {};
|
||||
|
||||
@@ -25,7 +25,7 @@ class ControllablePhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::CONTROLLABLE_PHYSICS;
|
||||
|
||||
ControllablePhysicsComponent(Entity* entity, int32_t componentId);
|
||||
ControllablePhysicsComponent(Entity* entity, const int32_t componentID);
|
||||
~ControllablePhysicsComponent() override;
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#include "Logger.h"
|
||||
#include "Game.h"
|
||||
#include "dConfig.h"
|
||||
#include "CDLootMatrixTable.h"
|
||||
#include "CDLootTableTable.h"
|
||||
#include "CDRarityTableTable.h"
|
||||
|
||||
#include "Amf3.h"
|
||||
#include "AmfSerialize.h"
|
||||
@@ -37,13 +40,14 @@
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eStateChangeType.h"
|
||||
#include "eGameActivity.h"
|
||||
#include <ranges>
|
||||
|
||||
#include "CDComponentsRegistryTable.h"
|
||||
|
||||
Implementation<bool, const Entity*> DestroyableComponent::IsEnemyImplentation;
|
||||
Implementation<bool, const Entity*> DestroyableComponent::IsFriendImplentation;
|
||||
|
||||
DestroyableComponent::DestroyableComponent(Entity* parent) : Component(parent) {
|
||||
DestroyableComponent::DestroyableComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
using namespace GameMessages;
|
||||
m_iArmor = 0;
|
||||
m_fMaxArmor = 0.0f;
|
||||
@@ -666,11 +670,6 @@ void DestroyableComponent::Damage(uint32_t damage, const LWOOBJID source, uint32
|
||||
return;
|
||||
}
|
||||
|
||||
//check if hardcore mode is enabled
|
||||
if (Game::entityManager->GetHardcoreMode()) {
|
||||
DoHardcoreModeDrops(source);
|
||||
}
|
||||
|
||||
Smash(source, eKillType::VIOLENT, u"", skillID);
|
||||
}
|
||||
|
||||
@@ -698,6 +697,13 @@ void DestroyableComponent::NotifySubscribers(Entity* attacker, uint32_t damage)
|
||||
}
|
||||
|
||||
void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType, const std::u16string& deathType, uint32_t skillID) {
|
||||
if (m_IsDead) return;
|
||||
|
||||
//check if hardcore mode is enabled
|
||||
if (Game::entityManager->GetHardcoreMode()) {
|
||||
DoHardcoreModeDrops(source);
|
||||
}
|
||||
|
||||
if (m_iHealth > 0) {
|
||||
SetArmor(0);
|
||||
SetHealth(0);
|
||||
@@ -705,6 +711,7 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
|
||||
m_IsDead = true;
|
||||
m_KillerID = source;
|
||||
|
||||
auto* owner = Game::entityManager->GetEntity(source);
|
||||
@@ -752,40 +759,11 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
//NANI?!
|
||||
if (!isPlayer) {
|
||||
if (owner != nullptr) {
|
||||
auto* team = TeamManager::Instance()->GetTeam(owner->GetObjectID());
|
||||
|
||||
if (team != nullptr && m_Parent->GetComponent<BaseCombatAIComponent>() != nullptr) {
|
||||
LWOOBJID specificOwner = LWOOBJID_EMPTY;
|
||||
auto* scriptedActivityComponent = m_Parent->GetComponent<ScriptedActivityComponent>();
|
||||
uint32_t teamSize = team->members.size();
|
||||
uint32_t lootMatrixId = GetLootMatrixID();
|
||||
|
||||
if (scriptedActivityComponent) {
|
||||
lootMatrixId = scriptedActivityComponent->GetLootMatrixForTeamSize(teamSize);
|
||||
}
|
||||
|
||||
if (team->lootOption == 0) { // Round robin
|
||||
specificOwner = TeamManager::Instance()->GetNextLootOwner(team);
|
||||
|
||||
auto* member = Game::entityManager->GetEntity(specificOwner);
|
||||
|
||||
if (member) Loot::DropLoot(member, m_Parent->GetObjectID(), lootMatrixId, GetMinCoins(), GetMaxCoins());
|
||||
} else {
|
||||
for (const auto memberId : team->members) { // Free for all
|
||||
auto* member = Game::entityManager->GetEntity(memberId);
|
||||
|
||||
if (member == nullptr) continue;
|
||||
|
||||
Loot::DropLoot(member, m_Parent->GetObjectID(), lootMatrixId, GetMinCoins(), GetMaxCoins());
|
||||
}
|
||||
}
|
||||
} else { // drop loot for non team user
|
||||
Loot::DropLoot(owner, m_Parent->GetObjectID(), GetLootMatrixID(), GetMinCoins(), GetMaxCoins());
|
||||
}
|
||||
Loot::DropLoot(owner, m_Parent->GetObjectID(), GetLootMatrixID(), GetMinCoins(), GetMaxCoins());
|
||||
}
|
||||
} else {
|
||||
//Check if this zone allows coin drops
|
||||
if (Game::zoneManager->GetPlayerLoseCoinOnDeath()) {
|
||||
if (Game::zoneManager->GetPlayerLoseCoinOnDeath() && !Game::entityManager->GetHardcoreMode()) {
|
||||
auto* character = m_Parent->GetCharacter();
|
||||
uint64_t coinsTotal = character->GetCoins();
|
||||
const uint64_t minCoinsToLose = Game::zoneManager->GetWorldConfig().coinsLostOnDeathMin;
|
||||
@@ -798,7 +776,15 @@ void DestroyableComponent::Smash(const LWOOBJID source, const eKillType killType
|
||||
|
||||
coinsTotal -= coinsToLose;
|
||||
|
||||
Loot::DropLoot(m_Parent, m_Parent->GetObjectID(), -1, coinsToLose, coinsToLose);
|
||||
GameMessages::DropClientLoot lootMsg{};
|
||||
lootMsg.target = m_Parent->GetObjectID();
|
||||
lootMsg.ownerID = m_Parent->GetObjectID();
|
||||
lootMsg.currency = coinsToLose;
|
||||
lootMsg.spawnPos = m_Parent->GetPosition();
|
||||
lootMsg.sourceID = source;
|
||||
lootMsg.item = LOT_NULL;
|
||||
lootMsg.Send();
|
||||
lootMsg.Send(m_Parent->GetSystemAddress());
|
||||
character->SetCoins(coinsTotal, eLootSourceType::PICKUP);
|
||||
}
|
||||
}
|
||||
@@ -981,7 +967,8 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
||||
auto* character = m_Parent->GetComponent<CharacterComponent>();
|
||||
auto uscore = character->GetUScore();
|
||||
|
||||
auto uscoreToLose = uscore * (Game::entityManager->GetHardcoreLoseUscoreOnDeathPercent() / 100);
|
||||
auto uscoreToLose = static_cast<uint64_t>(uscore * (Game::entityManager->GetHardcoreLoseUscoreOnDeathPercent() / 100.0f));
|
||||
LOG("Player %llu has lost %llu uscore!", m_Parent->GetObjectID(), uscoreToLose);
|
||||
character->SetUScore(uscore - uscoreToLose);
|
||||
|
||||
GameMessages::SendModifyLEGOScore(m_Parent, m_Parent->GetSystemAddress(), -uscoreToLose, eLootSourceType::MISSION);
|
||||
@@ -995,13 +982,18 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
||||
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);
|
||||
for (const auto item : itemMap | std::views::values) {
|
||||
// Don't drop excluded items or null ones
|
||||
if (!item || Game::entityManager->GetHardcoreExcludedItemDrops().contains(item->GetLot())) continue;
|
||||
GameMessages::DropClientLoot lootMsg{};
|
||||
lootMsg.target = m_Parent->GetObjectID();
|
||||
lootMsg.ownerID = m_Parent->GetObjectID();
|
||||
lootMsg.sourceID = m_Parent->GetObjectID();
|
||||
lootMsg.item = item->GetLot();
|
||||
lootMsg.count = 1;
|
||||
lootMsg.spawnPos = m_Parent->GetPosition();
|
||||
for (int i = 0; i < item->GetCount(); i++) Loot::DropItem(*m_Parent, lootMsg);
|
||||
item->SetCount(0, false, false);
|
||||
}
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}
|
||||
@@ -1012,32 +1004,55 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
||||
//get character:
|
||||
auto* chars = m_Parent->GetCharacter();
|
||||
if (chars) {
|
||||
auto coins = chars->GetCoins();
|
||||
auto oldCoins = chars->GetCoins();
|
||||
// Floor this so there arent coins generated from rounding
|
||||
auto coins = static_cast<uint64_t>(oldCoins * Game::entityManager->GetHardcoreCoinKeep());
|
||||
auto coinsToDrop = oldCoins - coins;
|
||||
LOG("Player had %llu coins, will lose %i coins to have %i", oldCoins, coinsToDrop, coins);
|
||||
|
||||
//lose all coins:
|
||||
chars->SetCoins(0, eLootSourceType::NONE);
|
||||
chars->SetCoins(coins, eLootSourceType::NONE);
|
||||
|
||||
//drop all coins:
|
||||
GameMessages::SendDropClientLoot(m_Parent, source, LOT_NULL, coins, m_Parent->GetPosition());
|
||||
constexpr auto MAX_TO_DROP_PER_GM = 100'000;
|
||||
GameMessages::DropClientLoot lootMsg{};
|
||||
lootMsg.target = m_Parent->GetObjectID();
|
||||
lootMsg.ownerID = m_Parent->GetObjectID();
|
||||
lootMsg.spawnPos = m_Parent->GetPosition();
|
||||
lootMsg.sourceID = source;
|
||||
lootMsg.item = LOT_NULL;
|
||||
lootMsg.Send();
|
||||
lootMsg.Send(m_Parent->GetSystemAddress());
|
||||
while (coinsToDrop > MAX_TO_DROP_PER_GM) {
|
||||
LOG("Dropping 100,000, %llu left", coinsToDrop);
|
||||
lootMsg.currency = 100'000;
|
||||
lootMsg.Send();
|
||||
lootMsg.Send(m_Parent->GetSystemAddress());
|
||||
coinsToDrop -= 100'000;
|
||||
}
|
||||
lootMsg.currency = coinsToDrop;
|
||||
lootMsg.Send();
|
||||
lootMsg.Send(m_Parent->GetSystemAddress());
|
||||
}
|
||||
|
||||
// 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
|
||||
Game::entityManager->DestructEntity(m_Parent);
|
||||
Game::entityManager->ConstructEntity(m_Parent);
|
||||
return;
|
||||
}
|
||||
|
||||
//award the player some u-score:
|
||||
auto* player = Game::entityManager->GetEntity(source);
|
||||
if (player && player->IsPlayer()) {
|
||||
const auto lot = m_Parent->GetLOT();
|
||||
auto* playerStats = player->GetComponent<CharacterComponent>();
|
||||
if (playerStats) {
|
||||
if (playerStats && GetMaxHealth() > 0 && !Game::entityManager->GetHardcoreUscoreExcludedEnemies().contains(lot)) {
|
||||
//get the maximum health from this enemy:
|
||||
auto maxHealth = GetMaxHealth();
|
||||
const auto uscoreMultiplier = Game::entityManager->GetHardcoreUscoreEnemiesMultiplier();
|
||||
const bool isUscoreReducedLot =
|
||||
Game::entityManager->GetHardcoreUscoreReducedLots().contains(lot) ||
|
||||
Game::entityManager->GetHardcoreUscoreReduced();
|
||||
const auto uscoreReduction = isUscoreReducedLot ? Game::entityManager->GetHardcoreUscoreReduction() : 1.0f;
|
||||
|
||||
int uscore = maxHealth * Game::entityManager->GetHardcoreUscoreEnemiesMultiplier();
|
||||
|
||||
int uscore = maxHealth * Game::entityManager->GetHardcoreUscoreEnemiesMultiplier() * uscoreReduction;
|
||||
LOG("Rewarding player %llu with %i uscore for killing enemy %i", player->GetObjectID(), uscore, lot);
|
||||
playerStats->SetUScore(playerStats->GetUScore() + uscore);
|
||||
GameMessages::SendModifyLEGOScore(player, player->GetSystemAddress(), uscore, eLootSourceType::MISSION);
|
||||
|
||||
@@ -1048,38 +1063,89 @@ void DestroyableComponent::DoHardcoreModeDrops(const LWOOBJID source) {
|
||||
|
||||
bool DestroyableComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
|
||||
auto& destroyableInfo = reportInfo.info->PushDebug("Destroyable");
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Health") = m_iHealth;
|
||||
destroyableInfo.PushDebug<AMFDoubleValue>("Max Health") = m_fMaxHealth;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Armor") = m_iArmor;
|
||||
destroyableInfo.PushDebug<AMFDoubleValue>("Max Armor") = m_fMaxArmor;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Imagination") = m_iImagination;
|
||||
destroyableInfo.PushDebug<AMFDoubleValue>("Max Imagination") = m_fMaxImagination;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Damage To Absorb") = m_DamageToAbsorb;
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Is GM Immune") = m_IsGMImmune;
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Is Shielded") = m_IsShielded;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("DestructibleComponent DB Table Template ID") = m_ComponentID;
|
||||
|
||||
if (m_CurrencyIndex == -1) {
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Has Loot Currency") = false;
|
||||
} else {
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Loot Currency ID") = m_CurrencyIndex;
|
||||
auto& detailedCoinInfo = destroyableInfo.PushDebug("Coin Info");
|
||||
detailedCoinInfo.PushDebug<AMFIntValue>("Min Coins") = m_MinCoins;
|
||||
detailedCoinInfo.PushDebug<AMFIntValue>("Max Coins") = m_MaxCoins;
|
||||
}
|
||||
|
||||
if (m_LootMatrixID == -1 || m_LootMatrixID == 0) {
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Has Loot Matrix") = false;
|
||||
} else {
|
||||
auto& lootInfo = destroyableInfo.PushDebug("Loot Info");
|
||||
lootInfo.PushDebug<AMFIntValue>("Loot Matrix ID") = m_LootMatrixID;
|
||||
auto* const componentsRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
|
||||
auto* const itemComponentTable = CDClientManager::GetTable<CDItemComponentTable>();
|
||||
auto* const lootMatrixTable = CDClientManager::GetTable<CDLootMatrixTable>();
|
||||
auto* const lootTableTable = CDClientManager::GetTable<CDLootTableTable>();
|
||||
auto* const rarityTableTable = CDClientManager::GetTable<CDRarityTableTable>();
|
||||
|
||||
const auto& matrix = lootMatrixTable->GetMatrix(m_LootMatrixID);
|
||||
|
||||
for (const auto& entry : matrix) {
|
||||
auto& thisEntry = lootInfo.PushDebug("Loot table Index - " + std::to_string(entry.LootTableIndex));
|
||||
thisEntry.PushDebug<AMFDoubleValue>("Percent chance to drop") = entry.percent * 100.0f;
|
||||
thisEntry.PushDebug<AMFDoubleValue>("Minimum amount to drop") = entry.minToDrop;
|
||||
thisEntry.PushDebug<AMFDoubleValue>("Maximum amount to drop") = entry.maxToDrop;
|
||||
const auto& lootTable = lootTableTable->GetTable(entry.LootTableIndex);
|
||||
const auto& rarityTable = rarityTableTable->GetRarityTable(entry.RarityTableIndex);
|
||||
|
||||
auto& thisRarity = thisEntry.PushDebug("Rarity");
|
||||
for (const auto& rarity : rarityTable) {
|
||||
thisRarity.PushDebug<AMFDoubleValue>("Rarity " + std::to_string(rarity.rarity)) = rarity.randmax;
|
||||
}
|
||||
|
||||
auto& thisItems = thisEntry.PushDebug("Drop(s) Info");
|
||||
for (const auto& loot : lootTable) {
|
||||
uint32_t itemComponentId = componentsRegistryTable->GetByIDAndType(loot.itemid, eReplicaComponentType::ITEM);
|
||||
uint32_t rarity = itemComponentTable->GetItemComponentByID(itemComponentId).rarity;
|
||||
auto title = "%[Objects_" + std::to_string(loot.itemid) + "_name] " + std::to_string(loot.itemid);
|
||||
if (loot.MissionDrop) title += " - Mission Drop";
|
||||
thisItems.PushDebug(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto* const entity = Game::entityManager->GetEntity(reportInfo.clientID);
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Is on your team") = entity ? IsFriend(entity) : false;
|
||||
auto& stats = destroyableInfo.PushDebug("Statistics");
|
||||
stats.PushDebug<AMFIntValue>("Health") = m_iHealth;
|
||||
stats.PushDebug<AMFDoubleValue>("Maximum Health") = m_fMaxHealth;
|
||||
stats.PushDebug<AMFIntValue>("Armor") = m_iArmor;
|
||||
stats.PushDebug<AMFDoubleValue>("Maximum Armor") = m_fMaxArmor;
|
||||
stats.PushDebug<AMFIntValue>("Imagination") = m_iImagination;
|
||||
stats.PushDebug<AMFDoubleValue>("Maximum Imagination") = m_fMaxImagination;
|
||||
stats.PushDebug<AMFIntValue>("Damage Absorption Points") = m_DamageToAbsorb;
|
||||
stats.PushDebug<AMFBoolValue>("Is GM Immune") = m_IsGMImmune;
|
||||
stats.PushDebug<AMFBoolValue>("Is Shielded") = m_IsShielded;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Attacks To Block") = m_AttacksToBlock;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Damage Reduction") = m_DamageReduction;
|
||||
auto& factions = destroyableInfo.PushDebug("Factions");
|
||||
size_t i = 0;
|
||||
std::stringstream factionsStream;
|
||||
for (const auto factionID : m_FactionIDs) {
|
||||
factions.PushDebug<AMFStringValue>(std::to_string(i++) + " " + std::to_string(factionID)) = "";
|
||||
factionsStream << factionID << " ";
|
||||
}
|
||||
auto& enemyFactions = destroyableInfo.PushDebug("Enemy Factions");
|
||||
i = 0;
|
||||
|
||||
destroyableInfo.PushDebug<AMFStringValue>("Factions") = factionsStream.str();
|
||||
|
||||
factionsStream.str("");
|
||||
for (const auto enemyFactionID : m_EnemyFactionIDs) {
|
||||
enemyFactions.PushDebug<AMFStringValue>(std::to_string(i++) + " " + std::to_string(enemyFactionID)) = "";
|
||||
factionsStream << enemyFactionID << " ";
|
||||
}
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Is Smashable") = m_IsSmashable;
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Is Dead") = m_IsDead;
|
||||
|
||||
destroyableInfo.PushDebug<AMFStringValue>("Enemy Factions") = factionsStream.str();
|
||||
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Is A Smashable") = m_IsSmashable;
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Is Smashed") = m_IsSmashed;
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Is Module Assembly") = m_IsModuleAssembly;
|
||||
destroyableInfo.PushDebug<AMFDoubleValue>("Explode Factor") = m_ExplodeFactor;
|
||||
destroyableInfo.PushDebug<AMFBoolValue>("Has Threats") = m_HasThreats;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Loot Matrix ID") = m_LootMatrixID;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Min Coins") = m_MinCoins;
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Max Coins") = m_MaxCoins;
|
||||
|
||||
destroyableInfo.PushDebug<AMFStringValue>("Killer ID") = std::to_string(m_KillerID);
|
||||
|
||||
// "Scripts"; idk what to do about scripts yet
|
||||
@@ -1094,7 +1160,25 @@ bool DestroyableComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
immuneCounts.PushDebug<AMFIntValue>("Quickbuild Interrupt") = m_ImmuneToQuickbuildInterruptCount;
|
||||
immuneCounts.PushDebug<AMFIntValue>("Pull To Point") = m_ImmuneToPullToPointCount;
|
||||
|
||||
destroyableInfo.PushDebug<AMFIntValue>("Death Behavior") = m_DeathBehavior;
|
||||
auto& deathInfo = destroyableInfo.PushDebug("Death Info");
|
||||
deathInfo.PushDebug<AMFBoolValue>("Is Dead") = m_IsDead;
|
||||
switch (m_DeathBehavior) {
|
||||
case 0:
|
||||
deathInfo.PushDebug<AMFStringValue>("Death Behavior") = "Fade";
|
||||
break;
|
||||
case 1:
|
||||
deathInfo.PushDebug<AMFStringValue>("Death Behavior") = "Stay";
|
||||
break;
|
||||
case 2:
|
||||
deathInfo.PushDebug<AMFStringValue>("Death Behavior") = "Immediate";
|
||||
break;
|
||||
case -1:
|
||||
deathInfo.PushDebug<AMFStringValue>("Death Behavior") = "Invulnerable";
|
||||
break;
|
||||
default:
|
||||
deathInfo.PushDebug<AMFStringValue>("Death Behavior") = "Other";
|
||||
break;
|
||||
}
|
||||
destroyableInfo.PushDebug<AMFDoubleValue>("Damage Cooldown Timer") = m_DamageCooldownTimer;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -26,7 +26,7 @@ class DestroyableComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
|
||||
|
||||
DestroyableComponent(Entity* parentEntity);
|
||||
DestroyableComponent(Entity* parentEntity, const int32_t componentID);
|
||||
~DestroyableComponent() override;
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
@@ -370,6 +370,8 @@ public:
|
||||
*/
|
||||
uint32_t GetLootMatrixID() const { return m_LootMatrixID; }
|
||||
|
||||
void SetCurrencyIndex(int32_t currencyIndex) { m_CurrencyIndex = currencyIndex; }
|
||||
|
||||
/**
|
||||
* Returns the ID of the entity that killed this entity, if any
|
||||
* @return the ID of the entity that killed this entity, if any
|
||||
@@ -471,6 +473,8 @@ public:
|
||||
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
bool OnSetFaction(GameMessages::GameMsg& msg);
|
||||
|
||||
void SetIsDead(const bool value) { m_IsDead = value; }
|
||||
|
||||
static Implementation<bool, const Entity*> IsEnemyImplentation;
|
||||
static Implementation<bool, const Entity*> IsFriendImplentation;
|
||||
|
||||
@@ -585,6 +589,9 @@ private:
|
||||
*/
|
||||
uint32_t m_LootMatrixID;
|
||||
|
||||
// The currency index to determine how much loot to drop
|
||||
int32_t m_CurrencyIndex{ -1 };
|
||||
|
||||
/**
|
||||
* The min amount of coins that will drop when this entity is smashed
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "DonationVendorComponent.h"
|
||||
#include "Database.h"
|
||||
|
||||
DonationVendorComponent::DonationVendorComponent(Entity* parent) : VendorComponent(parent) {
|
||||
DonationVendorComponent::DonationVendorComponent(Entity* parent, const int32_t componentID) : VendorComponent(parent, componentID) {
|
||||
//LoadConfigData
|
||||
m_PercentComplete = 0.0;
|
||||
m_TotalDonated = 0;
|
||||
|
||||
@@ -9,7 +9,7 @@ class Entity;
|
||||
class DonationVendorComponent final : public VendorComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR;
|
||||
DonationVendorComponent(Entity* parent);
|
||||
DonationVendorComponent(Entity* parent, const int32_t componentID);
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
uint32_t GetActivityID() {return m_ActivityId;};
|
||||
void SubmitDonation(uint32_t count);
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
#include "GhostComponent.h"
|
||||
|
||||
GhostComponent::GhostComponent(Entity* parent) : Component(parent) {
|
||||
#include "Amf3.h"
|
||||
#include "GameMessages.h"
|
||||
|
||||
GhostComponent::GhostComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_GhostReferencePoint = NiPoint3Constant::ZERO;
|
||||
m_GhostOverridePoint = NiPoint3Constant::ZERO;
|
||||
m_GhostOverride = false;
|
||||
|
||||
RegisterMsg<GameMessages::GetObjectReportInfo>(this, &GhostComponent::MsgGetObjectReportInfo);
|
||||
}
|
||||
|
||||
GhostComponent::~GhostComponent() {
|
||||
@@ -55,3 +60,12 @@ bool GhostComponent::IsObserved(LWOOBJID id) {
|
||||
void GhostComponent::GhostEntity(LWOOBJID id) {
|
||||
m_ObservedEntities.erase(id);
|
||||
}
|
||||
|
||||
bool GhostComponent::MsgGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
auto& cmptType = reportMsg.info->PushDebug("Ghost");
|
||||
cmptType.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
|
||||
cmptType.PushDebug<AMFBoolValue>("Is GM Invis") = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ class NiPoint3;
|
||||
class GhostComponent final : public Component {
|
||||
public:
|
||||
static inline const eReplicaComponentType ComponentType = eReplicaComponentType::GHOST;
|
||||
GhostComponent(Entity* parent);
|
||||
GhostComponent(Entity* parent, const int32_t componentID);
|
||||
~GhostComponent() override;
|
||||
|
||||
void SetGhostOverride(bool value) { m_GhostOverride = value; };
|
||||
@@ -39,6 +39,8 @@ public:
|
||||
|
||||
void GhostEntity(const LWOOBJID id);
|
||||
|
||||
bool MsgGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
|
||||
private:
|
||||
NiPoint3 m_GhostReferencePoint;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "EntityManager.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
||||
HavokVehiclePhysicsComponent::HavokVehiclePhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
|
||||
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &HavokVehiclePhysicsComponent::OnGetObjectReportInfo);
|
||||
|
||||
m_Velocity = NiPoint3Constant::ZERO;
|
||||
|
||||
@@ -13,7 +13,7 @@ class HavokVehiclePhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS;
|
||||
|
||||
HavokVehiclePhysicsComponent(Entity* parentEntity, int32_t componentId);
|
||||
HavokVehiclePhysicsComponent(Entity* parentEntity, const int32_t componentID);
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
|
||||
@@ -39,10 +39,13 @@
|
||||
#include "CDObjectSkillsTable.h"
|
||||
#include "CDSkillBehaviorTable.h"
|
||||
#include "StringifiedEnum.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
InventoryComponent::InventoryComponent(Entity* parent) : Component(parent) {
|
||||
InventoryComponent::InventoryComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
using namespace GameMessages;
|
||||
RegisterMsg<GetObjectReportInfo>(this, &InventoryComponent::OnGetObjectReportInfo);
|
||||
this->m_Dirty = true;
|
||||
this->m_Equipped = {};
|
||||
this->m_Pushed = {};
|
||||
@@ -279,7 +282,14 @@ void InventoryComponent::AddItem(
|
||||
|
||||
case 1:
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
GameMessages::SendDropClientLoot(this->m_Parent, this->m_Parent->GetObjectID(), lot, 0, this->m_Parent->GetPosition(), 1);
|
||||
GameMessages::DropClientLoot lootMsg{};
|
||||
lootMsg.target = m_Parent->GetObjectID();
|
||||
lootMsg.ownerID = m_Parent->GetObjectID();
|
||||
lootMsg.sourceID = m_Parent->GetObjectID();
|
||||
lootMsg.item = lot;
|
||||
lootMsg.count = 1;
|
||||
lootMsg.spawnPos = m_Parent->GetPosition();
|
||||
Loot::DropItem(*m_Parent, lootMsg);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -440,7 +450,7 @@ Item* InventoryComponent::FindItemBySubKey(LWOOBJID id, eInventoryType inventory
|
||||
}
|
||||
}
|
||||
|
||||
bool InventoryComponent::HasSpaceForLoot(const std::unordered_map<LOT, int32_t>& loot) {
|
||||
bool InventoryComponent::HasSpaceForLoot(const Loot::Return& loot) {
|
||||
std::unordered_map<eInventoryType, int32_t> spaceOffset{};
|
||||
|
||||
uint32_t slotsNeeded = 0;
|
||||
@@ -626,7 +636,8 @@ void InventoryComponent::UpdateXml(tinyxml2::XMLDocument& document) {
|
||||
for (const auto& pair : this->m_Inventories) {
|
||||
auto* inventory = pair.second;
|
||||
|
||||
if (inventory->GetType() == VENDOR_BUYBACK || inventory->GetType() == eInventoryType::MODELS_IN_BBB) {
|
||||
static const auto EXCLUDED_INVENTORIES = { VENDOR_BUYBACK, MODELS_IN_BBB, ITEM_SETS };
|
||||
if (std::ranges::find(EXCLUDED_INVENTORIES, inventory->GetType()) != EXCLUDED_INVENTORIES.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1786,3 +1797,105 @@ void InventoryComponent::LoadGroupXml(const tinyxml2::XMLElement& groups) {
|
||||
groupElement = groupElement->NextSiblingElement("grp");
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryComponent::RegenerateItemIDs() {
|
||||
for (auto* const inventory : m_Inventories | std::views::values) {
|
||||
inventory->RegenerateItemIDs();
|
||||
}
|
||||
}
|
||||
|
||||
std::string DebugInvToString(const eInventoryType inv, bool verbose) {
|
||||
switch (inv) {
|
||||
case ITEMS:
|
||||
return "Backpack";
|
||||
case VAULT_ITEMS:
|
||||
return "Bank";
|
||||
case BRICKS:
|
||||
return verbose ? "Bricks" : "Bricks (contents only shown in high-detail report)";
|
||||
case MODELS_IN_BBB:
|
||||
return "Models in BBB";
|
||||
case TEMP_ITEMS:
|
||||
return "Temp Equip";
|
||||
case MODELS:
|
||||
return verbose ? "Model" : "Model (contents only shown in high-detail report)";
|
||||
case TEMP_MODELS:
|
||||
return "Module";
|
||||
case BEHAVIORS:
|
||||
return "B3 Behavior";
|
||||
case PROPERTY_DEEDS:
|
||||
return "Property";
|
||||
case BRICKS_IN_BBB:
|
||||
return "Brick In BBB";
|
||||
case VENDOR:
|
||||
return "Vendor";
|
||||
case VENDOR_BUYBACK:
|
||||
return "BuyBack";
|
||||
case QUEST:
|
||||
return "Quest";
|
||||
case DONATION:
|
||||
return "Donation";
|
||||
case VAULT_MODELS:
|
||||
return "Bank Model";
|
||||
case ITEM_SETS:
|
||||
return "Bank Behavior";
|
||||
case INVALID:
|
||||
return "Invalid";
|
||||
case ALL:
|
||||
return "All";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool InventoryComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
auto& report = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
auto& cmpt = report.info->PushDebug("Inventory");
|
||||
cmpt.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
|
||||
uint32_t numItems = 0;
|
||||
for (auto* inventory : m_Inventories | std::views::values) numItems += inventory->GetItems().size();
|
||||
cmpt.PushDebug<AMFIntValue>("Inventory Item Count") = numItems;
|
||||
|
||||
auto& itemsInBags = cmpt.PushDebug("Items in bags");
|
||||
for (const auto& [id, inventoryMut] : m_Inventories) {
|
||||
if (!inventoryMut) continue;
|
||||
const auto* const inventory = inventoryMut;
|
||||
auto& curInv = itemsInBags.PushDebug(DebugInvToString(id, report.bVerbose) + " - " + std::to_string(id));
|
||||
for (uint32_t i = 0; i < inventory->GetSize(); i++) {
|
||||
const auto* const item = inventory->FindItemBySlot(i);
|
||||
if (!item) continue;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "%[Objects_" << item->GetLot() << "_name] Slot " << item->GetSlot();
|
||||
auto& slot = curInv.PushDebug(ss.str());
|
||||
slot.PushDebug<AMFStringValue>("Object ID") = std::to_string(item->GetId());
|
||||
slot.PushDebug<AMFIntValue>("LOT") = item->GetLot();
|
||||
if (item->GetSubKey() != LWOOBJID_EMPTY) slot.PushDebug<AMFStringValue>("Subkey") = std::to_string(item->GetSubKey());
|
||||
slot.PushDebug<AMFIntValue>("Count") = item->GetCount();
|
||||
slot.PushDebug<AMFIntValue>("Slot") = item->GetSlot();
|
||||
slot.PushDebug<AMFBoolValue>("Bind on pickup") = item->GetInfo().isBOP;
|
||||
slot.PushDebug<AMFBoolValue>("Bind on equip") = item->GetInfo().isBOE;
|
||||
slot.PushDebug<AMFBoolValue>("Is currently bound") = item->GetBound();
|
||||
auto& extra = slot.PushDebug("Extra Info");
|
||||
for (const auto* const setting : item->GetConfig()) {
|
||||
if (setting) extra.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& equipped = cmpt.PushDebug("Equipped Items");
|
||||
for (const auto& [location, info] : GetEquippedItems()) {
|
||||
std::stringstream ss;
|
||||
ss << "%[Objects_" << info.lot << "_name]";
|
||||
auto& equipSlot = equipped.PushDebug(ss.str());
|
||||
equipSlot.PushDebug<AMFStringValue>("Location") = location;
|
||||
equipSlot.PushDebug<AMFStringValue>("Object ID") = std::to_string(info.id);
|
||||
equipSlot.PushDebug<AMFIntValue>("Slot") = info.slot;
|
||||
equipSlot.PushDebug<AMFIntValue>("Count") = info.count;
|
||||
auto& extra = equipSlot.PushDebug("Extra Info");
|
||||
for (const auto* const setting : info.config) {
|
||||
if (setting) extra.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "eInventoryType.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "eLootSourceType.h"
|
||||
#include "Loot.h"
|
||||
|
||||
class Entity;
|
||||
class ItemSet;
|
||||
@@ -67,7 +68,7 @@ public:
|
||||
static constexpr uint32_t MaximumGroupCount = 50;
|
||||
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
||||
InventoryComponent(Entity* parent);
|
||||
InventoryComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
@@ -200,7 +201,7 @@ public:
|
||||
* @param loot a map of items to add and how many to add
|
||||
* @return whether the entity has enough space for all the items
|
||||
*/
|
||||
bool HasSpaceForLoot(const std::unordered_map<LOT, int32_t>& loot);
|
||||
bool HasSpaceForLoot(const Loot::Return& loot);
|
||||
|
||||
/**
|
||||
* Equips an item in the specified slot
|
||||
@@ -402,10 +403,16 @@ public:
|
||||
bool SetSkill(BehaviorSlot slot, uint32_t skillId);
|
||||
|
||||
void UpdateGroup(const GroupUpdate& groupUpdate);
|
||||
void RemoveGroup(const std::string& groupId);
|
||||
|
||||
std::unordered_map<LWOOBJID, DatabasePet>& GetPetsMut() { return m_Pets; };
|
||||
|
||||
void FixInvisibleItems();
|
||||
|
||||
// Used to migrate a character version, no need to call outside of that context
|
||||
void RegenerateItemIDs();
|
||||
|
||||
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
|
||||
~InventoryComponent() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -8,7 +8,7 @@ class ItemComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ITEM;
|
||||
|
||||
ItemComponent(Entity* entity) : Component(entity) {}
|
||||
ItemComponent(Entity* entity, const int32_t componentID) : Component(entity, componentID) {}
|
||||
|
||||
void Serialize(RakNet::BitStream& bitStream, bool isConstruction) override;
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ class LUPExhibitComponent final : public Component
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::LUP_EXHIBIT;
|
||||
|
||||
LUPExhibitComponent(Entity* parent) : Component(parent) {};
|
||||
LUPExhibitComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {};
|
||||
void Update(float deltaTime) override;
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
void NextLUPExhibit();
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "CDRewardsTable.h"
|
||||
|
||||
LevelProgressionComponent::LevelProgressionComponent(Entity* parent) : Component(parent) {
|
||||
LevelProgressionComponent::LevelProgressionComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_Parent = parent;
|
||||
m_Level = 1;
|
||||
m_SpeedBase = 500.0f;
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
* Constructor for this component
|
||||
* @param parent parent that contains this component
|
||||
*/
|
||||
LevelProgressionComponent(Entity* parent);
|
||||
LevelProgressionComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ class MiniGameControlComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MINI_GAME_CONTROL;
|
||||
|
||||
MiniGameControlComponent(Entity* parent) : Component(parent) {}
|
||||
MiniGameControlComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {}
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool isConstruction);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
#include "MinigameComponent.h"
|
||||
|
||||
void MinigameComponent::Serialize(RakNet::BitStream& outBitStream, bool isConstruction) {
|
||||
outBitStream.Write<uint32_t>(0x40000000);
|
||||
}
|
||||
@@ -19,14 +19,20 @@
|
||||
#include "MissionPrerequisites.h"
|
||||
#include "AchievementCacheKey.h"
|
||||
#include "eMissionState.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
// MARK: Mission Component
|
||||
|
||||
std::unordered_map<AchievementCacheKey, std::vector<uint32_t>> MissionComponent::m_AchievementCache = {};
|
||||
|
||||
//! Initializer
|
||||
MissionComponent::MissionComponent(Entity* parent) : Component(parent) {
|
||||
MissionComponent::MissionComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
using namespace GameMessages;
|
||||
m_LastUsedMissionOrderUID = Game::zoneManager->GetUniqueMissionIdStartingValue();
|
||||
|
||||
RegisterMsg<GetObjectReportInfo>(this, &MissionComponent::OnGetObjectReportInfo);
|
||||
RegisterMsg<GameMessages::GetMissionState>(this, &MissionComponent::OnGetMissionState);
|
||||
RegisterMsg<GameMessages::MissionNeedsLot>(this, &MissionComponent::OnMissionNeedsLot);
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
@@ -136,6 +142,7 @@ void MissionComponent::RemoveMission(uint32_t missionId) {
|
||||
}
|
||||
|
||||
void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) {
|
||||
LOG("Progressing missions %s %i %llu %s %s", StringifiedEnum::ToString(type).data(), value, associate, targets.c_str(), ignoreAchievements ? "(ignoring achievements)" : "");
|
||||
std::vector<uint32_t> acceptedAchievements;
|
||||
if (count > 0 && !ignoreAchievements) {
|
||||
acceptedAchievements = LookForAchievements(type, value, true, associate, targets, count);
|
||||
@@ -620,3 +627,123 @@ void MissionComponent::ResetMission(const int32_t missionId) {
|
||||
m_Missions.erase(missionId);
|
||||
GameMessages::SendResetMissions(m_Parent, m_Parent->GetSystemAddress(), missionId);
|
||||
}
|
||||
|
||||
void PushMissions(const std::map<uint32_t, Mission*>& missions, AMFArrayValue& V, bool verbose) {
|
||||
for (const auto& [id, mission] : missions) {
|
||||
std::stringstream ss;
|
||||
if (!mission) {
|
||||
ss << "Mission ID: " << id;
|
||||
V.PushDebug(ss.str());
|
||||
} else if (!verbose) {
|
||||
ss << "%[Missions_" << id << "_name]" << ", Mission ID";
|
||||
V.PushDebug<AMFIntValue>(ss.str()) = id;
|
||||
} else {
|
||||
ss << "%[Missions_" << id << "_name]" << ", Mission ID: " << id;
|
||||
auto& missionV = V.PushDebug(ss.str());
|
||||
auto& missionInformation = missionV.PushDebug("Mission Information");
|
||||
|
||||
if (mission->IsComplete()) {
|
||||
missionInformation.PushDebug<AMFStringValue>("Time mission last completed") = std::to_string(mission->GetTimestamp());
|
||||
missionInformation.PushDebug<AMFIntValue>("Number of times completed") = mission->GetCompletions();
|
||||
}
|
||||
// Expensive to network this especially when its read from the client anyways
|
||||
// missionInformation.PushDebug("Description").PushDebug("None");
|
||||
// missionInformation.PushDebug("Text").PushDebug("None");
|
||||
|
||||
auto& statusInfo = missionInformation.PushDebug("Mission statuses for local player");
|
||||
if (mission->IsAvalible()) statusInfo.PushDebug("Available");
|
||||
if (mission->IsActive()) statusInfo.PushDebug("Active");
|
||||
if (mission->IsReadyToComplete()) statusInfo.PushDebug("Ready To Complete");
|
||||
if (mission->IsComplete()) statusInfo.PushDebug("Completed");
|
||||
if (mission->IsFailed()) statusInfo.PushDebug("Failed");
|
||||
const auto& clientInfo = mission->GetClientInfo();
|
||||
|
||||
statusInfo.PushDebug<AMFBoolValue>("Is an achievement mission") = mission->IsAchievement();
|
||||
statusInfo.PushDebug<AMFBoolValue>("Is an timed mission") = clientInfo.time_limit > 0;
|
||||
auto& taskInfo = statusInfo.PushDebug("Task Info");
|
||||
taskInfo.PushDebug<AMFIntValue>("Number of tasks in this mission") = mission->GetTasks().size();
|
||||
int32_t i = 0;
|
||||
for (const auto* task : mission->GetTasks()) {
|
||||
auto& thisTask = taskInfo.PushDebug("Task " + std::to_string(i));
|
||||
// Expensive to network this especially when its read from the client anyways
|
||||
// thisTask.PushDebug("Description").PushDebug("%[MissionTasks_" + taskUidStr + "_description]");
|
||||
thisTask.PushDebug<AMFIntValue>("Number done") = std::min(task->GetProgress(), static_cast<uint32_t>(task->GetClientInfo().targetValue));
|
||||
thisTask.PushDebug<AMFIntValue>("Number total needed") = task->GetClientInfo().targetValue;
|
||||
thisTask.PushDebug<AMFIntValue>("Task Type") = task->GetClientInfo().taskType;
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
// auto& chatText = missionInformation.PushDebug("Chat Text for Mission States");
|
||||
// Expensive to network this especially when its read from the client anyways
|
||||
// chatText.PushDebug("Available Text").PushDebug("%[MissionText_" + idStr + "_chat_state_1]");
|
||||
// chatText.PushDebug("Active Text").PushDebug("%[MissionText_" + idStr + "_chat_state_2]");
|
||||
// chatText.PushDebug("Ready-to-Complete Text").PushDebug("%[MissionText_" + idStr + "_chat_state_3]");
|
||||
// chatText.PushDebug("Complete Text").PushDebug("%[MissionText_" + idStr + "_chat_state_4]");
|
||||
|
||||
if (clientInfo.time_limit > 0) {
|
||||
missionInformation.PushDebug<AMFIntValue>("Time Limit") = clientInfo.time_limit;
|
||||
missionInformation.PushDebug<AMFDoubleValue>("Time Remaining") = 0;
|
||||
}
|
||||
|
||||
if (clientInfo.offer_objectID != -1) {
|
||||
missionInformation.PushDebug<AMFIntValue>("Offer Object LOT") = clientInfo.offer_objectID;
|
||||
}
|
||||
|
||||
if (clientInfo.target_objectID != -1) {
|
||||
missionInformation.PushDebug<AMFIntValue>("Complete Object LOT") = clientInfo.target_objectID;
|
||||
}
|
||||
|
||||
if (!clientInfo.prereqMissionID.empty()) {
|
||||
missionInformation.PushDebug<AMFStringValue>("Requirement Mission IDs") = clientInfo.prereqMissionID;
|
||||
}
|
||||
|
||||
missionInformation.PushDebug<AMFBoolValue>("Is Repeatable") = clientInfo.repeatable;
|
||||
const bool hasNoOfferer = clientInfo.offer_objectID == -1 || clientInfo.offer_objectID == 0;
|
||||
const bool hasNoCompleter = clientInfo.target_objectID == -1 || clientInfo.target_objectID == 0;
|
||||
missionInformation.PushDebug<AMFBoolValue>("Is Achievement") = hasNoOfferer && hasNoCompleter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MissionComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
auto& missionInfo = reportMsg.info->PushDebug("Mission (Laggy)");
|
||||
missionInfo.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
|
||||
// Sort the missions so they are easier to parse and present to the end user
|
||||
std::map<uint32_t, Mission*> achievements;
|
||||
std::map<uint32_t, Mission*> missions;
|
||||
std::map<uint32_t, Mission*> doneMissions;
|
||||
for (const auto [id, mission] : m_Missions) {
|
||||
if (!mission) continue;
|
||||
else if (mission->IsComplete()) doneMissions[id] = mission;
|
||||
else if (mission->IsAchievement()) achievements[id] = mission;
|
||||
else if (mission->IsMission()) missions[id] = mission;
|
||||
}
|
||||
|
||||
// None of these should be empty, but if they are dont print the field
|
||||
if (!achievements.empty() || !missions.empty()) {
|
||||
auto& incompleteMissions = missionInfo.PushDebug("Incomplete Missions");
|
||||
PushMissions(achievements, incompleteMissions, reportMsg.bVerbose);
|
||||
PushMissions(missions, incompleteMissions, reportMsg.bVerbose);
|
||||
}
|
||||
|
||||
if (!doneMissions.empty()) {
|
||||
auto& completeMissions = missionInfo.PushDebug("Completed Missions");
|
||||
PushMissions(doneMissions, completeMissions, reportMsg.bVerbose);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MissionComponent::OnGetMissionState(GameMessages::GameMsg& msg) {
|
||||
auto misState = static_cast<GameMessages::GetMissionState&>(msg);
|
||||
misState.missionState = GetMissionState(misState.missionID);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MissionComponent::OnMissionNeedsLot(GameMessages::GameMsg& msg) {
|
||||
const auto& needMsg = static_cast<GameMessages::MissionNeedsLot&>(msg);
|
||||
return RequiresItem(needMsg.item);
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ class MissionComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MISSION;
|
||||
|
||||
explicit MissionComponent(Entity* parent);
|
||||
explicit MissionComponent(Entity* parent, const int32_t componentID);
|
||||
~MissionComponent() override;
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
||||
void LoadFromXml(const tinyxml2::XMLDocument& doc) override;
|
||||
@@ -171,6 +171,9 @@ public:
|
||||
|
||||
void ResetMission(const int32_t missionId);
|
||||
private:
|
||||
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
bool OnGetMissionState(GameMessages::GameMsg& msg);
|
||||
bool OnMissionNeedsLot(GameMessages::GameMsg& msg);
|
||||
/**
|
||||
* All the missions owned by this entity, mapped by mission ID
|
||||
*/
|
||||
|
||||
@@ -39,19 +39,13 @@ bool OfferedMission::GetAcceptsMission() const {
|
||||
|
||||
//------------------------ MissionOfferComponent below ------------------------
|
||||
|
||||
MissionOfferComponent::MissionOfferComponent(Entity* parent, const LOT parentLot) : Component(parent) {
|
||||
auto* compRegistryTable = CDClientManager::GetTable<CDComponentsRegistryTable>();
|
||||
|
||||
auto value = compRegistryTable->GetByIDAndType(parentLot, eReplicaComponentType::MISSION_OFFER, -1);
|
||||
|
||||
if (value != -1) {
|
||||
const uint32_t componentId = value;
|
||||
|
||||
MissionOfferComponent::MissionOfferComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
if (componentID != -1) {
|
||||
// Now lookup the missions in the MissionNPCComponent table
|
||||
auto* missionNpcComponentTable = CDClientManager::GetTable<CDMissionNPCComponentTable>();
|
||||
|
||||
auto missions = missionNpcComponentTable->Query([=](const CDMissionNPCComponent& entry) {
|
||||
return entry.id == static_cast<unsigned>(componentId);
|
||||
auto missions = missionNpcComponentTable->Query([componentID](const CDMissionNPCComponent& entry) {
|
||||
return entry.id == static_cast<unsigned>(componentID);
|
||||
});
|
||||
|
||||
for (auto& mission : missions) {
|
||||
|
||||
@@ -63,7 +63,7 @@ class MissionOfferComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
|
||||
|
||||
MissionOfferComponent(Entity* parent, LOT parentLot);
|
||||
MissionOfferComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
/**
|
||||
* Handles the OnUse event triggered by some entity, determines which missions to show based on what they may
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "Database.h"
|
||||
#include "DluAssert.h"
|
||||
|
||||
ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
||||
ModelComponent::ModelComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
using namespace GameMessages;
|
||||
m_OriginalPosition = m_Parent->GetDefaultPosition();
|
||||
m_OriginalRotation = m_Parent->GetDefaultRotation();
|
||||
@@ -25,6 +25,7 @@ ModelComponent::ModelComponent(Entity* parent) : Component(parent) {
|
||||
m_userModelID = m_Parent->GetVarAs<LWOOBJID>(u"userModelID");
|
||||
RegisterMsg<RequestUse>(this, &ModelComponent::OnRequestUse);
|
||||
RegisterMsg<ResetModelToDefaults>(this, &ModelComponent::OnResetModelToDefaults);
|
||||
RegisterMsg<GetObjectReportInfo>(this, &ModelComponent::OnGetObjectReportInfo);
|
||||
}
|
||||
|
||||
bool ModelComponent::OnResetModelToDefaults(GameMessages::GameMsg& msg) {
|
||||
@@ -375,3 +376,19 @@ void ModelComponent::RemoveAttack() {
|
||||
set.Send();
|
||||
}
|
||||
}
|
||||
|
||||
bool ModelComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
auto& reportMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
if (!reportMsg.info) return false;
|
||||
auto& cmptInfo = reportMsg.info->PushDebug("Model Behaviors (Mutable)");
|
||||
cmptInfo.PushDebug<AMFIntValue>("Component ID") = GetComponentID();
|
||||
|
||||
cmptInfo.PushDebug<AMFStringValue>("Name") = "Objects_" + std::to_string(m_Parent->GetLOT()) + "_name";
|
||||
cmptInfo.PushDebug<AMFBoolValue>("Has Unique Name") = false;
|
||||
cmptInfo.PushDebug<AMFStringValue>("UGID (from item)") = std::to_string(m_userModelID);
|
||||
cmptInfo.PushDebug<AMFStringValue>("UGID") = std::to_string(m_userModelID);
|
||||
cmptInfo.PushDebug<AMFStringValue>("Description") = "";
|
||||
cmptInfo.PushDebug<AMFIntValue>("Behavior Count") = m_Behaviors.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,13 +27,14 @@ class ModelComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MODEL;
|
||||
|
||||
ModelComponent(Entity* parent);
|
||||
ModelComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
void LoadBehaviors();
|
||||
void Update(float deltaTime) override;
|
||||
|
||||
bool OnRequestUse(GameMessages::GameMsg& msg);
|
||||
bool OnResetModelToDefaults(GameMessages::GameMsg& msg);
|
||||
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "ModuleAssemblyComponent.h"
|
||||
|
||||
ModuleAssemblyComponent::ModuleAssemblyComponent(Entity* parent) : Component(parent) {
|
||||
ModuleAssemblyComponent::ModuleAssemblyComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_SubKey = LWOOBJID_EMPTY;
|
||||
m_UseOptionalParts = false;
|
||||
m_AssemblyPartsLOTs = u"";
|
||||
|
||||
@@ -14,7 +14,7 @@ class ModuleAssemblyComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
|
||||
|
||||
ModuleAssemblyComponent(Entity* parent);
|
||||
ModuleAssemblyComponent(Entity* parent, const int32_t componentID);
|
||||
~ModuleAssemblyComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace {
|
||||
std::map<LOT, float> m_PhysicsSpeedCache;
|
||||
}
|
||||
|
||||
MovementAIComponent::MovementAIComponent(Entity* parent, MovementAIInfo info) : Component(parent) {
|
||||
MovementAIComponent::MovementAIComponent(Entity* parent, const int32_t componentID, MovementAIInfo info) : Component(parent, componentID) {
|
||||
m_Info = info;
|
||||
m_AtFinalWaypoint = true;
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class MovementAIComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MOVEMENT_AI;
|
||||
|
||||
MovementAIComponent(Entity* parentEntity, MovementAIInfo info);
|
||||
MovementAIComponent(Entity* parentEntity, const int32_t componentID, MovementAIInfo info);
|
||||
|
||||
void SetPath(const std::string pathName);
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ void MoverSubComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIniti
|
||||
|
||||
//------------- MovingPlatformComponent below --------------
|
||||
|
||||
MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const std::string& pathName) : Component(parent) {
|
||||
MovingPlatformComponent::MovingPlatformComponent(Entity* parent, const int32_t componentID, const std::string& pathName) : Component(parent, componentID) {
|
||||
m_MoverSubComponentType = eMoverSubComponentType::mover;
|
||||
m_MoverSubComponent = new MoverSubComponent(m_Parent->GetDefaultPosition());
|
||||
m_PathName = GeneralUtils::ASCIIToUTF16(pathName);
|
||||
|
||||
@@ -108,7 +108,7 @@ class MovingPlatformComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::MOVING_PLATFORM;
|
||||
|
||||
MovingPlatformComponent(Entity* parent, const std::string& pathName);
|
||||
MovingPlatformComponent(Entity* parent, const int32_t componentID, const std::string& pathName);
|
||||
~MovingPlatformComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "InventoryComponent.h"
|
||||
#include "CharacterComponent.h"
|
||||
|
||||
MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent) : Component(parent) {
|
||||
MultiZoneEntranceComponent::MultiZoneEntranceComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_Parent = parent;
|
||||
std::string zoneString = GeneralUtils::UTF16ToWTF8(m_Parent->GetVar<std::u16string>(u"MultiZoneIDs"));
|
||||
std::stringstream ss(zoneString);
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
* Constructor for this component, builds the m_LUPWorlds vector
|
||||
* @param parent parent that contains this component
|
||||
*/
|
||||
MultiZoneEntranceComponent(Entity* parent);
|
||||
MultiZoneEntranceComponent(Entity* parent, const int32_t componentID);
|
||||
~MultiZoneEntranceComponent() override;
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,9 +10,11 @@
|
||||
#include "InventoryComponent.h"
|
||||
#include "Item.h"
|
||||
#include "MissionComponent.h"
|
||||
#include "User.h"
|
||||
#include "SwitchComponent.h"
|
||||
#include "DestroyableComponent.h"
|
||||
#include "dpWorld.h"
|
||||
#include "UserManager.h"
|
||||
#include "PetDigServer.h"
|
||||
#include "ObjectIDManager.h"
|
||||
#include "eUnequippableActiveType.h"
|
||||
@@ -21,6 +23,7 @@
|
||||
#include "eUseItemResponse.h"
|
||||
#include "ePlayerFlag.h"
|
||||
|
||||
#include "GeneralUtils.h"
|
||||
#include "Game.h"
|
||||
#include "dConfig.h"
|
||||
#include "dChatFilter.h"
|
||||
@@ -43,9 +46,8 @@ std::unordered_map<LWOOBJID, LWOOBJID> PetComponent::activePets{};
|
||||
* while the faction ones could be checked using their respective missions.
|
||||
*/
|
||||
|
||||
PetComponent::PetComponent(Entity* parentEntity, uint32_t componentId) : Component{ parentEntity } {
|
||||
m_PetInfo = CDClientManager::GetTable<CDPetComponentTable>()->GetByID(componentId); // TODO: Make reference when safe
|
||||
m_ComponentId = componentId;
|
||||
PetComponent::PetComponent(Entity* parentEntity, const int32_t componentID) : Component{ parentEntity, componentID } {
|
||||
m_PetInfo = CDClientManager::GetTable<CDPetComponentTable>()->GetByID(componentID); // TODO: Make reference when safe
|
||||
|
||||
m_Interaction = LWOOBJID_EMPTY;
|
||||
m_Owner = LWOOBJID_EMPTY;
|
||||
@@ -479,10 +481,19 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
return;
|
||||
}
|
||||
|
||||
LWOOBJID petSubKey = ObjectIDManager::GenerateRandomObjectID();
|
||||
LWOOBJID petSubKey = ObjectIDManager::GetPersistentID();
|
||||
const uint32_t maxTries = 100;
|
||||
uint32_t tries = 0;
|
||||
while (Database::Get()->GetPetNameInfo(petSubKey) && tries < maxTries) {
|
||||
tries++;
|
||||
LOG("Found a duplicate pet %llu, getting a new subKey", petSubKey);
|
||||
petSubKey = ObjectIDManager::GetPersistentID();
|
||||
}
|
||||
|
||||
GeneralUtils::SetBit(petSubKey, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(petSubKey, eObjectBits::PERSISTENT);
|
||||
if (tries >= maxTries) {
|
||||
LOG("Failed to get a unique pet subKey after %i tries, aborting pet creation for player %i", maxTries, tamer->GetCharacter() ? tamer->GetCharacter()->GetID() : -1);
|
||||
return;
|
||||
}
|
||||
|
||||
m_DatabaseId = petSubKey;
|
||||
|
||||
@@ -528,7 +539,7 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
|
||||
// Triggers the catch a pet missions
|
||||
constexpr auto PET_FLAG_BASE = 800;
|
||||
tamer->GetCharacter()->SetPlayerFlag(PET_FLAG_BASE + m_ComponentId, true);
|
||||
tamer->GetCharacter()->SetPlayerFlag(PET_FLAG_BASE + m_ComponentID, true);
|
||||
|
||||
auto* missionComponent = tamer->GetComponent<MissionComponent>();
|
||||
|
||||
@@ -545,18 +556,29 @@ void PetComponent::NotifyTamingBuildSuccess(NiPoint3 position) {
|
||||
}
|
||||
|
||||
void PetComponent::RequestSetPetName(std::u16string name) {
|
||||
const bool autoRejectNames = UserManager::Instance()->GetMuteAutoRejectNames();
|
||||
|
||||
if (m_Tamer == LWOOBJID_EMPTY) {
|
||||
if (m_Owner != LWOOBJID_EMPTY) {
|
||||
auto* owner = GetOwner();
|
||||
|
||||
m_ModerationStatus = 1; // Pending
|
||||
m_Name = "";
|
||||
// If auto reject names is on, and the user is muted, force use of predefined name
|
||||
if (autoRejectNames && owner && owner->GetCharacter() && owner->GetCharacter()->GetParentUser()->GetIsMuted()) {
|
||||
m_ModerationStatus = 2; // Approved
|
||||
std::string forcedName = "Pet";
|
||||
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{ forcedName, static_cast<int32_t>(m_ModerationStatus) });
|
||||
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
|
||||
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
|
||||
} else {
|
||||
m_ModerationStatus = 1; // Pending
|
||||
m_Name = "";
|
||||
|
||||
//Save our pet's new name to the db:
|
||||
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
|
||||
//Save our pet's new name to the db:
|
||||
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
|
||||
|
||||
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
|
||||
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
|
||||
GameMessages::SendSetPetName(m_Owner, GeneralUtils::UTF8ToUTF16(m_Name), m_DatabaseId, owner->GetSystemAddress());
|
||||
GameMessages::SendSetPetNameModerated(m_Owner, m_DatabaseId, m_ModerationStatus, owner->GetSystemAddress());
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -578,11 +600,21 @@ void PetComponent::RequestSetPetName(std::u16string name) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_ModerationStatus = 1; // Pending
|
||||
m_Name = "";
|
||||
// If auto reject names is on, and the user is muted, force use of predefined name ELSE proceed with normal name check
|
||||
if (autoRejectNames && tamer->GetCharacter() && tamer->GetCharacter()->GetParentUser()->GetIsMuted()) {
|
||||
m_ModerationStatus = 2; // Approved
|
||||
m_Name = "";
|
||||
std::string forcedName = "Pet";
|
||||
|
||||
//Save our pet's new name to the db:
|
||||
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
|
||||
Database::Get()->SetPetNameModerationStatus(m_DatabaseId, IPetNames::Info{ forcedName, static_cast<int32_t>(m_ModerationStatus) });
|
||||
LOG("AccountID: %i is muted, forcing use of predefined pet name", tamer->GetCharacter()->GetParentUser()->GetAccountID());
|
||||
} else {
|
||||
m_ModerationStatus = 1; // Pending
|
||||
m_Name = "";
|
||||
|
||||
//Save our pet's new name to the db:
|
||||
SetPetNameForModeration(GeneralUtils::UTF16ToWTF8(name));
|
||||
}
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class PetComponent final : public Component
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PET;
|
||||
|
||||
explicit PetComponent(Entity* parentEntity, uint32_t componentId);
|
||||
explicit PetComponent(Entity* parentEntity, const int32_t componentID);
|
||||
~PetComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
@@ -250,11 +250,6 @@ private:
|
||||
*/
|
||||
static std::unordered_map<LWOOBJID, LWOOBJID> currentActivities;
|
||||
|
||||
/**
|
||||
* The ID of the component in the pet component table
|
||||
*/
|
||||
uint32_t m_ComponentId;
|
||||
|
||||
/**
|
||||
* The ID of the model that was built to complete the taming minigame for this pet
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
#include "dpShapeBox.h"
|
||||
#include "dpShapeSphere.h"
|
||||
|
||||
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
||||
PhantomPhysicsComponent::PhantomPhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
|
||||
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &PhantomPhysicsComponent::OnGetObjectReportInfo);
|
||||
|
||||
m_Position = m_Parent->GetDefaultPosition();
|
||||
|
||||
@@ -28,7 +28,7 @@ class PhantomPhysicsComponent final : public PhysicsComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PHANTOM_PHYSICS;
|
||||
|
||||
PhantomPhysicsComponent(Entity* parent, int32_t componentId);
|
||||
PhantomPhysicsComponent(Entity* parent, const int32_t componentID);
|
||||
~PhantomPhysicsComponent() override;
|
||||
void Update(float deltaTime) override;
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "EntityInfo.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Component(parent) {
|
||||
PhysicsComponent::PhysicsComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_Position = NiPoint3Constant::ZERO;
|
||||
m_Rotation = QuatUtils::IDENTITY;
|
||||
m_DirtyPosition = false;
|
||||
@@ -23,7 +23,7 @@ PhysicsComponent::PhysicsComponent(Entity* parent, int32_t componentId) : Compon
|
||||
CDPhysicsComponentTable* physicsComponentTable = CDClientManager::GetTable<CDPhysicsComponentTable>();
|
||||
|
||||
if (physicsComponentTable) {
|
||||
auto* info = physicsComponentTable->GetByID(componentId);
|
||||
auto* info = physicsComponentTable->GetByID(componentID);
|
||||
if (info) {
|
||||
m_CollisionGroup = info->collisionGroup;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class dpEntity;
|
||||
|
||||
class PhysicsComponent : public Component {
|
||||
public:
|
||||
PhysicsComponent(Entity* parent, int32_t componentId);
|
||||
PhysicsComponent(Entity* parent, const int32_t componentID);
|
||||
virtual ~PhysicsComponent() = default;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "PlayerForcedMovementComponent.h"
|
||||
|
||||
PlayerForcedMovementComponent::PlayerForcedMovementComponent(Entity* parent) : Component(parent) {
|
||||
PlayerForcedMovementComponent::PlayerForcedMovementComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_Parent = parent;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
* Constructor for this component
|
||||
* @param parent parent that contains this component
|
||||
*/
|
||||
PlayerForcedMovementComponent(Entity* parent);
|
||||
PlayerForcedMovementComponent(Entity* parent, const int32_t componentID);
|
||||
~PlayerForcedMovementComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "Inventory.h"
|
||||
#include "Item.h"
|
||||
|
||||
PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId) : Component(parent) {
|
||||
PossessableComponent::PossessableComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_Possessor = LWOOBJID_EMPTY;
|
||||
CDItemComponent item = Inventory::FindItemComponent(m_Parent->GetLOT());
|
||||
m_AnimationFlag = static_cast<eAnimationFlags>(item.animationFlag);
|
||||
@@ -12,7 +12,7 @@ PossessableComponent::PossessableComponent(Entity* parent, uint32_t componentId)
|
||||
// Get the possession Type from the CDClient
|
||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT possessionType, depossessOnHit FROM PossessableComponent WHERE id = ?;");
|
||||
|
||||
query.bind(1, static_cast<int>(componentId));
|
||||
query.bind(1, static_cast<int>(componentID));
|
||||
|
||||
auto result = query.execQuery();
|
||||
|
||||
|
||||
@@ -16,15 +16,10 @@ class PossessableComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSABLE;
|
||||
|
||||
PossessableComponent(Entity* parentEntity, uint32_t componentId);
|
||||
PossessableComponent(Entity* parentEntity, const int32_t componentID);
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
/**
|
||||
* @brief mounts the Entity
|
||||
*/
|
||||
void Mount();
|
||||
|
||||
/**
|
||||
* @brief dismounts the Entity
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "eControlScheme.h"
|
||||
#include "eStateChangeType.h"
|
||||
|
||||
PossessorComponent::PossessorComponent(Entity* parent) : Component(parent) {
|
||||
PossessorComponent::PossessorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_Possessable = LWOOBJID_EMPTY;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class PossessorComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::POSSESSOR;
|
||||
|
||||
PossessorComponent(Entity* parent);
|
||||
PossessorComponent(Entity* parent, const int32_t componentID);
|
||||
~PossessorComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
class PropertyComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY;
|
||||
explicit PropertyComponent(Entity* const parentEntity) noexcept : Component{ parentEntity } {}
|
||||
explicit PropertyComponent(Entity* const parentEntity, const int32_t componentID) noexcept : Component{ parentEntity, componentID } {}
|
||||
};
|
||||
|
||||
#endif // !PROPERTYCOMPONENT_H
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "ePropertySortType.h"
|
||||
#include "User.h"
|
||||
|
||||
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, uint32_t componentID) : Component(parent) {
|
||||
PropertyEntranceComponent::PropertyEntranceComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
this->propertyQueries = {};
|
||||
|
||||
auto table = CDClientManager::GetTable<CDPropertyEntranceComponentTable>();
|
||||
@@ -135,7 +135,7 @@ void PropertyEntranceComponent::OnPropertyEntranceSync(Entity* entity, bool incl
|
||||
const auto owner = propertyEntry.ownerId;
|
||||
const auto otherCharacter = Database::Get()->GetCharacterInfo(owner);
|
||||
if (!otherCharacter.has_value()) {
|
||||
LOG("Failed to find property owner name for %u!", owner);
|
||||
LOG("Failed to find property owner name for %llu!", owner);
|
||||
continue;
|
||||
}
|
||||
auto& entry = entries.emplace_back();
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
class PropertyEntranceComponent final : public Component {
|
||||
public:
|
||||
explicit PropertyEntranceComponent(Entity* parent, uint32_t componentID);
|
||||
explicit PropertyEntranceComponent(Entity* parent, const int32_t componentID);
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_ENTRANCE;
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
PropertyManagementComponent* PropertyManagementComponent::instance = nullptr;
|
||||
|
||||
PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Component(parent) {
|
||||
PropertyManagementComponent::PropertyManagementComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
this->owner = LWOOBJID_EMPTY;
|
||||
this->templateId = 0;
|
||||
this->propertyId = LWOOBJID_EMPTY;
|
||||
@@ -64,7 +64,6 @@ PropertyManagementComponent::PropertyManagementComponent(Entity* parent) : Compo
|
||||
this->propertyId = propertyInfo->id;
|
||||
this->owner = propertyInfo->ownerId;
|
||||
GeneralUtils::SetBit(this->owner, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(this->owner, eObjectBits::PERSISTENT);
|
||||
this->clone_Id = propertyInfo->cloneId;
|
||||
this->propertyName = propertyInfo->name;
|
||||
this->propertyDescription = propertyInfo->description;
|
||||
@@ -171,7 +170,7 @@ void PropertyManagementComponent::UpdatePropertyDetails(std::string name, std::s
|
||||
info.name = propertyName;
|
||||
info.description = propertyDescription;
|
||||
info.lastUpdatedTime = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
|
||||
Database::Get()->UpdateLastSave(info);
|
||||
Database::Get()->UpdatePropertyDetails(info);
|
||||
|
||||
@@ -204,14 +203,22 @@ bool PropertyManagementComponent::Claim(const LWOOBJID playerId) {
|
||||
|
||||
auto prop_path = zone->GetPath(m_Parent->GetVarAsString(u"propertyName"));
|
||||
|
||||
if (prop_path){
|
||||
if (prop_path) {
|
||||
if (!prop_path->property.displayName.empty()) name = prop_path->property.displayName;
|
||||
description = prop_path->property.displayDesc;
|
||||
}
|
||||
|
||||
SetOwnerId(playerId);
|
||||
|
||||
propertyId = ObjectIDManager::GenerateRandomObjectID();
|
||||
// Due to legacy IDs being random
|
||||
propertyId = ObjectIDManager::GetPersistentID();
|
||||
const uint32_t maxTries = 100;
|
||||
uint32_t tries = 0;
|
||||
while (Database::Get()->GetPropertyInfo(propertyId) && tries < maxTries) {
|
||||
tries++;
|
||||
LOG("Found a duplicate property %llu, getting a new propertyId", propertyId);
|
||||
propertyId = ObjectIDManager::GetPersistentID();
|
||||
}
|
||||
|
||||
IProperty::Info info;
|
||||
info.id = propertyId;
|
||||
@@ -375,46 +382,45 @@ void PropertyManagementComponent::UpdateModelPosition(const LWOOBJID id, const N
|
||||
node->position = position;
|
||||
node->rotation = rotation;
|
||||
|
||||
ObjectIDManager::RequestPersistentID([this, node, modelLOT, entity, position, rotation, originalRotation](uint32_t persistentId) {
|
||||
SpawnerInfo info{};
|
||||
SpawnerInfo info{};
|
||||
|
||||
info.templateID = modelLOT;
|
||||
info.nodes = { node };
|
||||
info.templateScale = 1.0f;
|
||||
info.activeOnLoad = true;
|
||||
info.amountMaintained = 1;
|
||||
info.respawnTime = 10;
|
||||
info.templateID = modelLOT;
|
||||
info.nodes = { node };
|
||||
info.templateScale = 1.0f;
|
||||
info.activeOnLoad = true;
|
||||
info.amountMaintained = 1;
|
||||
info.respawnTime = 10;
|
||||
|
||||
info.emulated = true;
|
||||
info.emulator = Game::entityManager->GetZoneControlEntity()->GetObjectID();
|
||||
info.emulated = true;
|
||||
info.emulator = Game::entityManager->GetZoneControlEntity()->GetObjectID();
|
||||
|
||||
info.spawnerID = persistentId;
|
||||
GeneralUtils::SetBit(info.spawnerID, eObjectBits::CLIENT);
|
||||
info.spawnerID = ObjectIDManager::GetPersistentID();
|
||||
GeneralUtils::SetBit(info.spawnerID, eObjectBits::CLIENT);
|
||||
|
||||
const auto spawnerId = Game::zoneManager->MakeSpawner(info);
|
||||
const auto spawnerId = Game::zoneManager->MakeSpawner(info);
|
||||
|
||||
auto* spawner = Game::zoneManager->GetSpawner(spawnerId);
|
||||
auto* spawner = Game::zoneManager->GetSpawner(spawnerId);
|
||||
|
||||
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0));
|
||||
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"userModelID", info.spawnerID));
|
||||
info.nodes[0]->config.push_back(new LDFData<int>(u"modelType", 2));
|
||||
info.nodes[0]->config.push_back(new LDFData<bool>(u"propertyObjectID", true));
|
||||
info.nodes[0]->config.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"modelBehaviors", 0));
|
||||
info.nodes[0]->config.push_back(new LDFData<LWOOBJID>(u"userModelID", info.spawnerID));
|
||||
info.nodes[0]->config.push_back(new LDFData<int>(u"modelType", 2));
|
||||
info.nodes[0]->config.push_back(new LDFData<bool>(u"propertyObjectID", true));
|
||||
info.nodes[0]->config.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
|
||||
auto* model = spawner->Spawn();
|
||||
auto* modelComponent = model->GetComponent<ModelComponent>();
|
||||
if (modelComponent) modelComponent->Pause();
|
||||
auto* model = spawner->Spawn();
|
||||
auto* modelComponent = model->GetComponent<ModelComponent>();
|
||||
if (modelComponent) modelComponent->Pause();
|
||||
|
||||
models.insert_or_assign(model->GetObjectID(), spawnerId);
|
||||
models.insert_or_assign(model->GetObjectID(), spawnerId);
|
||||
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), position, m_Parent->GetObjectID(), 14, originalRotation);
|
||||
GameMessages::SendPlaceModelResponse(entity->GetObjectID(), entity->GetSystemAddress(), position, m_Parent->GetObjectID(), 14, originalRotation);
|
||||
|
||||
GameMessages::SendUGCEquipPreCreateBasedOnEditMode(entity->GetObjectID(), entity->GetSystemAddress(), 0, spawnerId);
|
||||
GameMessages::SendUGCEquipPreCreateBasedOnEditMode(entity->GetObjectID(), entity->GetSystemAddress(), 0, spawnerId);
|
||||
|
||||
GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
GameMessages::SendGetModelsOnProperty(entity->GetObjectID(), GetModels(), UNASSIGNED_SYSTEM_ADDRESS);
|
||||
|
||||
Game::entityManager->GetZoneControlEntity()->OnZonePropertyModelPlaced(entity);
|
||||
|
||||
Game::entityManager->GetZoneControlEntity()->OnZonePropertyModelPlaced(entity);
|
||||
});
|
||||
// Progress place model missions
|
||||
auto missionComponent = entity->GetComponent<MissionComponent>();
|
||||
if (missionComponent != nullptr) missionComponent->Progress(eMissionTaskType::PLACE_MODEL, 0);
|
||||
@@ -622,8 +628,6 @@ void PropertyManagementComponent::Load() {
|
||||
//BBB property models need to have extra stuff set for them:
|
||||
if (databaseModel.lot == 14) {
|
||||
LWOOBJID blueprintID = databaseModel.ugcId;
|
||||
GeneralUtils::SetBit(blueprintID, eObjectBits::CHARACTER);
|
||||
GeneralUtils::SetBit(blueprintID, eObjectBits::PERSISTENT);
|
||||
|
||||
settings.push_back(new LDFData<LWOOBJID>(u"blueprintid", blueprintID));
|
||||
settings.push_back(new LDFData<int>(u"componentWhitelist", 1));
|
||||
@@ -696,7 +700,7 @@ void PropertyManagementComponent::Save() {
|
||||
// save the behaviors of the model
|
||||
for (const auto& [behaviorId, behaviorStr] : modelBehaviors) {
|
||||
if (behaviorStr.empty() || behaviorId == -1 || behaviorId == 0) continue;
|
||||
IBehaviors::Info info {
|
||||
IBehaviors::Info info{
|
||||
.behaviorId = behaviorId,
|
||||
.characterId = character->GetID(),
|
||||
.behaviorInfo = behaviorStr
|
||||
@@ -824,7 +828,7 @@ void PropertyManagementComponent::OnChatMessageReceived(const std::string& sMess
|
||||
if (!model) continue;
|
||||
auto* const modelComponent = model->GetComponent<ModelComponent>();
|
||||
if (!modelComponent) continue;
|
||||
|
||||
|
||||
modelComponent->OnChatMessageReceived(sMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ enum class PropertyPrivacyOption {
|
||||
class PropertyManagementComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_MANAGEMENT;
|
||||
PropertyManagementComponent(Entity* parent);
|
||||
PropertyManagementComponent(Entity* parent, const int32_t componentID);
|
||||
static PropertyManagementComponent* Instance();
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "PropertyManagementComponent.h"
|
||||
#include "UserManager.h"
|
||||
|
||||
PropertyVendorComponent::PropertyVendorComponent(Entity* parent) : Component(parent) {
|
||||
PropertyVendorComponent::PropertyVendorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
}
|
||||
|
||||
void PropertyVendorComponent::OnUse(Entity* originator) {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
class PropertyVendorComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROPERTY_VENDOR;
|
||||
explicit PropertyVendorComponent(Entity* parent);
|
||||
explicit PropertyVendorComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
/**
|
||||
* Handles a use event from some entity, if the property is cleared this allows the entity to claim it
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
const std::unordered_set<LWOOBJID> ProximityMonitorComponent::m_EmptyObjectSet = {};
|
||||
|
||||
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, int radiusSmall, int radiusLarge) : Component(parent) {
|
||||
ProximityMonitorComponent::ProximityMonitorComponent(Entity* parent, const int32_t componentID, int radiusSmall, int radiusLarge) : Component(parent, componentID) {
|
||||
if (radiusSmall != -1 && radiusLarge != -1) {
|
||||
SetProximityRadius(radiusSmall, "rocketSmall");
|
||||
SetProximityRadius(radiusLarge, "rocketLarge");
|
||||
|
||||
@@ -23,7 +23,7 @@ class ProximityMonitorComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::PROXIMITY_MONITOR;
|
||||
|
||||
ProximityMonitorComponent(Entity* parentEntity, int smallRadius = -1, int largeRadius = -1);
|
||||
ProximityMonitorComponent(Entity* parentEntity, const int32_t componentID, int smallRadius = -1, int largeRadius = -1);
|
||||
~ProximityMonitorComponent() override;
|
||||
void Update(float deltaTime) override;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "CppScripts.h"
|
||||
|
||||
QuickBuildComponent::QuickBuildComponent(Entity* const entity) : Component{ entity } {
|
||||
QuickBuildComponent::QuickBuildComponent(Entity* const entity, const int32_t componentID) : Component{ entity, componentID } {
|
||||
std::u16string checkPreconditions = entity->GetVar<std::u16string>(u"CheckPrecondition");
|
||||
|
||||
if (!checkPreconditions.empty()) {
|
||||
|
||||
@@ -24,7 +24,7 @@ class QuickBuildComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::QUICK_BUILD;
|
||||
|
||||
QuickBuildComponent(Entity* const entity);
|
||||
QuickBuildComponent(Entity* const entity, const int32_t componentID);
|
||||
~QuickBuildComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#define M_PI 3.14159265358979323846264338327950288
|
||||
#endif
|
||||
|
||||
RacingControlComponent::RacingControlComponent(Entity* parent)
|
||||
: Component(parent) {
|
||||
RacingControlComponent::RacingControlComponent(Entity* parent, const int32_t componentID)
|
||||
: Component(parent, componentID) {
|
||||
m_PathName = u"MainPath";
|
||||
m_NumberOfLaps = 3;
|
||||
m_RemainingLaps = m_NumberOfLaps;
|
||||
|
||||
@@ -108,7 +108,7 @@ class RacingControlComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_CONTROL;
|
||||
|
||||
RacingControlComponent(Entity* parentEntity);
|
||||
RacingControlComponent(Entity* parentEntity, const int32_t componentID);
|
||||
~RacingControlComponent();
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -9,7 +9,7 @@ class Entity;
|
||||
class RacingSoundTriggerComponent : public SoundTriggerComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_SOUND_TRIGGER;
|
||||
RacingSoundTriggerComponent(Entity* parent) : SoundTriggerComponent(parent){};
|
||||
RacingSoundTriggerComponent(Entity* parent, const int32_t componentID) : SoundTriggerComponent(parent, componentID){};
|
||||
};
|
||||
|
||||
#endif //!__RACINGSOUNDTRIGGERCOMPONENT__H__
|
||||
|
||||
@@ -8,7 +8,7 @@ class RacingStatsComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RACING_STATS;
|
||||
|
||||
RacingStatsComponent(Entity* parent) : Component(parent) {}
|
||||
RacingStatsComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {}
|
||||
};
|
||||
|
||||
#endif //!__RACINGSTATSCOMPONENT__H__
|
||||
|
||||
@@ -11,9 +11,8 @@
|
||||
#include "EntityManager.h"
|
||||
#include "eStateChangeType.h"
|
||||
|
||||
RailActivatorComponent::RailActivatorComponent(Entity* parent, int32_t componentID) : Component(parent) {
|
||||
m_ComponentID = componentID;
|
||||
const auto tableData = CDClientManager::GetTable<CDRailActivatorComponentTable>()->GetEntryByID(componentID);;
|
||||
RailActivatorComponent::RailActivatorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
const auto tableData = CDClientManager::GetTable<CDRailActivatorComponentTable>()->GetEntryByID(componentID);
|
||||
|
||||
m_Path = parent->GetVar<std::u16string>(u"rail_path");
|
||||
m_PathDirection = parent->GetVar<bool>(u"rail_path_direction");
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
class RailActivatorComponent final : public Component {
|
||||
public:
|
||||
explicit RailActivatorComponent(Entity* parent, int32_t componentID);
|
||||
explicit RailActivatorComponent(Entity* parent, const int32_t componentID);
|
||||
~RailActivatorComponent() override;
|
||||
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RAIL_ACTIVATOR;
|
||||
@@ -37,12 +37,6 @@ public:
|
||||
*/
|
||||
void OnCancelRailMovement(Entity* originator);
|
||||
private:
|
||||
|
||||
/**
|
||||
* The ID of this component in the components database
|
||||
*/
|
||||
int32_t m_ComponentID;
|
||||
|
||||
/**
|
||||
* The entities that are currently traversing the rail
|
||||
*/
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
std::unordered_map<int32_t, float> RenderComponent::m_DurationCache{};
|
||||
|
||||
RenderComponent::RenderComponent(Entity* const parentEntity, const int32_t componentId) : Component{ parentEntity } {
|
||||
RenderComponent::RenderComponent(Entity* const parentEntity, const int32_t componentID) : Component{ parentEntity, componentID } {
|
||||
m_LastAnimationName = "";
|
||||
if (componentId == -1) return;
|
||||
if (componentID == -1) return;
|
||||
|
||||
auto query = CDClientDatabase::CreatePreppedStmt("SELECT * FROM RenderComponent WHERE id = ?;");
|
||||
query.bind(1, componentId);
|
||||
query.bind(1, componentID);
|
||||
auto result = query.execQuery();
|
||||
|
||||
if (!result.eof()) {
|
||||
|
||||
@@ -63,7 +63,7 @@ class RenderComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RENDER;
|
||||
|
||||
RenderComponent(Entity* const parentEntity, const int32_t componentId = -1);
|
||||
RenderComponent(Entity* const parentEntity, const int32_t componentID);
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
void Update(float deltaTime) override;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "EntityInfo.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent, int32_t componentId) : PhysicsComponent(parent, componentId) {
|
||||
RigidbodyPhantomPhysicsComponent::RigidbodyPhantomPhysicsComponent(Entity* parent, const int32_t componentID) : PhysicsComponent(parent, componentID) {
|
||||
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &RigidbodyPhantomPhysicsComponent::OnGetObjectReportInfo);
|
||||
|
||||
m_Position = m_Parent->GetDefaultPosition();
|
||||
|
||||
@@ -21,7 +21,7 @@ class RigidbodyPhantomPhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
|
||||
|
||||
RigidbodyPhantomPhysicsComponent(Entity* parent, int32_t componentId);
|
||||
RigidbodyPhantomPhysicsComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
void Update(const float deltaTime) override;
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
#include "ServiceType.h"
|
||||
#include "MessageType/Master.h"
|
||||
|
||||
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, int rocketId) : Component(parent) {
|
||||
RocketLaunchpadControlComponent::RocketLaunchpadControlComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
||||
"SELECT targetZone, defaultZoneID, targetScene, altLandingPrecondition, altLandingSpawnPointName FROM RocketLaunchpadControlComponent WHERE id = ?;");
|
||||
query.bind(1, rocketId);
|
||||
query.bind(1, componentID);
|
||||
|
||||
auto result = query.execQuery();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class RocketLaunchpadControlComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::ROCKET_LAUNCH;
|
||||
|
||||
RocketLaunchpadControlComponent(Entity* parent, int rocketId);
|
||||
RocketLaunchpadControlComponent(Entity* parent, const int32_t componentID);
|
||||
~RocketLaunchpadControlComponent() override;
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,16 +5,17 @@
|
||||
|
||||
#include "Entity.h"
|
||||
#include "ScriptComponent.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
ScriptComponent::ScriptComponent(Entity* parent, std::string scriptName, bool serialized, bool client) : Component(parent) {
|
||||
ScriptComponent::ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client) : Component(parent, componentID) {
|
||||
using namespace GameMessages;
|
||||
m_Serialized = serialized;
|
||||
m_Client = client;
|
||||
m_ScriptName = scriptName;
|
||||
|
||||
SetScript(scriptName);
|
||||
}
|
||||
|
||||
ScriptComponent::~ScriptComponent() {
|
||||
|
||||
RegisterMsg<GetObjectReportInfo>(this, &ScriptComponent::OnGetObjectReportInfo);
|
||||
}
|
||||
|
||||
void ScriptComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) {
|
||||
@@ -50,3 +51,16 @@ void ScriptComponent::SetScript(const std::string& scriptName) {
|
||||
// and they may also be used by other script components so DON'T delete them.
|
||||
m_Script = CppScripts::GetScript(m_Parent, scriptName);
|
||||
}
|
||||
|
||||
bool ScriptComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||
auto& infoMsg = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||
|
||||
auto& scriptInfo = infoMsg.info->PushDebug("Script");
|
||||
scriptInfo.PushDebug<AMFStringValue>("Script Name") = m_ScriptName.empty() ? "None" : m_ScriptName;
|
||||
auto& networkSettings = scriptInfo.PushDebug("Network Settings");
|
||||
for (const auto* const setting : m_Parent->GetNetworkSettings()) {
|
||||
networkSettings.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(setting->GetKey())) = setting->GetValueAsString();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@ class ScriptComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPT;
|
||||
|
||||
ScriptComponent(Entity* parent, std::string scriptName, bool serialized, bool client = false);
|
||||
~ScriptComponent() override;
|
||||
ScriptComponent(Entity* parent, const int32_t componentID, const std::string& scriptName, bool serialized, bool client = false);
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -43,6 +42,8 @@ public:
|
||||
* @param scriptName the name of the script to find
|
||||
*/
|
||||
void SetScript(const std::string& scriptName);
|
||||
|
||||
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||
|
||||
private:
|
||||
|
||||
@@ -60,6 +61,8 @@ private:
|
||||
* Whether or not this script is a client script
|
||||
*/
|
||||
bool m_Client;
|
||||
|
||||
std::string m_ScriptName;
|
||||
};
|
||||
|
||||
#endif // SCRIPTCOMPONENT_H
|
||||
|
||||
@@ -9,7 +9,7 @@ class Entity;
|
||||
class ScriptedActivityComponent final : public ActivityComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SCRIPTED_ACTIVITY;
|
||||
ScriptedActivityComponent(Entity* parent, int activityID) : ActivityComponent(parent, activityID){};
|
||||
ScriptedActivityComponent(Entity* parent, const int32_t componentID) : ActivityComponent(parent, componentID){};
|
||||
};
|
||||
|
||||
#endif //!__SCRIPTEDACTIVITYCOMPONENT__H__
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "EntityManager.h"
|
||||
#include "ScriptedActivityComponent.h"
|
||||
|
||||
ShootingGalleryComponent::ShootingGalleryComponent(Entity* parent, int32_t activityID) : ActivityComponent(parent, activityID) {
|
||||
ShootingGalleryComponent::ShootingGalleryComponent(Entity* parent, const int32_t componentID) : ActivityComponent(parent, componentID) {
|
||||
}
|
||||
|
||||
void ShootingGalleryComponent::SetStaticParams(const StaticShootingGalleryParams& params) {
|
||||
|
||||
@@ -76,7 +76,7 @@ class ShootingGalleryComponent final : public ActivityComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SHOOTING_GALLERY;
|
||||
|
||||
explicit ShootingGalleryComponent(Entity* parent, int32_t activityID);
|
||||
explicit ShootingGalleryComponent(Entity* parent, const int32_t componentID);
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool isInitialUpdate) override;
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,7 +30,7 @@ class SimplePhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SIMPLE_PHYSICS;
|
||||
|
||||
SimplePhysicsComponent(Entity* parent, int32_t componentID);
|
||||
SimplePhysicsComponent(Entity* parent, const int32_t componentID);
|
||||
~SimplePhysicsComponent() override;
|
||||
|
||||
void Update(const float deltaTime) override;
|
||||
|
||||
@@ -489,7 +489,7 @@ void SkillComponent::HandleUnCast(const uint32_t behaviorId, const LWOOBJID targ
|
||||
behavior->UnCast(&context, { target });
|
||||
}
|
||||
|
||||
SkillComponent::SkillComponent(Entity* parent) : Component(parent) {
|
||||
SkillComponent::SkillComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
this->m_skillUid = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ class SkillComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SKILL;
|
||||
|
||||
explicit SkillComponent(Entity* parent);
|
||||
explicit SkillComponent(Entity* parent, const int32_t componentID);
|
||||
~SkillComponent() override;
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
@@ -25,7 +25,7 @@ void MixerProgram::Serialize(RakNet::BitStream& outBitStream){
|
||||
outBitStream.Write(name.c_str(), name.size());
|
||||
outBitStream.Write(result);
|
||||
}
|
||||
SoundTriggerComponent::SoundTriggerComponent(Entity* parent) : Component(parent) {
|
||||
SoundTriggerComponent::SoundTriggerComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
|
||||
const auto musicCueName = parent->GetVar<std::string>(u"NDAudioMusicCue_Name");
|
||||
if (!musicCueName.empty()) {
|
||||
|
||||
@@ -60,7 +60,7 @@ struct MixerProgram {
|
||||
class SoundTriggerComponent : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SOUND_TRIGGER;
|
||||
explicit SoundTriggerComponent(Entity* parent);
|
||||
explicit SoundTriggerComponent(Entity* parent, const int32_t componentID);
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
void ActivateMusicCue(const std::string& name, float bordemTime = -1.0);
|
||||
void DeactivateMusicCue(const std::string& name);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
std::vector<SwitchComponent*> SwitchComponent::petSwitches;
|
||||
|
||||
SwitchComponent::SwitchComponent(Entity* parent) : Component(parent) {
|
||||
SwitchComponent::SwitchComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_Active = false;
|
||||
|
||||
m_ResetTime = m_Parent->GetVarAs<int32_t>(u"switch_reset_time");
|
||||
|
||||
@@ -18,7 +18,7 @@ class SwitchComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::SWITCH;
|
||||
|
||||
SwitchComponent(Entity* parent);
|
||||
SwitchComponent(Entity* parent, const int32_t componentID);
|
||||
~SwitchComponent() override;
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
@@ -67,6 +67,10 @@ public:
|
||||
*/
|
||||
static SwitchComponent* GetClosestSwitch(NiPoint3 position);
|
||||
|
||||
const std::vector<int32_t>& GetFactionsToRespondTo() const {
|
||||
return m_FactionsToRespondTo;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* A list of all pet switches.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo) : Component(parent) {
|
||||
TriggerComponent::TriggerComponent(Entity* parent, const int32_t componentID, const std::string triggerInfo) : Component(parent, componentID) {
|
||||
m_Parent = parent;
|
||||
m_Trigger = nullptr;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ class TriggerComponent final : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::TRIGGER;
|
||||
|
||||
explicit TriggerComponent(Entity* parent, const std::string triggerInfo);
|
||||
explicit TriggerComponent(Entity* parent, const int32_t componentID, const std::string triggerInfo);
|
||||
|
||||
void TriggerEvent(eTriggerEventType event, Entity* optionalTarget = nullptr);
|
||||
LUTriggers::Trigger* GetTrigger() const { return m_Trigger; }
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "UserManager.h"
|
||||
#include "CheatDetection.h"
|
||||
|
||||
VendorComponent::VendorComponent(Entity* parent) : Component(parent) {
|
||||
VendorComponent::VendorComponent(Entity* parent, const int32_t componentID) : Component(parent, componentID) {
|
||||
m_HasStandardCostItems = false;
|
||||
m_HasMultiCostItems = false;
|
||||
SetupConstants();
|
||||
|
||||
@@ -21,7 +21,7 @@ struct SoldItem {
|
||||
class VendorComponent : public Component {
|
||||
public:
|
||||
static constexpr eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR;
|
||||
VendorComponent(Entity* parent);
|
||||
VendorComponent(Entity* parent, const int32_t componentID);
|
||||
|
||||
void Serialize(RakNet::BitStream& outBitStream, bool bIsInitialUpdate) override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user