Vendor cleanup and start Donation Vendor impl

This commit is contained in:
Aaron Kimbre 2023-06-23 00:56:25 -05:00
parent e180430ede
commit dc96fcba85
8 changed files with 146 additions and 74 deletions

View File

@ -74,8 +74,8 @@ CDItemComponentTable::CDItemComponentTable(void) {
#endif #endif
} }
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) { const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int id) {
const auto& it = this->entries.find(skillID); const auto& it = this->entries.find(id);
if (it != this->entries.end()) { if (it != this->entries.end()) {
return it->second; return it->second;
} }
@ -83,11 +83,11 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
#ifndef CDCLIENT_CACHE_ALL #ifndef CDCLIENT_CACHE_ALL
std::stringstream query; std::stringstream query;
query << "SELECT * FROM ItemComponent WHERE id = " << std::to_string(skillID); query << "SELECT * FROM ItemComponent WHERE id = " << std::to_string(id);
auto tableData = CDClientDatabase::ExecuteQuery(query.str()); auto tableData = CDClientDatabase::ExecuteQuery(query.str());
if (tableData.eof()) { if (tableData.eof()) {
entries.insert(std::make_pair(skillID, Default)); entries.insert(std::make_pair(id, Default));
return Default; return Default;
} }
@ -140,7 +140,7 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
tableData.nextRow(); tableData.nextRow();
} }
const auto& it2 = this->entries.find(skillID); const auto& it2 = this->entries.find(id);
if (it2 != this->entries.end()) { if (it2 != this->entries.end()) {
return it2->second; return it2->second;
} }

View File

@ -58,7 +58,7 @@ public:
static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent); static std::map<LOT, uint32_t> ParseCraftingCurrencies(const CDItemComponent& itemComponent);
// Gets an entry by ID // Gets an entry by ID
const CDItemComponent& GetItemComponentByID(unsigned int skillID); const CDItemComponent& GetItemComponentByID(unsigned int id);
static CDItemComponent Default; static CDItemComponent Default;
}; };

View File

@ -7,6 +7,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
"Component.cpp" "Component.cpp"
"ControllablePhysicsComponent.cpp" "ControllablePhysicsComponent.cpp"
"DestroyableComponent.cpp" "DestroyableComponent.cpp"
"DonationVendorComponent.cpp"
"InventoryComponent.cpp" "InventoryComponent.cpp"
"ItemComponent.cpp" "ItemComponent.cpp"
"LevelProgressionComponent.cpp" "LevelProgressionComponent.cpp"

View File

@ -0,0 +1,24 @@
#include "DonationVendorComponent.h"
DonationVendorComponent::DonationVendorComponent(Entity* parent) : VendorComponent(parent) {
m_PercentComplete = 0.0;
m_TotalDonated = 0;
m_TotalRemaining = 0;
}
void DonationVendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
VendorComponent::Serialize(outBitStream, bIsInitialUpdate, flags);
outBitStream->Write(bIsInitialUpdate || m_DirtyDonationVendor);
if (bIsInitialUpdate || m_DirtyDonationVendor) {
outBitStream->Write(m_PercentComplete);
outBitStream->Write(m_TotalDonated);
outBitStream->Write(m_TotalRemaining);
}
}
void DonationVendorComponent::LoadConfigData() {
m_ActivityId = m_ParentEntity->GetVar<uint32_t>(u"activityID");
VendorComponent::LoadConfigData();
}

View File

