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
}
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int skillID) {
const auto& it = this->entries.find(skillID);
const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int id) {
const auto& it = this->entries.find(id);
if (it != this->entries.end()) {
return it->second;
}
@ -83,11 +83,11 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
#ifndef CDCLIENT_CACHE_ALL
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());
if (tableData.eof()) {
entries.insert(std::make_pair(skillID, Default));
entries.insert(std::make_pair(id, Default));
return Default;
}
@ -140,7 +140,7 @@ const CDItemComponent& CDItemComponentTable::GetItemComponentByID(unsigned int s
tableData.nextRow();
}
const auto& it2 = this->entries.find(skillID);
const auto& it2 = this->entries.find(id);
if (it2 != this->entries.end()) {
return it2->second;
}

View File

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

View File

@ -7,6 +7,7 @@ set(DGAME_DCOMPONENTS_SOURCES "BaseCombatAIComponent.cpp"
"Component.cpp"
"ControllablePhysicsComponent.cpp"
"DestroyableComponent.cpp"
"DonationVendorComponent.cpp"
"InventoryComponent.cpp"
"ItemComponent.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 "CDLootMatrixTable.h"
#include "CDLootTableTable.h"
#include "CDItemComponentTable.h"
VendorComponent::VendorComponent(Entity* parent) : Component(parent) {
m_HasStandardCostItems = false;
m_HasMultiCostItems = false;
SetupConstants();
RefreshInventory(true);
}
VendorComponent::~VendorComponent() = default;
void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
outBitStream->Write1();
outBitStream->Write1(); // Has standard items (Required for vendors with missions.)
outBitStream->Write(HasCraftingStation()); // Has multi use items
outBitStream->Write(bIsInitialUpdate || m_DirtyVendor);
if (bIsInitialUpdate || m_DirtyVendor) {
outBitStream->Write(m_HasStandardCostItems);
outBitStream->Write(m_HasMultiCostItems);
}
}
void VendorComponent::OnUse(Entity* originator) {
@ -28,39 +31,19 @@ void VendorComponent::OnUse(Entity* originator) {
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) {
SetHasStandardCostItems(false);
SetHasMultiCostItems(false);
//Custom code for Max vanity NPC
if (m_ParentEntity->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) {
if (!isCreation) return;
m_Inventory.insert({ 11909, 0 }); //Top hat w frog
m_Inventory.insert({ 7785, 0 }); //Flash bulb
m_Inventory.insert({ 12764, 0 }); //Big fountain soda
m_Inventory.insert({ 12241, 0 }); //Hot cocoa (from fb)
SetHasStandardCostItems(true);
m_Inventory.insert({ 11909, 0 }); // Top hat w frog
m_Inventory.insert({ 7785, 0 }); // Flash bulb
m_Inventory.insert({ 12764, 0 }); // Big fountain soda
m_Inventory.insert({ 12241, 0 }); // Hot cocoa (from fb)
return;
}
m_Inventory.clear();
@ -71,12 +54,20 @@ void VendorComponent::RefreshInventory(bool isCreation) {
// Done with lootMatrix table
auto* lootTableTable = CDClientManager::Instance().GetTable<CDLootTableTable>();
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>();
auto* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
for (const auto& lootMatrix : lootMatrices) {
int lootTableID = lootMatrix.LootTableIndex;
std::vector<CDLootTable> vendorItems = lootTableTable->Query([=](CDLootTable entry) { return (entry.LootTableIndex == lootTableID); });
if (lootMatrix.maxToDrop == 0 || lootMatrix.minToDrop == 0) {
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 });
}
} else {
@ -84,19 +75,21 @@ void VendorComponent::RefreshInventory(bool isCreation) {
for (size_t i = 0; i < randomCount; i++) {
if (vendorItems.empty()) break;
auto randomItemIndex = GeneralUtils::GenerateRandomNumber<int32_t>(0, vendorItems.size() - 1);
const auto& randomItem = vendorItems[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 });
}
}
}
//Because I want a vendor to sell these cameras
//Because I (Max) want a vendor to sell these cameras
if (m_ParentEntity->GetLOT() == 13569) {
auto randomCamera = GeneralUtils::GenerateRandomNumber<int32_t>(0, 2);
@ -118,7 +111,9 @@ void VendorComponent::RefreshInventory(bool isCreation) {
// Callback timer to refresh this inventory.
m_ParentEntity->AddCallbackTimer(m_RefreshTimeSeconds, [this]() {
RefreshInventory();
});
}
);
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
GameMessages::SendVendorStatusUpdate(m_ParentEntity, UNASSIGNED_SYSTEM_ADDRESS);
}
@ -135,6 +130,4 @@ void VendorComponent::SetupConstants() {
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;
VendorComponent(Entity* parent);
~VendorComponent() override;
void Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags);
void OnUse(Entity* originator) override;
/**
* Gets the buy scaler
* @return the buy scaler
*/
float GetBuyScalar() const;
float GetBuyScalar() const {
return m_BuyScalar;
}
/**
* Sets the buy scalar.
* @param value the new value.
*/
void SetBuyScalar(float value);
float GetSellScalar() const {
return m_SellScalar;
}
/**
* Gets the buy scaler
* @return the buy scaler
*/
float GetSellScalar() const;
void SetBuyScalar(float value) {
m_BuyScalar = value;
}
/**
* Sets the sell scalar.
* @param value the new value.
*/
void SetSellScalar(float value);
void SetSellScalar(float value) {
m_SellScalar = value;
}
/**
* True if the NPC LOT is 13800, the only NPC with a crafting station.
*/
bool HasCraftingStation();
std::map<LOT, int>& GetInventory() {
return m_Inventory;
}
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.
@ -68,7 +69,9 @@ public:
*/
void SetupConstants();
bool SellsItem(const LOT item) const;
bool SellsItem(const LOT item) const {
return m_Inventory.find(item) != m_Inventory.end();
}
private:
/**
* The buy scalar.
@ -94,6 +97,10 @@ private:
* The list of items the vendor sells.
*/
std::map<LOT, int> m_Inventory;
bool m_DirtyVendor;
bool m_HasStandardCostItems;
bool m_HasMultiCostItems;
};
#endif // VENDORCOMPONENT_H

View File

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