mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-11-23 05:57:20 +00:00
Merge branch 'components-wheeeee' of https://github.com/DarkflameUniverse/DarkflameServer into components-wheeeee
This commit is contained in:
commit
1b7be5d7db
@ -17,7 +17,7 @@ enum class eStateChangeType : uint32_t;
|
|||||||
* Represents the stats of an entity, for example its health, imagination and armor. Also handles factions, which
|
* Represents the stats of an entity, for example its health, imagination and armor. Also handles factions, which
|
||||||
* indicate which enemies this entity has.
|
* indicate which enemies this entity has.
|
||||||
*/
|
*/
|
||||||
class DestroyableComponent : public Component {
|
class DestroyableComponent final : public Component {
|
||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DESTROYABLE;
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
|
|
||||||
class DonationVendorComponent : public VendorComponent {
|
class DonationVendorComponent final : public VendorComponent {
|
||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR;
|
||||||
DonationVendorComponent(Entity* parent);
|
DonationVendorComponent(Entity* parent);
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
|
|
||||||
class GateRushComponent : public RacingControlComponent {
|
class GateRushComponent final : public RacingControlComponent {
|
||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::GATE_RUSH_CONTROL;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::GATE_RUSH_CONTROL;
|
||||||
GateRushComponent(Entity* parent, int32_t componentId);
|
GateRushComponent(Entity* parent, int32_t componentId);
|
||||||
|
@ -26,7 +26,7 @@ struct RemoteInputInfo {
|
|||||||
/**
|
/**
|
||||||
* Physics component for vehicles.
|
* Physics component for vehicles.
|
||||||
*/
|
*/
|
||||||
class HavokVehiclePhysicsComponent : public Component {
|
class HavokVehiclePhysicsComponent final : public Component {
|
||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::HAVOK_VEHICLE_PHYSICS;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ enum class eItemType : int32_t;
|
|||||||
* of different types, each type representing a different group of items, see `eInventoryType` for a list of
|
* of different types, each type representing a different group of items, see `eInventoryType` for a list of
|
||||||
* inventories.
|
* inventories.
|
||||||
*/
|
*/
|
||||||
class InventoryComponent : public Component
|
class InventoryComponent final : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::INVENTORY;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "Entity.h"
|
#include "Entity.h"
|
||||||
#include "eUgcModerationStatus.h"
|
#include "eUgcModerationStatus.h"
|
||||||
|
|
||||||
|
|
||||||
ItemComponent::ItemComponent(Entity* parent) : Component(parent) {
|
ItemComponent::ItemComponent(Entity* parent) : Component(parent) {
|
||||||
m_ParentEntity = parent;
|
m_ParentEntity = parent;
|
||||||
|
|
||||||
@ -19,13 +18,13 @@ ItemComponent::ItemComponent(Entity* parent) : Component(parent) {
|
|||||||
void ItemComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void ItemComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||||
|
|
||||||
outBitStream->Write(m_DirtyItemInfo || bIsInitialUpdate);
|
outBitStream->Write(m_DirtyItemInfo || bIsInitialUpdate);
|
||||||
if (m_DirtyItemInfo || bIsInitialUpdate){
|
if (m_DirtyItemInfo || bIsInitialUpdate) {
|
||||||
outBitStream->Write(m_UgId);
|
outBitStream->Write(m_UgId);
|
||||||
outBitStream->Write(m_UgModerationStatus);
|
outBitStream->Write(m_UgModerationStatus);
|
||||||
outBitStream->Write(m_UgDescription != u"");
|
outBitStream->Write(!m_UgDescription.empty());
|
||||||
if (m_UgDescription != u""){
|
if (!m_UgDescription.empty()){
|
||||||
outBitStream->Write<uint32_t>(m_UgDescription.length());
|
outBitStream->Write<uint32_t>(m_UgDescription.length());
|
||||||
for (uint16_t character : m_UgDescription) outBitStream->Write(character);
|
outBitStream->Write(reinterpret_cast<const char*>(m_UgDescription.c_str()), m_UgDescription.length() * sizeof(uint16_t));
|
||||||
}
|
}
|
||||||
m_DirtyItemInfo = false;
|
m_DirtyItemInfo = false;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
#ifndef __ITEMCOMPONENT__H__
|
||||||
|
#define __ITEMCOMPONENT__H__
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "RakNetTypes.h"
|
#include "RakNetTypes.h"
|
||||||
#include "NiPoint3.h"
|
#include "NiPoint3.h"
|
||||||
@ -9,7 +12,7 @@
|
|||||||
class Entity;
|
class Entity;
|
||||||
enum class eUgcModerationStatus : uint32_t;
|
enum class eUgcModerationStatus : uint32_t;
|
||||||
|
|
||||||
class ItemComponent : public Component {
|
class ItemComponent final : public Component {
|
||||||
public:
|
public:
|
||||||
static const eReplicaComponentType ComponentType = eReplicaComponentType::ITEM;
|
static const eReplicaComponentType ComponentType = eReplicaComponentType::ITEM;
|
||||||
|
|
||||||
@ -39,7 +42,7 @@ private:
|
|||||||
LWOOBJID m_UgId;
|
LWOOBJID m_UgId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Whether or not the description of this item is approved.
|
||||||
*/
|
*/
|
||||||
eUgcModerationStatus m_UgModerationStatus;
|
eUgcModerationStatus m_UgModerationStatus;
|
||||||
|
|
||||||
@ -48,3 +51,5 @@ private:
|
|||||||
*/
|
*/
|
||||||
std::u16string m_UgDescription;
|
std::u16string m_UgDescription;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif //!__ITEMCOMPONENT__H__
|
||||||
|
@ -3,42 +3,32 @@
|
|||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
|
|
||||||
LUPExhibitComponent::LUPExhibitComponent(Entity* parent) : Component(parent) {
|
LUPExhibitComponent::LUPExhibitComponent(Entity* parent) : Component(parent) {
|
||||||
m_Exhibits = { 11121, 11295, 11423, 11979 };
|
|
||||||
|
|
||||||
m_ExhibitIndex = 0;
|
m_ExhibitIndex = 0;
|
||||||
|
m_UpdateTimer = 0.0f;
|
||||||
m_Exhibit = m_Exhibits[m_ExhibitIndex];
|
m_Exhibit = m_Exhibits.front();
|
||||||
|
m_DirtyExhibitInfo = true;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
LUPExhibitComponent::~LUPExhibitComponent() {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LUPExhibitComponent::Update(float deltaTime) {
|
void LUPExhibitComponent::Update(float deltaTime) {
|
||||||
m_UpdateTimer += deltaTime;
|
m_UpdateTimer += deltaTime;
|
||||||
|
if (m_UpdateTimer < 20.0f) return;
|
||||||
|
|
||||||
if (m_UpdateTimer > 20.0f) {
|
|
||||||
NextExhibit();
|
NextExhibit();
|
||||||
|
|
||||||
m_UpdateTimer = 0.0f;
|
m_UpdateTimer = 0.0f;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LUPExhibitComponent::NextExhibit() {
|
void LUPExhibitComponent::NextExhibit() {
|
||||||
m_ExhibitIndex++;
|
m_ExhibitIndex++;
|
||||||
|
|
||||||
if (m_ExhibitIndex >= m_Exhibits.size()) {
|
// After 1361 years, this will skip exhibit 4 one time. I think modulo is ok here.
|
||||||
m_ExhibitIndex = 0;
|
m_Exhibit = m_Exhibits.at(m_ExhibitIndex % m_Exhibits.size());
|
||||||
}
|
|
||||||
|
|
||||||
m_Exhibit = m_Exhibits[m_ExhibitIndex];
|
|
||||||
|
|
||||||
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LUPExhibitComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) {
|
void LUPExhibitComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags) {
|
||||||
outBitStream->Write1(); // Dirty flag?
|
outBitStream->Write(bIsInitialUpdate || m_DirtyExhibitInfo);
|
||||||
|
if (bIsInitialUpdate || m_DirtyExhibitInfo) {
|
||||||
outBitStream->Write(m_Exhibit);
|
outBitStream->Write(m_Exhibit);
|
||||||
|
if (!bIsInitialUpdate) m_DirtyExhibitInfo = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,13 +8,12 @@
|
|||||||
* Component that handles the LOT that is shown in the LUP exhibit in the LUP world. Works by setting a timer and
|
* Component that handles the LOT that is shown in the LUP exhibit in the LUP world. Works by setting a timer and
|
||||||
* switching the LOTs around that we'd like to display.
|
* switching the LOTs around that we'd like to display.
|
||||||
*/
|
*/
|
||||||
class LUPExhibitComponent : public Component
|
class LUPExhibitComponent final : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::EXHIBIT;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::EXHIBIT;
|
||||||
|
|
||||||
LUPExhibitComponent(Entity* parent);
|
LUPExhibitComponent(Entity* parent);
|
||||||
~LUPExhibitComponent();
|
|
||||||
void Update(float deltaTime) override;
|
void Update(float deltaTime) override;
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, uint32_t& flags);
|
||||||
|
|
||||||
@ -36,10 +35,13 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The list of possible exhibits to show
|
* The list of possible exhibits to show
|
||||||
*/
|
*/
|
||||||
std::vector<LOT> m_Exhibits;
|
const std::vector<LOT> m_Exhibits = { 11121, 11295, 11423, 11979 };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current index in the exhibit list
|
* The current index in the exhibit list
|
||||||
*/
|
*/
|
||||||
size_t m_ExhibitIndex;
|
size_t m_ExhibitIndex;
|
||||||
|
|
||||||
|
// Whether or not to notify clients of a change in the visible exhibit
|
||||||
|
bool m_DirtyExhibitInfo;
|
||||||
};
|
};
|
||||||
|
@ -43,47 +43,48 @@ void LevelProgressionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void LevelProgressionComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||||
outBitStream->Write(bIsInitialUpdate || m_DirtyLevelInfo);
|
outBitStream->Write(bIsInitialUpdate || m_DirtyLevelInfo);
|
||||||
if (bIsInitialUpdate || m_DirtyLevelInfo) outBitStream->Write(m_Level);
|
if (bIsInitialUpdate || m_DirtyLevelInfo) {
|
||||||
m_DirtyLevelInfo = false;
|
outBitStream->Write(m_Level);
|
||||||
|
if (!bIsInitialUpdate) m_DirtyLevelInfo = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelProgressionComponent::HandleLevelUp() {
|
void LevelProgressionComponent::HandleLevelUp() {
|
||||||
auto* rewardsTable = CDClientManager::Instance().GetTable<CDRewardsTable>();
|
auto* rewardsTable = CDClientManager::Instance().GetTable<CDRewardsTable>();
|
||||||
|
|
||||||
const auto& rewards = rewardsTable->GetByLevelID(m_Level);
|
const auto& rewards = rewardsTable->GetByLevelID(m_Level);
|
||||||
bool rewardingItem = rewards.size() > 0;
|
if (rewards.empty()) return;
|
||||||
|
|
||||||
auto* inventoryComponent = m_ParentEntity->GetComponent<InventoryComponent>();
|
auto* inventoryComponent = m_ParentEntity->GetComponent<InventoryComponent>();
|
||||||
auto* controllablePhysicsComponent = m_ParentEntity->GetComponent<ControllablePhysicsComponent>();
|
auto* controllablePhysicsComponent = m_ParentEntity->GetComponent<ControllablePhysicsComponent>();
|
||||||
|
|
||||||
if (!inventoryComponent || !controllablePhysicsComponent) return;
|
if (!inventoryComponent || !controllablePhysicsComponent) return;
|
||||||
// Tell the client we beginning to send level rewards.
|
// Tell the client we beginning to send level rewards.
|
||||||
if (rewardingItem) GameMessages::NotifyLevelRewards(m_ParentEntity->GetObjectID(), m_ParentEntity->GetSystemAddress(), m_Level, rewardingItem);
|
GameMessages::NotifyLevelRewards(m_ParentEntity->GetObjectID(), m_ParentEntity->GetSystemAddress(), m_Level, true);
|
||||||
|
|
||||||
for (auto* reward : rewards) {
|
for (auto* reward : rewards) {
|
||||||
switch (reward->rewardType) {
|
switch (reward->rewardType) {
|
||||||
case 0:
|
case 0:
|
||||||
inventoryComponent->AddItem(reward->value, reward->count, eLootSourceType::LEVEL_REWARD);
|
inventoryComponent->AddItem(reward->value, reward->count, eLootSourceType::LEVEL_REWARD);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4: {
|
||||||
{
|
|
||||||
auto* items = inventoryComponent->GetInventory(eInventoryType::ITEMS);
|
auto* items = inventoryComponent->GetInventory(eInventoryType::ITEMS);
|
||||||
|
if (!items) continue;
|
||||||
items->SetSize(items->GetSize() + reward->value);
|
items->SetSize(items->GetSize() + reward->value);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 9:
|
case 9:
|
||||||
SetSpeedBase(static_cast<float>(reward->value));
|
SetSpeedBase(static_cast<float>(reward->value));
|
||||||
controllablePhysicsComponent->SetSpeedMultiplier(GetSpeedBase() / 500.0f);
|
controllablePhysicsComponent->SetSpeedMultiplier(GetSpeedBase() / 500.0f);
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
case 12:
|
case 12:
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Tell the client we have finished sending level rewards.
|
// Tell the client we have finished sending level rewards.
|
||||||
if (rewardingItem) GameMessages::NotifyLevelRewards(m_ParentEntity->GetObjectID(), m_ParentEntity->GetSystemAddress(), m_Level, !rewardingItem);
|
GameMessages::NotifyLevelRewards(m_ParentEntity->GetObjectID(), m_ParentEntity->GetSystemAddress(), m_Level, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LevelProgressionComponent::SetRetroactiveBaseSpeed() {
|
void LevelProgressionComponent::SetRetroactiveBaseSpeed() {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class LevelProgressionComponent : public Component {
|
class LevelProgressionComponent final : public Component {
|
||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::LEVEL_PROGRESSION;
|
||||||
|
|
||||||
@ -45,7 +45,11 @@ public:
|
|||||||
* Sets the level of the entity
|
* Sets the level of the entity
|
||||||
* @param level the level to set
|
* @param level the level to set
|
||||||
*/
|
*/
|
||||||
void SetLevel(uint32_t level) { m_Level = level; m_DirtyLevelInfo = true; }
|
void SetLevel(uint32_t level) {
|
||||||
|
if (m_Level == level) return;
|
||||||
|
m_Level = level;
|
||||||
|
m_DirtyLevelInfo = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current Speed Base of the entity
|
* Gets the current Speed Base of the entity
|
||||||
@ -98,7 +102,7 @@ private:
|
|||||||
float m_SpeedBase;
|
float m_SpeedBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Character format version
|
* The Character format version. Certain bug fixes increment this version number.
|
||||||
*/
|
*/
|
||||||
eCharacterVersion m_CharacterVersion;
|
eCharacterVersion m_CharacterVersion;
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Darkflame Universe
|
* Darkflame Universe
|
||||||
* Copyright 2019
|
* Copyright 2023
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "MissionComponent.h"
|
#include "MissionComponent.h"
|
||||||
@ -19,62 +18,40 @@
|
|||||||
#include "MissionPrerequisites.h"
|
#include "MissionPrerequisites.h"
|
||||||
#include "AchievementCacheKey.h"
|
#include "AchievementCacheKey.h"
|
||||||
#include "eMissionState.h"
|
#include "eMissionState.h"
|
||||||
|
#include "GeneralUtils.h"
|
||||||
// MARK: Mission Component
|
|
||||||
|
|
||||||
std::unordered_map<AchievementCacheKey, std::vector<uint32_t>> MissionComponent::m_AchievementCache = {};
|
std::unordered_map<AchievementCacheKey, std::vector<uint32_t>> MissionComponent::m_AchievementCache = {};
|
||||||
|
|
||||||
//! Initializer
|
|
||||||
MissionComponent::MissionComponent(Entity* parent) : Component(parent) {
|
MissionComponent::MissionComponent(Entity* parent) : Component(parent) {
|
||||||
m_LastUsedMissionOrderUID = dZoneManager::Instance()->GetUniqueMissionIdStartingValue();
|
m_LastUsedMissionOrderUID = dZoneManager::Instance()->GetUniqueMissionIdStartingValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Destructor
|
|
||||||
MissionComponent::~MissionComponent() {
|
MissionComponent::~MissionComponent() {
|
||||||
for (const auto& mission : m_Missions) {
|
for (const auto& [missionId, mission] : m_Missions) {
|
||||||
delete mission.second;
|
delete mission;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->m_Missions.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Mission* MissionComponent::GetMission(const uint32_t missionId) const {
|
Mission* MissionComponent::GetMission(const uint32_t missionId) const {
|
||||||
if (m_Missions.count(missionId) == 0) {
|
if (m_Missions.count(missionId) == 0) return nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto& index = m_Missions.find(missionId);
|
const auto& index = m_Missions.find(missionId);
|
||||||
|
|
||||||
if (index == m_Missions.end()) {
|
return index == m_Missions.end() ? nullptr : index->second;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return index->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
eMissionState MissionComponent::GetMissionState(const uint32_t missionId) const {
|
eMissionState MissionComponent::GetMissionState(const uint32_t missionId) const {
|
||||||
auto* mission = GetMission(missionId);
|
auto* mission = GetMission(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (!mission) return CanAccept(missionId) ? eMissionState::AVAILABLE : eMissionState::UNKNOWN;
|
||||||
return CanAccept(missionId) ? eMissionState::AVAILABLE : eMissionState::UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
return mission->GetMissionState();
|
return mission->GetMissionState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::unordered_map<uint32_t, Mission*>& MissionComponent::GetMissions() const {
|
|
||||||
return m_Missions;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool MissionComponent::CanAccept(const uint32_t missionId) const {
|
bool MissionComponent::CanAccept(const uint32_t missionId) const {
|
||||||
return MissionPrerequisites::CanAccept(missionId, m_Missions);
|
return MissionPrerequisites::CanAccept(missionId, m_Missions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MissionComponent::AcceptMission(const uint32_t missionId, const bool skipChecks) {
|
void MissionComponent::AcceptMission(const uint32_t missionId, const bool skipChecks) {
|
||||||
if (!skipChecks && !CanAccept(missionId)) {
|
if (!skipChecks && !CanAccept(missionId)) {
|
||||||
return;
|
return;
|
||||||
@ -83,7 +60,7 @@ void MissionComponent::AcceptMission(const uint32_t missionId, const bool skipCh
|
|||||||
// If this is a daily mission, it may already be "accepted"
|
// If this is a daily mission, it may already be "accepted"
|
||||||
auto* mission = this->GetMission(missionId);
|
auto* mission = this->GetMission(missionId);
|
||||||
|
|
||||||
if (mission != nullptr) {
|
if (mission) {
|
||||||
if (mission->GetClientInfo().repeatable) {
|
if (mission->GetClientInfo().repeatable) {
|
||||||
mission->Accept();
|
mission->Accept();
|
||||||
if (mission->IsMission()) mission->SetUniqueMissionOrderID(++m_LastUsedMissionOrderUID);
|
if (mission->IsMission()) mission->SetUniqueMissionOrderID(++m_LastUsedMissionOrderUID);
|
||||||
@ -100,54 +77,41 @@ void MissionComponent::AcceptMission(const uint32_t missionId, const bool skipCh
|
|||||||
|
|
||||||
this->m_Missions.insert_or_assign(missionId, mission);
|
this->m_Missions.insert_or_assign(missionId, mission);
|
||||||
|
|
||||||
if (missionId == 1728) {
|
|
||||||
//Needs to send a mail
|
//Needs to send a mail
|
||||||
|
if (missionId == 1728) Mail::HandleNotificationRequest(m_ParentEntity->GetSystemAddress(), m_ParentEntity->GetObjectID());
|
||||||
auto address = m_ParentEntity->GetSystemAddress();
|
|
||||||
|
|
||||||
Mail::HandleNotificationRequest(address, m_ParentEntity->GetObjectID());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MissionComponent::CompleteMission(const uint32_t missionId, const bool skipChecks, const bool yieldRewards) {
|
void MissionComponent::CompleteMission(const uint32_t missionId, const bool skipChecks, const bool yieldRewards) {
|
||||||
// Get the mission first
|
// Get the mission first
|
||||||
auto* mission = this->GetMission(missionId);
|
auto* mission = this->GetMission(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (!mission) {
|
||||||
AcceptMission(missionId, skipChecks);
|
AcceptMission(missionId, skipChecks);
|
||||||
|
|
||||||
mission = this->GetMission(missionId);
|
mission = this->GetMission(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (!mission) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//If this mission is not repeatable, and already completed, we stop here.
|
//If this mission is not repeatable, and already completed, we stop here.
|
||||||
if (mission->IsComplete() && !mission->IsRepeatable()) {
|
if (mission->IsComplete() && !mission->IsRepeatable()) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mission->Complete(yieldRewards);
|
mission->Complete(yieldRewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionComponent::RemoveMission(uint32_t missionId) {
|
void MissionComponent::RemoveMission(const uint32_t missionId) {
|
||||||
auto* mission = this->GetMission(missionId);
|
auto missionItr = m_Missions.find(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (missionItr == m_Missions.end()) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete mission;
|
delete missionItr->second;
|
||||||
|
|
||||||
m_Missions.erase(missionId);
|
m_Missions.erase(missionItr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID associate, const std::string& targets, int32_t count, bool ignoreAchievements) {
|
void MissionComponent::Progress(const eMissionTaskType type, const int32_t value, const LWOOBJID& associate, const std::string& targets, const int32_t count, const bool ignoreAchievements) {
|
||||||
for (const auto& pair : m_Missions) {
|
for (const auto& [missionId, mission] : m_Missions) {
|
||||||
auto* mission = pair.second;
|
if (!mission) continue;
|
||||||
|
|
||||||
if (mission->IsAchievement() && ignoreAchievements) continue;
|
if (mission->IsAchievement() && ignoreAchievements) continue;
|
||||||
|
|
||||||
if (mission->IsComplete()) continue;
|
if (mission->IsComplete()) continue;
|
||||||
@ -163,73 +127,57 @@ void MissionComponent::Progress(eMissionTaskType type, int32_t value, LWOOBJID a
|
|||||||
void MissionComponent::ForceProgress(const uint32_t missionId, const uint32_t taskId, const int32_t value, const bool acceptMission) {
|
void MissionComponent::ForceProgress(const uint32_t missionId, const uint32_t taskId, const int32_t value, const bool acceptMission) {
|
||||||
auto* mission = GetMission(missionId);
|
auto* mission = GetMission(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (!mission) {
|
||||||
if (!acceptMission) {
|
if (!acceptMission) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AcceptMission(missionId);
|
AcceptMission(missionId);
|
||||||
|
|
||||||
mission = GetMission(missionId);
|
mission = GetMission(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (!mission) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* element : mission->GetTasks()) {
|
std::for_each(mission->GetTasks().begin(), mission->GetTasks().end(), [value, taskId](MissionTask* element) {
|
||||||
if (element->GetClientInfo().uid != taskId) continue;
|
if (element->GetClientInfo().uid != taskId) return;
|
||||||
|
|
||||||
element->AddProgress(value);
|
element->AddProgress(value);
|
||||||
}
|
});
|
||||||
|
|
||||||
if (!mission->IsComplete()) {
|
if (!mission->IsComplete()) mission->CheckCompletion();
|
||||||
mission->CheckCompletion();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionComponent::ForceProgressTaskType(const uint32_t missionId, const uint32_t taskType, const int32_t value, const bool acceptMission) {
|
void MissionComponent::ForceProgressTaskType(const uint32_t missionId, const uint32_t taskType, const int32_t value, const bool acceptMission) {
|
||||||
auto* mission = GetMission(missionId);
|
auto* mission = GetMission(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (!mission) {
|
||||||
if (!acceptMission) {
|
if (!acceptMission) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CDMissions missionInfo;
|
CDMissions missionInfo;
|
||||||
|
|
||||||
if (!GetMissionInfo(missionId, missionInfo)) {
|
if (!GetMissionInfo(missionId, missionInfo)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (missionInfo.isMission) {
|
if (missionInfo.isMission) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AcceptMission(missionId);
|
AcceptMission(missionId);
|
||||||
|
|
||||||
mission = GetMission(missionId);
|
mission = GetMission(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (!mission) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* element : mission->GetTasks()) {
|
std::for_each(mission->GetTasks().begin(), mission->GetTasks().end(), [value, taskType](MissionTask* element) {
|
||||||
if (element->GetType() != static_cast<eMissionTaskType>(taskType)) continue;
|
if (element->GetType() != static_cast<eMissionTaskType>(taskType)) return;
|
||||||
|
|
||||||
element->AddProgress(value);
|
element->AddProgress(value);
|
||||||
}
|
});
|
||||||
|
|
||||||
if (!mission->IsComplete()) {
|
if (!mission->IsComplete()) mission->CheckCompletion();
|
||||||
mission->CheckCompletion();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionComponent::ForceProgressValue(uint32_t missionId, uint32_t taskType, int32_t value, bool acceptMission) {
|
void MissionComponent::ForceProgressValue(const uint32_t missionId, const uint32_t taskType, const int32_t value, const bool acceptMission) {
|
||||||
auto* mission = GetMission(missionId);
|
auto* mission = GetMission(missionId);
|
||||||
|
|
||||||
if (mission == nullptr) {
|
if (!mission) {
|
||||||
if (!acceptMission) {
|
if (!acceptMission) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -264,11 +212,11 @@ void MissionComponent::ForceProgressValue(uint32_t missionId, uint32_t taskType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MissionComponent::GetMissionInfo(uint32_t missionId, CDMissions& result) {
|
bool MissionComponent::GetMissionInfo(const uint32_t missionId, CDMissions& result) const {
|
||||||
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
|
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
|
||||||
|
|
||||||
const auto missions = missionsTable->Query([=](const CDMissions& entry) {
|
const auto missions = missionsTable->Query([=](const CDMissions& entry) {
|
||||||
return entry.id == static_cast<int>(missionId);
|
return entry.id == static_cast<uint32_t>(missionId);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (missions.empty()) {
|
if (missions.empty()) {
|
||||||
@ -280,10 +228,7 @@ bool MissionComponent::GetMissionInfo(uint32_t missionId, CDMissions& result) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MISSION_NEW_METHOD
|
bool MissionComponent::LookForAchievements(const eMissionTaskType type, const int32_t value, const bool progress, const LWOOBJID& associate, const std::string& targets, const int32_t count) {
|
||||||
|
|
||||||
bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value, bool progress, LWOOBJID associate, const std::string& targets, int32_t count) {
|
|
||||||
#ifdef MISSION_NEW_METHOD
|
|
||||||
// Query for achievments, using the cache
|
// Query for achievments, using the cache
|
||||||
const auto& result = QueryAchievements(type, value, targets);
|
const auto& result = QueryAchievements(type, value, targets);
|
||||||
|
|
||||||
@ -291,9 +236,7 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
|
|||||||
|
|
||||||
for (const uint32_t missionID : result) {
|
for (const uint32_t missionID : result) {
|
||||||
// Check if we already have this achievement
|
// Check if we already have this achievement
|
||||||
if (GetMission(missionID) != nullptr) {
|
if (GetMission(missionID)) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we can accept this achievement
|
// Check if we can accept this achievement
|
||||||
if (!MissionPrerequisites::CanAccept(missionID, m_Missions)) {
|
if (!MissionPrerequisites::CanAccept(missionID, m_Missions)) {
|
||||||
@ -311,87 +254,15 @@ bool MissionComponent::LookForAchievements(eMissionTaskType type, int32_t value,
|
|||||||
|
|
||||||
any = true;
|
any = true;
|
||||||
|
|
||||||
if (progress) {
|
if (!progress) continue;
|
||||||
// Progress mission to bring it up to speed
|
// Progress mission to bring it up to speed
|
||||||
instance->Progress(type, value, associate, targets, count);
|
instance->Progress(type, value, associate, targets, count);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return any;
|
return any;
|
||||||
#else
|
|
||||||
auto* missionTasksTable = CDClientManager::Instance().GetTable<CDMissionTasksTable>();
|
|
||||||
auto* missionsTable = CDClientManager::Instance().GetTable<CDMissionsTable>();
|
|
||||||
|
|
||||||
auto tasks = missionTasksTable->Query([=](const CDMissionTasks& entry) {
|
|
||||||
return entry.taskType == static_cast<unsigned>(type);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto any = false;
|
|
||||||
|
|
||||||
for (const auto& task : tasks) {
|
|
||||||
if (GetMission(task.id) != nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto missionEntries = missionsTable->Query([=](const CDMissions& entry) {
|
|
||||||
return entry.id == static_cast<int>(task.id) && !entry.isMission;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (missionEntries.empty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto mission = missionEntries[0];
|
|
||||||
|
|
||||||
if (mission.isMission || !MissionPrerequisites::CanAccept(mission.id, m_Missions)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (task.target != value && task.targetGroup != targets) {
|
|
||||||
auto stream = std::istringstream(task.targetGroup);
|
|
||||||
std::string token;
|
|
||||||
|
|
||||||
auto found = false;
|
|
||||||
|
|
||||||
while (std::getline(stream, token, ',')) {
|
|
||||||
try {
|
|
||||||
const auto target = std::stoul(token);
|
|
||||||
|
|
||||||
found = target == value;
|
|
||||||
|
|
||||||
if (found) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (std::invalid_argument& exception) {
|
|
||||||
Game::logger->Log("MissionComponent", "Failed to parse target (%s): (%s)!", token.c_str(), exception.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* instance = new Mission(this, mission.id);
|
|
||||||
|
|
||||||
m_Missions.insert_or_assign(mission.id, instance);
|
|
||||||
|
|
||||||
if (instance->IsMission()) instance->SetUniqueMissionOrderID(++m_LastUsedMissionOrderUID);
|
|
||||||
|
|
||||||
instance->Accept();
|
|
||||||
|
|
||||||
any = true;
|
|
||||||
|
|
||||||
if (progress) {
|
|
||||||
instance->Progress(type, value, associate, targets, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return any;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<uint32_t>& MissionComponent::QueryAchievements(eMissionTaskType type, int32_t value, const std::string targets) {
|
const std::vector<uint32_t>& MissionComponent::QueryAchievements(const eMissionTaskType type, const int32_t value, const std::string& targets) {
|
||||||
// Create a hash which represent this query for achievements
|
// Create a hash which represent this query for achievements
|
||||||
AchievementCacheKey toFind;
|
AchievementCacheKey toFind;
|
||||||
toFind.SetType(type);
|
toFind.SetType(type);
|
||||||
@ -420,95 +291,68 @@ const std::vector<uint32_t>& MissionComponent::QueryAchievements(eMissionTaskTyp
|
|||||||
// Seek the assosicated mission
|
// Seek the assosicated mission
|
||||||
auto foundMission = false;
|
auto foundMission = false;
|
||||||
|
|
||||||
const auto& mission = missionsTable->GetByMissionID(task.id, foundMission);
|
const auto& cdMission = missionsTable->GetByMissionID(task.id, foundMission);
|
||||||
|
|
||||||
if (!foundMission || mission.isMission) {
|
if (!foundMission || cdMission.isMission) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare the easy values
|
// Compare the easy values
|
||||||
if (task.target == value || task.targetGroup == targets) {
|
if (task.target == value || task.targetGroup == targets) {
|
||||||
result.push_back(mission.id);
|
result.push_back(cdMission.id);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare the target group, array separated by ','
|
// Compare the target group, array separated by ','
|
||||||
auto stream = std::istringstream(task.targetGroup);
|
for (const auto& possibleMissionStr : GeneralUtils::SplitString(task.targetGroup, ',')) {
|
||||||
std::string token;
|
uint32_t possibleMission;
|
||||||
|
if (GeneralUtils::TryParse(possibleMissionStr, possibleMission) && possibleMission == value) {
|
||||||
|
result.push_back(cdMission.id);
|
||||||
|
|
||||||
while (std::getline(stream, token, ',')) {
|
break;
|
||||||
try {
|
|
||||||
if (std::stoi(token) == value) {
|
|
||||||
result.push_back(mission.id);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} catch (std::invalid_argument& exception) {
|
|
||||||
// Ignored
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Insert into cache
|
// Insert into cache and return the inserted value.
|
||||||
m_AchievementCache.insert_or_assign(toFind, result);
|
return m_AchievementCache.insert_or_assign(toFind, result).first->second;
|
||||||
return m_AchievementCache.find(toFind)->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MissionComponent::RequiresItem(const LOT lot) {
|
bool MissionComponent::RequiresItem(const LOT lot) {
|
||||||
auto query = CDClientDatabase::CreatePreppedStmt(
|
auto query = CDClientDatabase::CreatePreppedStmt("SELECT type FROM Objects WHERE id = ?;");
|
||||||
"SELECT type FROM Objects WHERE id = ?;");
|
query.bind(1, static_cast<int>(lot));
|
||||||
query.bind(1, (int)lot);
|
|
||||||
|
|
||||||
auto result = query.execQuery();
|
auto result = query.execQuery();
|
||||||
|
|
||||||
if (result.eof()) {
|
if (result.eof()) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result.fieldIsNull(0)) {
|
if (!result.fieldIsNull(0)) {
|
||||||
const auto type = std::string(result.getStringField(0));
|
const auto type = std::string(result.getStringField(0));
|
||||||
|
|
||||||
result.finalize();
|
if (type == "Powerup") return true;
|
||||||
|
|
||||||
if (type == "Powerup") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result.finalize();
|
for (const auto& [missionId, mission] : m_Missions) {
|
||||||
|
if (mission->IsComplete()) continue;
|
||||||
for (const auto& pair : m_Missions) {
|
|
||||||
auto* mission = pair.second;
|
|
||||||
|
|
||||||
if (mission->IsComplete()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* task : mission->GetTasks()) {
|
for (auto* task : mission->GetTasks()) {
|
||||||
if (task->IsComplete() || task->GetType() != eMissionTaskType::GATHER) {
|
if (task->IsComplete() || task->GetType() != eMissionTaskType::GATHER) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!task->InAllTargets(lot)) {
|
if (!task->InAllTargets(lot)) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return LookForAchievements(eMissionTaskType::GATHER, lot, false);
|
||||||
const auto required = LookForAchievements(eMissionTaskType::GATHER, lot, false);
|
|
||||||
|
|
||||||
return required;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||||
if (doc == nullptr) return;
|
if (!doc) return;
|
||||||
|
|
||||||
auto* mis = doc->FirstChildElement("obj")->FirstChildElement("mis");
|
auto* mis = doc->FirstChildElement("obj")->FirstChildElement("mis");
|
||||||
|
|
||||||
if (mis == nullptr) return;
|
if (!mis) return;
|
||||||
|
|
||||||
auto* cur = mis->FirstChildElement("cur");
|
auto* cur = mis->FirstChildElement("cur");
|
||||||
auto* done = mis->FirstChildElement("done");
|
auto* done = mis->FirstChildElement("done");
|
||||||
@ -516,7 +360,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
auto* doneM = done->FirstChildElement();
|
auto* doneM = done->FirstChildElement();
|
||||||
|
|
||||||
while (doneM) {
|
while (doneM) {
|
||||||
int missionId;
|
uint32_t missionId;
|
||||||
|
|
||||||
doneM->QueryAttribute("id", &missionId);
|
doneM->QueryAttribute("id", &missionId);
|
||||||
|
|
||||||
@ -533,7 +377,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
uint32_t missionOrder{};
|
uint32_t missionOrder{};
|
||||||
while (currentM) {
|
while (currentM) {
|
||||||
int missionId;
|
uint32_t missionId;
|
||||||
|
|
||||||
currentM->QueryAttribute("id", &missionId);
|
currentM->QueryAttribute("id", &missionId);
|
||||||
|
|
||||||
@ -543,7 +387,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) {
|
if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) {
|
||||||
mission->SetUniqueMissionOrderID(missionOrder);
|
mission->SetUniqueMissionOrderID(missionOrder);
|
||||||
if (missionOrder > m_LastUsedMissionOrderUID) m_LastUsedMissionOrderUID = missionOrder;
|
m_LastUsedMissionOrderUID = std::max(missionOrder, m_LastUsedMissionOrderUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentM = currentM->NextSiblingElement();
|
currentM = currentM->NextSiblingElement();
|
||||||
@ -554,7 +398,7 @@ void MissionComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
|
|
||||||
void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
||||||
if (doc == nullptr) return;
|
if (!doc) return;
|
||||||
|
|
||||||
auto shouldInsertMis = false;
|
auto shouldInsertMis = false;
|
||||||
|
|
||||||
@ -562,7 +406,7 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
|
|
||||||
auto* mis = obj->FirstChildElement("mis");
|
auto* mis = obj->FirstChildElement("mis");
|
||||||
|
|
||||||
if (mis == nullptr) {
|
if (!mis) {
|
||||||
mis = doc->NewElement("mis");
|
mis = doc->NewElement("mis");
|
||||||
|
|
||||||
shouldInsertMis = true;
|
shouldInsertMis = true;
|
||||||
@ -573,50 +417,33 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
|||||||
auto* done = doc->NewElement("done");
|
auto* done = doc->NewElement("done");
|
||||||
auto* cur = doc->NewElement("cur");
|
auto* cur = doc->NewElement("cur");
|
||||||
|
|
||||||
for (const auto& pair : m_Missions) {
|
for (const auto& [missionId, mission] : m_Missions) {
|
||||||
auto* mission = pair.second;
|
if (!mission) continue;
|
||||||
|
|
||||||
if (mission) {
|
|
||||||
const auto complete = mission->IsComplete();
|
const auto complete = mission->IsComplete();
|
||||||
|
|
||||||
auto* m = doc->NewElement("m");
|
auto* missionElement = doc->NewElement("m");
|
||||||
|
|
||||||
if (complete) {
|
if (!complete && mission->IsMission()) missionElement->SetAttribute("o", mission->GetUniqueMissionOrderID());
|
||||||
mission->UpdateXml(m);
|
|
||||||
|
|
||||||
done->LinkEndChild(m);
|
mission->UpdateXml(missionElement);
|
||||||
|
|
||||||
continue;
|
cur->LinkEndChild(missionElement);
|
||||||
}
|
|
||||||
if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID());
|
|
||||||
|
|
||||||
mission->UpdateXml(m);
|
|
||||||
|
|
||||||
cur->LinkEndChild(m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mis->InsertFirstChild(done);
|
mis->InsertFirstChild(done);
|
||||||
mis->InsertEndChild(cur);
|
mis->InsertEndChild(cur);
|
||||||
|
|
||||||
if (shouldInsertMis) {
|
if (shouldInsertMis) obj->LinkEndChild(mis);
|
||||||
obj->LinkEndChild(mis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionComponent::AddCollectible(int32_t collectibleID) {
|
void MissionComponent::AddCollectible(const int32_t collectibleID) {
|
||||||
// Check if this collectible is already in the list
|
if (!HasCollectible(collectibleID)) m_Collectibles.push_back(collectibleID);
|
||||||
if (HasCollectible(collectibleID)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_Collectibles.push_back(collectibleID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MissionComponent::HasCollectible(int32_t collectibleID) {
|
bool MissionComponent::HasCollectible(const int32_t collectibleID) const {
|
||||||
return std::find(m_Collectibles.begin(), m_Collectibles.end(), collectibleID) != m_Collectibles.end();
|
return std::find(m_Collectibles.begin(), m_Collectibles.end(), collectibleID) != m_Collectibles.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MissionComponent::HasMission(uint32_t missionId) {
|
bool MissionComponent::HasMission(const uint32_t missionId) const {
|
||||||
return GetMission(missionId) != nullptr;
|
return GetMission(missionId) != nullptr;
|
||||||
}
|
}
|
||||||
|
@ -39,35 +39,35 @@ public:
|
|||||||
* Returns all the missions for this entity, mapped by mission ID
|
* Returns all the missions for this entity, mapped by mission ID
|
||||||
* @return the missions for this entity, mapped by mission ID
|
* @return the missions for this entity, mapped by mission ID
|
||||||
*/
|
*/
|
||||||
const std::unordered_map<uint32_t, Mission*>& GetMissions() const;
|
const std::unordered_map<uint32_t, Mission*>& GetMissions() const { return m_Missions; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the mission for the given mission ID, if it exists
|
* Returns the mission for the given mission ID, if it exists
|
||||||
* @param missionId the id of the mission to get
|
* @param missionId the id of the mission to get
|
||||||
* @return the mission for the given mission ID
|
* @return the mission for the given mission ID
|
||||||
*/
|
*/
|
||||||
Mission* GetMission(uint32_t missionId) const;
|
Mission* GetMission(const uint32_t missionId) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current state of the entities progression for the mission of the specified ID
|
* Returns the current state of the entities progression for the mission of the specified ID
|
||||||
* @param missionId the ID of the mission to get the mission state for
|
* @param missionId the ID of the mission to get the mission state for
|
||||||
* @return the mission state of the mission specified by the ID
|
* @return the mission state of the mission specified by the ID
|
||||||
*/
|
*/
|
||||||
eMissionState GetMissionState(uint32_t missionId) const;
|
eMissionState GetMissionState(const uint32_t missionId) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the entity has all the requirements for accepting the mission specified by the ID.
|
* Checks if the entity has all the requirements for accepting the mission specified by the ID.
|
||||||
* @param missionId the mission ID to check for if the character may accept it
|
* @param missionId the mission ID to check for if the character may accept it
|
||||||
* @return whether this entity can accept the mission represented by the given mission ID
|
* @return whether this entity can accept the mission represented by the given mission ID
|
||||||
*/
|
*/
|
||||||
bool CanAccept(uint32_t missionId) const;
|
bool CanAccept(const uint32_t missionId) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Accepts the mission specified by the ID, if the entity may accept it. Also stores it in the mission inventory.
|
* Accepts the mission specified by the ID, if the entity may accept it. Also stores it in the mission inventory.
|
||||||
* @param missionId the ID of the mission to accept
|
* @param missionId the ID of the mission to accept
|
||||||
* @param skipChecks skips the checks for the mission prerequisites
|
* @param skipChecks skips the checks for the mission prerequisites
|
||||||
*/
|
*/
|
||||||
void AcceptMission(uint32_t missionId, bool skipChecks = false);
|
void AcceptMission(const uint32_t missionId, const bool skipChecks = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completes the mission specified by the given ID, if the entity has fulfilled all progress requirements.
|
* Completes the mission specified by the given ID, if the entity has fulfilled all progress requirements.
|
||||||
@ -75,13 +75,13 @@ public:
|
|||||||
* @param skipChecks skips the checks for having completed all of the mission tasks
|
* @param skipChecks skips the checks for having completed all of the mission tasks
|
||||||
* @param yieldRewards whether to yield mission rewards, currently unused
|
* @param yieldRewards whether to yield mission rewards, currently unused
|
||||||
*/
|
*/
|
||||||
void CompleteMission(uint32_t missionId, bool skipChecks = false, bool yieldRewards = true);
|
void CompleteMission(const uint32_t missionId, const bool skipChecks = false, const bool yieldRewards = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the mission from the entities' mission chain. Not used for normal gameplay but useful for debugging.
|
* Removes the mission from the entities' mission chain. Not used for normal gameplay but useful for debugging.
|
||||||
* @param missionId the ID of the mission to remove
|
* @param missionId the ID of the mission to remove
|
||||||
*/
|
*/
|
||||||
void RemoveMission(uint32_t missionId);
|
void RemoveMission(const uint32_t missionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to progress mission tasks for a given type using parameters to progress. Note that this function is
|
* Attempts to progress mission tasks for a given type using parameters to progress. Note that this function is
|
||||||
@ -94,7 +94,7 @@ public:
|
|||||||
* @param count the number to progress by, for example the number of items
|
* @param count the number to progress by, for example the number of items
|
||||||
* @param ignoreAchievements do not progress achievements
|
* @param ignoreAchievements do not progress achievements
|
||||||
*/
|
*/
|
||||||
void Progress(eMissionTaskType type, int32_t value, LWOOBJID associate = 0, const std::string& targets = "", int32_t count = 1, bool ignoreAchievements = false);
|
void Progress(const eMissionTaskType type, const int32_t value, const LWOOBJID& associate = 0, const std::string& targets = "", const int32_t count = 1, const bool ignoreAchievements = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces progression for a mission and task, ignoring checks
|
* Forces progression for a mission and task, ignoring checks
|
||||||
@ -103,7 +103,7 @@ public:
|
|||||||
* @param value the value to progress with
|
* @param value the value to progress with
|
||||||
* @param acceptMission accept the mission if it was not already accepted
|
* @param acceptMission accept the mission if it was not already accepted
|
||||||
*/
|
*/
|
||||||
void ForceProgress(uint32_t missionId, uint32_t taskId, int32_t value, bool acceptMission = true);
|
void ForceProgress(const uint32_t missionId, const uint32_t taskId, const int32_t value, const bool acceptMission = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forces progress for all tasks of a certain type that belong to the same mission
|
* Forces progress for all tasks of a certain type that belong to the same mission
|
||||||
@ -112,7 +112,7 @@ public:
|
|||||||
* @param value the value to progress with
|
* @param value the value to progress with
|
||||||
* @param acceptMission accept the mission if it wasn't already
|
* @param acceptMission accept the mission if it wasn't already
|
||||||
*/
|
*/
|
||||||
void ForceProgressTaskType(uint32_t missionId, uint32_t taskType, int32_t value, bool acceptMission = true);
|
void ForceProgressTaskType(const uint32_t missionId, const uint32_t taskType, const int32_t value, const bool acceptMission = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force progresses by checking the value and progressing by 1
|
* Force progresses by checking the value and progressing by 1
|
||||||
@ -121,7 +121,7 @@ public:
|
|||||||
* @param value the value to check the mission values before progressing
|
* @param value the value to check the mission values before progressing
|
||||||
* @param acceptMission accept the mission if it wasn't already
|
* @param acceptMission accept the mission if it wasn't already
|
||||||
*/
|
*/
|
||||||
void ForceProgressValue(uint32_t missionId, uint32_t taskType, int32_t value, bool acceptMission = true);
|
void ForceProgressValue(const uint32_t missionId, const uint32_t taskType, const int32_t value, const bool acceptMission = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns client database mission information for a mission
|
* Returns client database mission information for a mission
|
||||||
@ -129,7 +129,7 @@ public:
|
|||||||
* @param result the result to store the information in
|
* @param result the result to store the information in
|
||||||
* @return true if the information was succesfully retrieved, false otherwise
|
* @return true if the information was succesfully retrieved, false otherwise
|
||||||
*/
|
*/
|
||||||
bool GetMissionInfo(uint32_t missionId, CDMissions& result);
|
bool GetMissionInfo(const uint32_t missionId, CDMissions& result) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if there's any achievements we might be able to accept for the given parameters
|
* Checks if there's any achievements we might be able to accept for the given parameters
|
||||||
@ -141,34 +141,34 @@ public:
|
|||||||
* @param count the number of values to progress by (differs by task type)
|
* @param count the number of values to progress by (differs by task type)
|
||||||
* @return true if a achievement was accepted, false otherwise
|
* @return true if a achievement was accepted, false otherwise
|
||||||
*/
|
*/
|
||||||
bool LookForAchievements(eMissionTaskType type, int32_t value, bool progress = true, LWOOBJID associate = LWOOBJID_EMPTY, const std::string& targets = "", int32_t count = 1);
|
bool LookForAchievements(const eMissionTaskType type, const int32_t value, const bool progress = true, const LWOOBJID& associate = LWOOBJID_EMPTY, const std::string& targets = "", const int32_t count = 1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if there's a mission active that requires the collection of the specified LOT
|
* Checks if there's a mission active that requires the collection of the specified LOT
|
||||||
* @param lot the LOT to check for
|
* @param lot the LOT to check for
|
||||||
* @return if there's a mission active that requires the collection of the specified LOT
|
* @return if there's a mission active that requires the collection of the specified LOT
|
||||||
*/
|
*/
|
||||||
bool RequiresItem(LOT lot);
|
bool RequiresItem(const LOT lot);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collects a collectable for the entity, unrendering it for the entity
|
* Collects a collectable for the entity, unrendering it for the entity
|
||||||
* @param collectibleID the ID of the collectable to add
|
* @param collectibleID the ID of the collectable to add
|
||||||
*/
|
*/
|
||||||
void AddCollectible(int32_t collectibleID);
|
void AddCollectible(const int32_t collectibleID);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the entity already has a collectible of the specified ID
|
* Checks if the entity already has a collectible of the specified ID
|
||||||
* @param collectibleID the ID of the collectible to check
|
* @param collectibleID the ID of the collectible to check
|
||||||
* @return if the entity already has a collectible of the specified ID
|
* @return if the entity already has a collectible of the specified ID
|
||||||
*/
|
*/
|
||||||
bool HasCollectible(int32_t collectibleID);
|
bool HasCollectible(const int32_t collectibleID) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the entity has a certain mission in its inventory
|
* Checks if the entity has a certain mission in its inventory
|
||||||
* @param missionId the ID of the mission to check
|
* @param missionId the ID of the mission to check
|
||||||
* @return if the entity has a certain mission in its inventory
|
* @return if the entity has a certain mission in its inventory
|
||||||
*/
|
*/
|
||||||
bool HasMission(uint32_t missionId);
|
bool HasMission(const uint32_t missionId) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@ -189,7 +189,7 @@ private:
|
|||||||
* @param targets optional targets to progress with
|
* @param targets optional targets to progress with
|
||||||
* @return list of mission IDs (achievements) that can be progressed for the given parameters
|
* @return list of mission IDs (achievements) that can be progressed for the given parameters
|
||||||
*/
|
*/
|
||||||
static const std::vector<uint32_t>& QueryAchievements(eMissionTaskType type, int32_t value, const std::string targets);
|
static const std::vector<uint32_t>& QueryAchievements(const eMissionTaskType type, const int32_t value, const std::string& targets);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* As achievements can be hard to query, we here store a list of all the mission IDs that can be unlocked for a
|
* As achievements can be hard to query, we here store a list of all the mission IDs that can be unlocked for a
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Darkflame Universe
|
* Darkflame Universe
|
||||||
* Copyright 2019
|
* Copyright 2023
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -18,59 +18,24 @@
|
|||||||
|
|
||||||
#include "CDComponentsRegistryTable.h"
|
#include "CDComponentsRegistryTable.h"
|
||||||
|
|
||||||
OfferedMission::OfferedMission(const uint32_t missionId, const bool offersMission, const bool acceptsMission) {
|
MissionOfferComponent::MissionOfferComponent(Entity* parent, const int32_t componentId) : Component(parent) {
|
||||||
this->missionId = missionId;
|
m_ComponentId = componentId;
|
||||||
this->offersMission = offersMission;
|
|
||||||
this->acceptsMission = acceptsMission;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MissionOfferComponent::LoadTemplateData() {
|
||||||
uint32_t OfferedMission::GetMissionId() const {
|
if (m_ComponentId == -1) return;
|
||||||
return this->missionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OfferedMission::GetOfferMission() const {
|
|
||||||
return this->offersMission;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OfferedMission::GetAcceptMission() const {
|
|
||||||
return this->acceptsMission;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------ MissionOfferComponent below ------------------------
|
|
||||||
|
|
||||||
MissionOfferComponent::MissionOfferComponent(Entity* parent, const LOT parentLot) : Component(parent) {
|
|
||||||
auto* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
|
||||||
|
|
||||||
auto value = compRegistryTable->GetByIDAndType(parentLot, eReplicaComponentType::MISSION_OFFER, -1);
|
|
||||||
|
|
||||||
if (value != -1) {
|
|
||||||
const uint32_t componentId = value;
|
|
||||||
|
|
||||||
// Now lookup the missions in the MissionNPCComponent table
|
// Now lookup the missions in the MissionNPCComponent table
|
||||||
auto* missionNpcComponentTable = CDClientManager::Instance().GetTable<CDMissionNPCComponentTable>();
|
auto* missionNpcComponentTable = CDClientManager::Instance().GetTable<CDMissionNPCComponentTable>();
|
||||||
|
|
||||||
auto missions = missionNpcComponentTable->Query([=](const CDMissionNPCComponent& entry) {
|
auto missions = missionNpcComponentTable->Query([=](const CDMissionNPCComponent& entry) {
|
||||||
return entry.id == static_cast<unsigned>(componentId);
|
return entry.id == static_cast<int32_t>(m_ComponentId);
|
||||||
});
|
});
|
||||||
|
|
||||||
for (auto& mission : missions) {
|
for (const auto& mission : missions) {
|
||||||
auto* offeredMission = new OfferedMission(mission.missionID, mission.offersMission, mission.acceptsMission);
|
this->offeredMissions.emplace_back(
|
||||||
this->offeredMissions.push_back(offeredMission);
|
std::make_unique<OfferedMission>(mission.missionID, mission.offersMission, mission.acceptsMission)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MissionOfferComponent::~MissionOfferComponent() {
|
|
||||||
for (auto* mission : this->offeredMissions) {
|
|
||||||
if (mission) {
|
|
||||||
delete mission;
|
|
||||||
mission = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
offeredMissions.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MissionOfferComponent::OnUse(Entity* originator) {
|
void MissionOfferComponent::OnUse(Entity* originator) {
|
||||||
@ -88,28 +53,29 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi
|
|||||||
|
|
||||||
std::vector<uint32_t> offered{};
|
std::vector<uint32_t> offered{};
|
||||||
|
|
||||||
CDMissions info{};
|
CDMissions missionInfo{};
|
||||||
|
|
||||||
if (specifiedMissionId > 0 && !Mission::IsValidMission(specifiedMissionId, info)) {
|
if (specifiedMissionId > 0 && !Mission::IsValidMission(specifiedMissionId, missionInfo)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* offeredMission : this->offeredMissions) {
|
for (const auto& offeredMission : offeredMissions) {
|
||||||
if (specifiedMissionId > 0) {
|
if (specifiedMissionId > 0 && (offeredMission->GetMissionId() != specifiedMissionId && !missionInfo.isRandom)) {
|
||||||
if (offeredMission->GetMissionId() != specifiedMissionId && !info.isRandom) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// First, check if we already have the mission
|
// First, check if we already have the mission
|
||||||
const auto missionId = offeredMission->GetMissionId();
|
const auto missionId = offeredMission->GetMissionId();
|
||||||
|
|
||||||
auto* mission = missionComponent->GetMission(missionId);
|
auto* mission = missionComponent->GetMission(missionId);
|
||||||
|
|
||||||
if (mission != nullptr) {
|
if (mission) {
|
||||||
if (specifiedMissionId <= 0) {
|
if (specifiedMissionId <= 0) {
|
||||||
// Handles the odd case where the offer object should not display the mission again
|
// Handles the odd case where the offer object should not display the mission again
|
||||||
if (!mission->IsComplete() && mission->GetClientInfo().offer_objectID == m_ParentEntity->GetLOT() && mission->GetClientInfo().target_objectID != m_ParentEntity->GetLOT() && mission->IsFetchMission()) {
|
if (!mission->IsComplete() &&
|
||||||
|
mission->GetClientInfo().offer_objectID == m_ParentEntity->GetLOT() &&
|
||||||
|
mission->GetClientInfo().target_objectID != m_ParentEntity->GetLOT() &&
|
||||||
|
mission->IsFetchMission()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,50 +93,30 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi
|
|||||||
const auto canAccept = MissionPrerequisites::CanAccept(missionId, missionComponent->GetMissions());
|
const auto canAccept = MissionPrerequisites::CanAccept(missionId, missionComponent->GetMissions());
|
||||||
|
|
||||||
// Mission has not yet been accepted - check the prereqs
|
// Mission has not yet been accepted - check the prereqs
|
||||||
if (!canAccept)
|
if (!canAccept || !Mission::IsValidMission(missionId, missionInfo)) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!Mission::IsValidMission(missionId, info)) {
|
// This means the mission is part of a random pool of missions.
|
||||||
continue;
|
if (missionInfo.isRandom && missionInfo.randomPool.empty()) continue;
|
||||||
}
|
|
||||||
|
|
||||||
const auto& randomPool = info.randomPool;
|
if (missionInfo.isRandom && !missionInfo.randomPool.empty()) {
|
||||||
const auto isRandom = info.isRandom;
|
auto randomMissionPoolStr = GeneralUtils::SplitString(missionInfo.randomPool, ',');
|
||||||
|
|
||||||
if (isRandom && randomPool.empty()) // This means the mission is part of a random pool of missions.
|
std::vector<uint32_t> randomMissions;
|
||||||
{
|
for (const auto& randomMissionStr : randomMissionPoolStr) {
|
||||||
continue;
|
uint32_t randomMission;
|
||||||
}
|
if (GeneralUtils::TryParse(randomMissionStr, randomMission)) randomMissions.push_back(randomMission);
|
||||||
|
|
||||||
if (isRandom && !randomPool.empty()) {
|
|
||||||
std::istringstream stream(randomPool);
|
|
||||||
std::string token;
|
|
||||||
|
|
||||||
std::vector<uint32_t> randomMissionPool;
|
|
||||||
|
|
||||||
while (std::getline(stream, token, ',')) {
|
|
||||||
try {
|
|
||||||
const auto value = std::stoul(token);
|
|
||||||
|
|
||||||
randomMissionPool.push_back(value);
|
|
||||||
} catch (std::invalid_argument& exception) {
|
|
||||||
Game::logger->Log("MissionOfferComponent", "Failed to parse value (%s): (%s)!", token.c_str(), exception.what());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (specifiedMissionId > 0) {
|
if (specifiedMissionId > 0) {
|
||||||
const auto& iter = std::find(randomMissionPool.begin(), randomMissionPool.end(), specifiedMissionId);
|
if (std::find(randomMissions.begin(), randomMissions.end(), specifiedMissionId) != randomMissions.end() &&
|
||||||
|
MissionPrerequisites::CanAccept(specifiedMissionId, missionComponent->GetMissions())) {
|
||||||
if (iter != randomMissionPool.end() && MissionPrerequisites::CanAccept(specifiedMissionId, missionComponent->GetMissions())) {
|
|
||||||
GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), specifiedMissionId, m_ParentEntity->GetObjectID());
|
GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), specifiedMissionId, m_ParentEntity->GetObjectID());
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> canAcceptPool;
|
std::vector<uint32_t> canAcceptPool;
|
||||||
|
for (const auto& sample : randomMissions) {
|
||||||
for (const auto sample : randomMissionPool) {
|
|
||||||
const auto state = missionComponent->GetMissionState(sample);
|
const auto state = missionComponent->GetMissionState(sample);
|
||||||
|
|
||||||
if (state == eMissionState::ACTIVE ||
|
if (state == eMissionState::ACTIVE ||
|
||||||
@ -180,9 +126,7 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi
|
|||||||
sample == specifiedMissionId) {
|
sample == specifiedMissionId) {
|
||||||
mission = missionComponent->GetMission(sample);
|
mission = missionComponent->GetMission(sample);
|
||||||
|
|
||||||
if (mission == nullptr || mission->IsAchievement()) {
|
if (!mission || mission->IsAchievement()) continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), sample, m_ParentEntity->GetObjectID());
|
GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), sample, m_ParentEntity->GetObjectID());
|
||||||
|
|
||||||
@ -191,16 +135,16 @@ void MissionOfferComponent::OfferMissions(Entity* entity, const uint32_t specifi
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(offered.begin(), offered.end(), sample) == offered.end() && MissionPrerequisites::CanAccept(sample, missionComponent->GetMissions())) {
|
if (std::find(offered.begin(), offered.end(), sample) == offered.end() &&
|
||||||
|
MissionPrerequisites::CanAccept(sample, missionComponent->GetMissions())) {
|
||||||
canAcceptPool.push_back(sample);
|
canAcceptPool.push_back(sample);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the mission is already active or we already completed one of them today
|
// If the mission is already active or we already completed one of them today
|
||||||
if (canAcceptPool.empty())
|
if (canAcceptPool.empty()) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
const auto selected = canAcceptPool[GeneralUtils::GenerateRandomNumber<int>(0, canAcceptPool.size() - 1)];
|
const auto selected = canAcceptPool[GeneralUtils::GenerateRandomNumber<int32_t>(0, canAcceptPool.size() - 1)];
|
||||||
|
|
||||||
GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), selected, m_ParentEntity->GetObjectID());
|
GameMessages::SendOfferMission(entity->GetObjectID(), entity->GetSystemAddress(), selected, m_ParentEntity->GetObjectID());
|
||||||
} else if (std::find(offered.begin(), offered.end(), missionId) == offered.end() && offeredMission->GetOfferMission()) {
|
} else if (std::find(offered.begin(), offered.end(), missionId) == offered.end() && offeredMission->GetOfferMission()) {
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Darkflame Universe
|
* Darkflame Universe
|
||||||
* Copyright 2019
|
* Copyright 2023
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MISSIONOFFERCOMPONENT_H
|
#ifndef __MISSIONOFFERCOMPONENT_H__
|
||||||
#define MISSIONOFFERCOMPONENT_H
|
#define __MISSIONOFFERCOMPONENT_H__
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "dCommonVars.h"
|
#include "dCommonVars.h"
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include <vector>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
@ -18,25 +21,29 @@ class Entity;
|
|||||||
* Light wrapper around missions that may be offered by an entity
|
* Light wrapper around missions that may be offered by an entity
|
||||||
*/
|
*/
|
||||||
struct OfferedMission {
|
struct OfferedMission {
|
||||||
OfferedMission(uint32_t missionId, bool offersMission, bool acceptsMission);
|
OfferedMission(const uint32_t missionId, const bool offersMission, const bool acceptsMission) {
|
||||||
|
this->missionId = missionId;
|
||||||
|
this->offersMission = offersMission;
|
||||||
|
this->acceptsMission = acceptsMission;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ID of the mission
|
* Returns the ID of the mission
|
||||||
* @return the ID of the mission
|
* @return the ID of the mission
|
||||||
*/
|
*/
|
||||||
uint32_t GetMissionId() const;
|
uint32_t GetMissionId() const { return missionId; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if this mission is offered by the entity
|
* Returns if this mission is offered by the entity
|
||||||
* @return true if this mission is offered by the entity, false otherwise
|
* @return true if this mission is offered by the entity, false otherwise
|
||||||
*/
|
*/
|
||||||
bool GetOfferMission() const;
|
bool GetOfferMission() const { return offersMission; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if this mission may be accepted by the entity (currently unused)
|
* Returns if this mission may be accepted by the entity (currently unused)
|
||||||
* @return true if this mission may be accepted by the entity, false otherwise
|
* @return true if this mission may be accepted by the entity, false otherwise
|
||||||
*/
|
*/
|
||||||
bool GetAcceptMission() const;
|
bool GetAcceptMission() const { return acceptsMission; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -63,8 +70,9 @@ class MissionOfferComponent : public Component {
|
|||||||
public:
|
public:
|
||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MISSION_OFFER;
|
||||||
|
|
||||||
MissionOfferComponent(Entity* parent, LOT parentLot);
|
MissionOfferComponent(Entity* parent, const int32_t componentId = -1);
|
||||||
~MissionOfferComponent() override;
|
|
||||||
|
void LoadTemplateData() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles the OnUse event triggered by some entity, determines which missions to show based on what they may
|
* Handles the OnUse event triggered by some entity, determines which missions to show based on what they may
|
||||||
@ -85,7 +93,9 @@ private:
|
|||||||
/**
|
/**
|
||||||
* The missions this entity has to offer
|
* The missions this entity has to offer
|
||||||
*/
|
*/
|
||||||
std::vector<OfferedMission*> offeredMissions;
|
std::vector<std::unique_ptr<OfferedMission>> offeredMissions;
|
||||||
|
|
||||||
|
int32_t m_ComponentId;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MISSIONOFFERCOMPONENT_H
|
#endif // __MISSIONOFFERCOMPONENT_H__
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include "ePhysicsBehaviorType.h"
|
#include "ePhysicsBehaviorType.h"
|
||||||
|
|
||||||
ModelBehaviorComponent::ModelBehaviorComponent(Entity* parent) : Component(parent) {
|
ModelBehaviorComponent::ModelBehaviorComponent(Entity* parent) : Component(parent) {
|
||||||
m_DirtyModelInfo = false;
|
m_DirtyModelInfo = true;
|
||||||
m_IsPickable = false;
|
m_IsPickable = false;
|
||||||
m_PhysicsType = ePhysicsBehaviorType::STANDARD;
|
m_PhysicsType = ePhysicsBehaviorType::STANDARD;
|
||||||
m_OriginalPosition = m_ParentEntity->GetDefaultPosition();
|
m_OriginalPosition = m_ParentEntity->GetDefaultPosition();
|
||||||
@ -17,7 +17,7 @@ void ModelBehaviorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIs
|
|||||||
outBitStream->Write(m_PhysicsType);
|
outBitStream->Write(m_PhysicsType);
|
||||||
outBitStream->Write(m_OriginalPosition);
|
outBitStream->Write(m_OriginalPosition);
|
||||||
outBitStream->Write(m_OriginalRotation);
|
outBitStream->Write(m_OriginalRotation);
|
||||||
m_DirtyModelInfo = false;
|
if (!bIsInitialUpdate) m_DirtyModelInfo = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,11 @@ public:
|
|||||||
* Sets the original position of the model
|
* Sets the original position of the model
|
||||||
* @param pos the original position to set
|
* @param pos the original position to set
|
||||||
*/
|
*/
|
||||||
void SetPosition(const NiPoint3& pos) { m_OriginalPosition = pos; m_DirtyModelInfo = true; }
|
void SetPosition(const NiPoint3& pos) {
|
||||||
|
if (m_OriginalPosition == pos) return;
|
||||||
|
m_OriginalPosition = pos;
|
||||||
|
m_DirtyModelInfo = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the original rotation of the model
|
* Returns the original rotation of the model
|
||||||
@ -42,7 +46,11 @@ public:
|
|||||||
* Sets the original rotation of the model
|
* Sets the original rotation of the model
|
||||||
* @param rot the original rotation to set
|
* @param rot the original rotation to set
|
||||||
*/
|
*/
|
||||||
void SetRotation(const NiQuaternion& rot) { m_OriginalRotation = rot; m_DirtyModelInfo = true; }
|
void SetRotation(const NiQuaternion& rot) {
|
||||||
|
if (m_OriginalRotation == rot) return;
|
||||||
|
m_OriginalRotation = rot;
|
||||||
|
m_DirtyModelInfo = true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -1,70 +1,31 @@
|
|||||||
#include "ModuleAssemblyComponent.h"
|
#include "ModuleAssemblyComponent.h"
|
||||||
|
|
||||||
|
#include "Entity.h"
|
||||||
|
|
||||||
ModuleAssemblyComponent::ModuleAssemblyComponent(Entity* parent) : Component(parent) {
|
ModuleAssemblyComponent::ModuleAssemblyComponent(Entity* parent) : Component(parent) {
|
||||||
m_SubKey = LWOOBJID_EMPTY;
|
m_SubKey = LWOOBJID_EMPTY;
|
||||||
m_UseOptionalParts = false;
|
m_UseOptionalParts = false;
|
||||||
m_AssemblyPartsLOTs = u"";
|
|
||||||
}
|
|
||||||
|
|
||||||
ModuleAssemblyComponent::~ModuleAssemblyComponent() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModuleAssemblyComponent::SetSubKey(LWOOBJID value) {
|
|
||||||
m_SubKey = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
LWOOBJID ModuleAssemblyComponent::GetSubKey() const {
|
|
||||||
return m_SubKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ModuleAssemblyComponent::SetUseOptionalParts(bool value) {
|
|
||||||
m_UseOptionalParts = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModuleAssemblyComponent::GetUseOptionalParts() const {
|
|
||||||
return m_UseOptionalParts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleAssemblyComponent::SetAssemblyPartsLOTs(const std::u16string& value) {
|
void ModuleAssemblyComponent::SetAssemblyPartsLOTs(const std::u16string& value) {
|
||||||
std::u16string val{};
|
m_AssemblyPartsLOTs = value;
|
||||||
|
std::replace(m_AssemblyPartsLOTs.begin(), m_AssemblyPartsLOTs.end(), u'+', u';');
|
||||||
val.reserve(value.size() + 1);
|
// doesn't matter if we push back a ; or a +. The client splits on either of them.
|
||||||
|
// For congruency however, maintain one or the other.
|
||||||
for (auto character : value) {
|
m_AssemblyPartsLOTs.push_back(u';');
|
||||||
if (character == '+') character = ';';
|
|
||||||
|
|
||||||
val.push_back(character);
|
|
||||||
}
|
|
||||||
|
|
||||||
val.push_back(';');
|
|
||||||
|
|
||||||
m_AssemblyPartsLOTs = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::u16string& ModuleAssemblyComponent::GetAssemblyPartsLOTs() const {
|
|
||||||
return m_AssemblyPartsLOTs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleAssemblyComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
void ModuleAssemblyComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
||||||
if (bIsInitialUpdate) {
|
if (!bIsInitialUpdate) return;
|
||||||
outBitStream->Write1();
|
outBitStream->Write(bIsInitialUpdate);
|
||||||
|
|
||||||
outBitStream->Write(m_SubKey != LWOOBJID_EMPTY);
|
outBitStream->Write(m_SubKey != LWOOBJID_EMPTY);
|
||||||
if (m_SubKey != LWOOBJID_EMPTY) {
|
if (m_SubKey != LWOOBJID_EMPTY) outBitStream->Write(m_SubKey);
|
||||||
outBitStream->Write(m_SubKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
outBitStream->Write(m_UseOptionalParts);
|
outBitStream->Write(m_UseOptionalParts);
|
||||||
|
|
||||||
outBitStream->Write(static_cast<uint16_t>(m_AssemblyPartsLOTs.size()));
|
outBitStream->Write<uint16_t>(m_AssemblyPartsLOTs.size());
|
||||||
for (char16_t character : m_AssemblyPartsLOTs) {
|
for (const char16_t character : m_AssemblyPartsLOTs) {
|
||||||
outBitStream->Write(character);
|
outBitStream->Write(character);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleAssemblyComponent::Update(float deltaTime) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
|
#ifndef __MODULEASSEMBLYCOMPONENT__H__
|
||||||
|
#define __MODULEASSEMBLYCOMPONENT__H__
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "BitStream.h"
|
|
||||||
#include "Entity.h"
|
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include "eReplicaComponentType.h"
|
#include "eReplicaComponentType.h"
|
||||||
|
|
||||||
|
namespace RakNet {
|
||||||
|
class BitStream;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that belongs to an object that may be modularly built, like cars and rockets. Note that this is not the
|
* Component that belongs to an object that may be modularly built, like cars and rockets. Note that this is not the
|
||||||
* same as having said items in your inventory (the subkey for this component) this component is the one that
|
* same as having said items in your inventory (the subkey for this component) this component is the one that
|
||||||
@ -15,35 +20,32 @@ public:
|
|||||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
|
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::MODULE_ASSEMBLY;
|
||||||
|
|
||||||
ModuleAssemblyComponent(Entity* parent);
|
ModuleAssemblyComponent(Entity* parent);
|
||||||
~ModuleAssemblyComponent() override;
|
|
||||||
|
|
||||||
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
|
||||||
void Update(float deltaTime) override;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the subkey of this entity
|
* Sets the subkey of this entity
|
||||||
* @param value the subkey to set
|
* @param value the subkey to set
|
||||||
*/
|
*/
|
||||||
void SetSubKey(LWOOBJID value);
|
void SetSubKey(const LWOOBJID& value) { m_SubKey = value; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the subkey for this entity
|
* Returns the subkey for this entity
|
||||||
* @return the subkey for this entity
|
* @return the subkey for this entity
|
||||||
*/
|
*/
|
||||||
LWOOBJID GetSubKey() const;
|
LWOOBJID GetSubKey() const { return m_SubKey; };
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the optional parts value
|
* Sets the optional parts value
|
||||||
* @param value the value to set
|
* @param value the value to set
|
||||||
*/
|
*/
|
||||||
void SetUseOptionalParts(bool value);
|
void SetUseOptionalParts(bool value) { m_UseOptionalParts = value; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the optional parts value
|
* Returns the optional parts value
|
||||||
* @return the value to set
|
* @return the value to set
|
||||||
*/
|
*/
|
||||||
bool GetUseOptionalParts() const;
|
bool GetUseOptionalParts() const { return m_UseOptionalParts; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the assembly part lots (the subsections of this modular build)
|
* Sets the assembly part lots (the subsections of this modular build)
|
||||||
@ -55,7 +57,7 @@ public:
|
|||||||
* Returns the assembly part lots (the subsections of this modular build)
|
* Returns the assembly part lots (the subsections of this modular build)
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
const std::u16string& GetAssemblyPartsLOTs() const;
|
const std::u16string& GetAssemblyPartsLOTs() const { return m_AssemblyPartsLOTs; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -75,3 +77,5 @@ private:
|
|||||||
*/
|
*/
|
||||||
std::u16string m_AssemblyPartsLOTs;
|
std::u16string m_AssemblyPartsLOTs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif //!__MODULEASSEMBLYCOMPONENT__H__
|
||||||
|
@ -517,7 +517,7 @@ void Entity::Initialize() {
|
|||||||
m_IsGhostingCandidate = false;
|
m_IsGhostingCandidate = false;
|
||||||
break;
|
break;
|
||||||
case eReplicaComponentType::MISSION_OFFER:
|
case eReplicaComponentType::MISSION_OFFER:
|
||||||
AddComponent<MissionOfferComponent>(GetLOT());
|
AddComponent<MissionOfferComponent>(componentId);
|
||||||
break;
|
break;
|
||||||
case eReplicaComponentType::RACING_STATS:
|
case eReplicaComponentType::RACING_STATS:
|
||||||
AddComponent<RacingStatsComponent>();
|
AddComponent<RacingStatsComponent>();
|
||||||
|
Loading…
Reference in New Issue
Block a user