@ -0,0 +1,44 @@
#ifndef __DONATIONVENDORCOMPONENT__H__
#define __DONATIONVENDORCOMPONENT__H__
#include "VendorComponent.h"
#include "eReplicaComponentType.h"
class Entity;
class DonationVendorComponent : public VendorComponent {
public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::DONATION_VENDOR;
DonationVendorComponent(Entity* parent);
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
void LoadConfigData() override;
void SetPercentComplete(float percentComplete){
if (m_PercentComplete == percentComplete) return;
m_PercentComplete = percentComplete;
m_DirtyDonationVendor = true;
}
void SetTotalDonated(float totalDonated){
if (m_TotalDonated == totalDonated) return;
m_TotalDonated = totalDonated;
m_DirtyDonationVendor = true;
}
void SetTotalRemaining(float totalRemaining){
if (m_TotalRemaining == totalRemaining) return;
m_TotalRemaining = totalRemaining;
m_DirtyDonationVendor = true;
}
private:
bool m_DirtyDonationVendor = false;
float m_PercentComplete = 0.0;
int32_t m_TotalDonated = 0;
int32_t m_TotalRemaining = 0;
uint32_t m_ActivityId = 0;
};
#endif //!__DONATIONVENDORCOMPONENT__H__

View File

@ -9,18 +9,21 @@
#include "CDVendorComponentTable.h" #include "CDVendorComponentTable.h"
#include "CDLootMatrixTable.h" #include "CDLootMatrixTable.h"
#include "CDLootTableTable.h" #include "CDLootTableTable.h"
#include "CDItemComponentTable.h"
VendorComponent::VendorComponent(Entity* parent) : Component(parent) { VendorComponent::VendorComponent(Entity* parent) : Component(parent) {
m_HasStandardCostItems = false;
m_HasMultiCostItems = false;
SetupConstants(); SetupConstants();
RefreshInventory(true); RefreshInventory(true);
} }
VendorComponent::~VendorComponent() = default;
void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) { void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
outBitStream->Write1(); outBitStream->Write(bIsInitialUpdate || m_DirtyVendor);
outBitStream->Write1(); // Has standard items (Required for vendors with missions.) if (bIsInitialUpdate || m_DirtyVendor) {
outBitStream->Write(HasCraftingStation()); // Has multi use items outBitStream->Write(m_HasStandardCostItems);
outBitStream->Write(m_HasMultiCostItems);
}
} }
void VendorComponent::OnUse(Entity* originator) { void VendorComponent::OnUse(Entity* originator) {
@ -28,35 +31,15 @@ void VendorComponent::OnUse(Entity* originator) {
GameMessages::SendVendorStatusUpdate(m_ParentEntity, originator->GetSystemAddress()); GameMessages::SendVendorStatusUpdate(m_ParentEntity, originator->GetSystemAddress());
} }
float VendorComponent::GetBuyScalar() const {
return m_BuyScalar;
}
float VendorComponent::GetSellScalar() const {
return m_SellScalar;
}
void VendorComponent::SetBuyScalar(float value) {
m_BuyScalar = value;
}
void VendorComponent::SetSellScalar(float value) {
m_SellScalar = value;
}
std::map<LOT, int>& VendorComponent::GetInventory() {
return m_Inventory;
}
bool VendorComponent::HasCraftingStation() {
// As far as we know, only Umami has a crafting station
return m_ParentEntity->GetLOT() == 13800;
}
void VendorComponent::RefreshInventory(bool isCreation) { void VendorComponent::RefreshInventory(bool isCreation) {
SetHasStandardCostItems(false);
SetHasMultiCostItems(false);
//Custom code for Max vanity NPC //Custom code for Max vanity NPC
if (m_ParentEntity->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) { if (m_ParentEntity->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) {
if (!isCreation) return; if (!isCreation) return;
SetHasStandardCostItems(true);
m_Inventory.insert({ 11909, 0 }); // Top hat w frog m_Inventory.insert({ 11909, 0 }); // Top hat w frog
m_Inventory.insert({ 7785, 0 }); // Flash bulb m_Inventory.insert({ 7785, 0 }); // Flash bulb
m_Inventory.insert({ 12764, 0 }); // Big fountain soda m_Inventory.insert({ 12764, 0 }); // Big fountain soda
@ -71,12 +54,20 @@ void VendorComponent::RefreshInventory(bool isCreation) {
// Done with lootMatrix table // Done with lootMatrix table
auto* lootTableTable = CDClientManager::Instance().GetTable<CDLootTableTable>(); auto* lootTableTable = CDClientManager::Instance().GetTable<CDLootTableTable>();
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>();
auto* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
for (const auto& lootMatrix : lootMatrices) { for (const auto& lootMatrix : lootMatrices) {
int lootTableID = lootMatrix.LootTableIndex; int lootTableID = lootMatrix.LootTableIndex;
std::vector<CDLootTable> vendorItems = lootTableTable->Query([=](CDLootTable entry) { return (entry.LootTableIndex == lootTableID); }); std::vector<CDLootTable> vendorItems = lootTableTable->Query([=](CDLootTable entry) { return (entry.LootTableIndex == lootTableID); });
if (lootMatrix.maxToDrop == 0 || lootMatrix.minToDrop == 0) { if (lootMatrix.maxToDrop == 0 || lootMatrix.minToDrop == 0) {
for (CDLootTable item : vendorItems) { for (CDLootTable item : vendorItems) {
if (!m_HasStandardCostItems || !m_HasMultiCostItems){
auto itemComponentID = compRegistryTable->GetByIDAndType(item.itemid, eReplicaComponentType::ITEM);
auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID);
if (!m_HasStandardCostItems && itemComponent.baseValue != -1) SetHasStandardCostItems(true);
if (!m_HasMultiCostItems && !itemComponent.currencyCosts.empty()) SetHasMultiCostItems(true);
}
m_Inventory.insert({ item.itemid, item.sortPriority }); m_Inventory.insert({ item.itemid, item.sortPriority });
} }
} else { } else {
@ -84,19 +75,21 @@ void VendorComponent::RefreshInventory(bool isCreation) {
for (size_t i = 0; i < randomCount; i++) { for (size_t i = 0; i < randomCount; i++) {
if (vendorItems.empty()) break; if (vendorItems.empty()) break;
auto randomItemIndex = GeneralUtils::GenerateRandomNumber<int32_t>(0, vendorItems.size() - 1); auto randomItemIndex = GeneralUtils::GenerateRandomNumber<int32_t>(0, vendorItems.size() - 1);
const auto& randomItem = vendorItems[randomItemIndex]; const auto& randomItem = vendorItems[randomItemIndex];
vendorItems.erase(vendorItems.begin() + randomItemIndex); vendorItems.erase(vendorItems.begin() + randomItemIndex);
if (!m_HasStandardCostItems || !m_HasMultiCostItems){
auto itemComponentID = compRegistryTable->GetByIDAndType(randomItem.itemid, eReplicaComponentType::ITEM);
auto itemComponent = itemComponentTable->GetItemComponentByID(itemComponentID);
if (!m_HasStandardCostItems && itemComponent.baseValue != -1) SetHasStandardCostItems(true);
if (!m_HasMultiCostItems && !itemComponent.currencyCosts.empty()) SetHasMultiCostItems(true);
}
m_Inventory.insert({ randomItem.itemid, randomItem.sortPriority }); m_Inventory.insert({ randomItem.itemid, randomItem.sortPriority });
} }
} }
} }
//Because I want a vendor to sell these cameras //Because I (Max) want a vendor to sell these cameras
if (m_ParentEntity->GetLOT() == 13569) { if (m_ParentEntity->GetLOT() == 13569) {
auto randomCamera = GeneralUtils::GenerateRandomNumber<int32_t>(0, 2); auto randomCamera = GeneralUtils::GenerateRandomNumber<int32_t>(0, 2);
@ -118,7 +111,9 @@ void VendorComponent::RefreshInventory(bool isCreation) {
// Callback timer to refresh this inventory. // Callback timer to refresh this inventory.
m_ParentEntity->AddCallbackTimer(m_RefreshTimeSeconds, [this]() { m_ParentEntity->AddCallbackTimer(m_RefreshTimeSeconds, [this]() {
RefreshInventory(); RefreshInventory();
}); }
);
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
GameMessages::SendVendorStatusUpdate(m_ParentEntity, UNASSIGNED_SYSTEM_ADDRESS); GameMessages::SendVendorStatusUpdate(m_ParentEntity, UNASSIGNED_SYSTEM_ADDRESS);
} }
@ -135,6 +130,4 @@ void VendorComponent::SetupConstants() {
m_LootMatrixID = vendorComps[0].LootMatrixIndex; m_LootMatrixID = vendorComps[0].LootMatrixIndex;
} }
bool VendorComponent::SellsItem(const LOT item) const {
return m_Inventory.find(item) != m_Inventory.end();
}

View File

@ -17,40 +17,41 @@ public:
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR; inline static const eReplicaComponentType ComponentType = eReplicaComponentType::VENDOR;
VendorComponent(Entity* parent); VendorComponent(Entity* parent);
~VendorComponent() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags); void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
void OnUse(Entity* originator) override; void OnUse(Entity* originator) override;
/** float GetBuyScalar() const {
* Gets the buy scaler return m_BuyScalar;
* @return the buy scaler }
*/
float GetBuyScalar() const;
/** float GetSellScalar() const {
* Sets the buy scalar. return m_SellScalar;
* @param value the new value. }
*/
void SetBuyScalar(float value);
/** void SetBuyScalar(float value) {
* Gets the buy scaler m_BuyScalar = value;
* @return the buy scaler }
*/
float GetSellScalar() const;
/** void SetSellScalar(float value) {
* Sets the sell scalar. m_SellScalar = value;
* @param value the new value. }
*/
void SetSellScalar(float value);
/** std::map<LOT, int>& GetInventory() {
* True if the NPC LOT is 13800, the only NPC with a crafting station. return m_Inventory;
*/ }
bool HasCraftingStation();
void SetHasMultiCostItems(bool hasMultiCostItems) {
if (m_HasMultiCostItems == hasMultiCostItems) return;
m_HasMultiCostItems = hasMultiCostItems;
m_DirtyVendor = true;
}
void SetHasStandardCostItems(bool hasStandardCostItems) {
if (m_HasStandardCostItems == hasStandardCostItems) return;
m_HasStandardCostItems = hasStandardCostItems;
m_DirtyVendor = true;
}
/** /**
* Gets the list if items the vendor sells. * Gets the list if items the vendor sells.
@ -68,7 +69,9 @@ public:
*/ */
void SetupConstants(); void SetupConstants();
bool SellsItem(const LOT item) const; bool SellsItem(const LOT item) const {
return m_Inventory.find(item) != m_Inventory.end();
}
private: private:
/** /**
* The buy scalar. * The buy scalar.
@ -94,6 +97,10 @@ private:
* The list of items the vendor sells. * The list of items the vendor sells.
*/ */
std::map<LOT, int> m_Inventory; std::map<LOT, int> m_Inventory;
bool m_DirtyVendor;
bool m_HasStandardCostItems;
bool m_HasMultiCostItems;
}; };
#endif // VENDORCOMPONENT_H #endif // VENDORCOMPONENT_H

View File

@ -70,6 +70,7 @@
#include "RacingStatsComponent.h" #include "RacingStatsComponent.h"
#include "MinigameControlComponent.h" #include "MinigameControlComponent.h"
#include "ItemComponent.h" #include "ItemComponent.h"
#include "DonationVendorComponent.h"
// Table includes // Table includes
#include "CDComponentsRegistryTable.h" #include "CDComponentsRegistryTable.h"
@ -469,6 +470,8 @@ void Entity::Initialize() {
case eReplicaComponentType::IGNORE_LIST: case eReplicaComponentType::IGNORE_LIST:
case eReplicaComponentType::INTERACTION_MANAGER: case eReplicaComponentType::INTERACTION_MANAGER:
case eReplicaComponentType::DONATION_VENDOR: case eReplicaComponentType::DONATION_VENDOR:
AddComponent<DonationVendorComponent>();
break;
case eReplicaComponentType::COMBAT_MEDIATOR: case eReplicaComponentType::COMBAT_MEDIATOR:
case eReplicaComponentType::ACHIEVEMENT_VENDOR: case eReplicaComponentType::ACHIEVEMENT_VENDOR:
case eReplicaComponentType::GATE_RUSH_CONTROL: case eReplicaComponentType::GATE_RUSH_CONTROL: