2021-12-05 17:54:36 +00:00
|
|
|
#include "VendorComponent.h"
|
|
|
|
|
|
|
|
#include <BitStream.h>
|
|
|
|
|
2022-04-26 10:41:16 +00:00
|
|
|
#include "Game.h"
|
|
|
|
#include "dServer.h"
|
2021-12-05 17:54:36 +00:00
|
|
|
|
2023-03-17 14:36:21 +00:00
|
|
|
#include "CDComponentsRegistryTable.h"
|
|
|
|
#include "CDVendorComponentTable.h"
|
|
|
|
#include "CDLootMatrixTable.h"
|
|
|
|
#include "CDLootTableTable.h"
|
2023-06-23 05:56:25 +00:00
|
|
|
#include "CDItemComponentTable.h"
|
2023-03-17 14:36:21 +00:00
|
|
|
|
2022-04-26 10:41:16 +00:00
|
|
|
VendorComponent::VendorComponent(Entity* parent) : Component(parent) {
|
2023-06-23 05:56:25 +00:00
|
|
|
m_HasStandardCostItems = false;
|
|
|
|
m_HasMultiCostItems = false;
|
2022-04-26 10:41:16 +00:00
|
|
|
SetupConstants();
|
|
|
|
RefreshInventory(true);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VendorComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInitialUpdate, unsigned int& flags) {
|
2023-06-23 05:56:25 +00:00
|
|
|
outBitStream->Write(bIsInitialUpdate || m_DirtyVendor);
|
|
|
|
if (bIsInitialUpdate || m_DirtyVendor) {
|
|
|
|
outBitStream->Write(m_HasStandardCostItems);
|
|
|
|
outBitStream->Write(m_HasMultiCostItems);
|
|
|
|
}
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VendorComponent::OnUse(Entity* originator) {
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendVendorOpenWindow(m_ParentEntity, originator->GetSystemAddress());
|
|
|
|
GameMessages::SendVendorStatusUpdate(m_ParentEntity, originator->GetSystemAddress());
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
|
|
|
|
2022-04-26 10:41:16 +00:00
|
|
|
|
|
|
|
void VendorComponent::RefreshInventory(bool isCreation) {
|
2023-06-23 05:56:25 +00:00
|
|
|
SetHasStandardCostItems(false);
|
|
|
|
SetHasMultiCostItems(false);
|
|
|
|
|
2022-04-26 10:41:16 +00:00
|
|
|
//Custom code for Max vanity NPC
|
2023-06-09 09:46:01 +00:00
|
|
|
if (m_ParentEntity->GetLOT() == 9749 && Game::server->GetZoneID() == 1201) {
|
2022-04-26 10:41:16 +00:00
|
|
|
if (!isCreation) return;
|
2023-06-23 05:56:25 +00:00
|
|
|
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)
|
2022-04-26 10:41:16 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_Inventory.clear();
|
2023-03-17 14:36:21 +00:00
|
|
|
auto* lootMatrixTable = CDClientManager::Instance().GetTable<CDLootMatrixTable>();
|
2022-04-26 10:41:16 +00:00
|
|
|
std::vector<CDLootMatrix> lootMatrices = lootMatrixTable->Query([=](CDLootMatrix entry) { return (entry.LootMatrixIndex == m_LootMatrixID); });
|
|
|
|
|
|
|
|
if (lootMatrices.empty()) return;
|
|
|
|
// Done with lootMatrix table
|
|
|
|
|
2023-03-17 14:36:21 +00:00
|
|
|
auto* lootTableTable = CDClientManager::Instance().GetTable<CDLootTableTable>();
|
2023-06-23 05:56:25 +00:00
|
|
|
auto* itemComponentTable = CDClientManager::Instance().GetTable<CDItemComponentTable>();
|
|
|
|
auto* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
2022-04-26 10:41:16 +00:00
|
|
|
|
|
|
|
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) {
|
2023-06-23 05:56:25 +00:00
|
|
|
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);
|
|
|
|
}
|
2022-04-26 10:41:16 +00:00
|
|
|
m_Inventory.insert({ item.itemid, item.sortPriority });
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
auto randomCount = GeneralUtils::GenerateRandomNumber<int32_t>(lootMatrix.minToDrop, lootMatrix.maxToDrop);
|
|
|
|
|
|
|
|
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);
|
2023-06-23 05:56:25 +00:00
|
|
|
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);
|
|
|
|
}
|
2022-04-26 10:41:16 +00:00
|
|
|
m_Inventory.insert({ randomItem.itemid, randomItem.sortPriority });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-23 05:56:25 +00:00
|
|
|
//Because I (Max) want a vendor to sell these cameras
|
2023-06-09 09:46:01 +00:00
|
|
|
if (m_ParentEntity->GetLOT() == 13569) {
|
2022-04-26 10:41:16 +00:00
|
|
|
auto randomCamera = GeneralUtils::GenerateRandomNumber<int32_t>(0, 2);
|
|
|
|
|
|
|
|
switch (randomCamera) {
|
|
|
|
case 0:
|
|
|
|
m_Inventory.insert({ 16253, 0 }); //Grungagroid
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
m_Inventory.insert({ 16254, 0 }); //Hipstabrick
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
m_Inventory.insert({ 16204, 0 }); //Megabrixel snapshot
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Callback timer to refresh this inventory.
|
2023-06-09 09:46:01 +00:00
|
|
|
m_ParentEntity->AddCallbackTimer(m_RefreshTimeSeconds, [this]() {
|
2022-04-26 10:41:16 +00:00
|
|
|
RefreshInventory();
|
2023-06-23 05:56:25 +00:00
|
|
|
}
|
|
|
|
);
|
|
|
|
EntityManager::Instance()->SerializeEntity(m_ParentEntity);
|
2023-06-09 09:46:01 +00:00
|
|
|
GameMessages::SendVendorStatusUpdate(m_ParentEntity, UNASSIGNED_SYSTEM_ADDRESS);
|
2021-12-05 17:54:36 +00:00
|
|
|
}
|
2022-04-26 10:41:16 +00:00
|
|
|
|
|
|
|
void VendorComponent::SetupConstants() {
|
2023-03-17 14:36:21 +00:00
|
|
|
auto* compRegistryTable = CDClientManager::Instance().GetTable<CDComponentsRegistryTable>();
|
2023-06-09 09:46:01 +00:00
|
|
|
int componentID = compRegistryTable->GetByIDAndType(m_ParentEntity->GetLOT(), eReplicaComponentType::VENDOR);
|
2022-04-26 10:41:16 +00:00
|
|
|
|
2023-03-17 14:36:21 +00:00
|
|
|
auto* vendorComponentTable = CDClientManager::Instance().GetTable<CDVendorComponentTable>();
|
2022-04-26 10:41:16 +00:00
|
|
|
std::vector<CDVendorComponent> vendorComps = vendorComponentTable->Query([=](CDVendorComponent entry) { return (entry.id == componentID); });
|
|
|
|
if (vendorComps.empty()) return;
|
|
|
|
m_BuyScalar = vendorComps[0].buyScalar;
|
|
|
|
m_SellScalar = vendorComps[0].sellScalar;
|
|
|
|
m_RefreshTimeSeconds = vendorComps[0].refreshTimeSeconds;
|
|
|
|
m_LootMatrixID = vendorComps[0].LootMatrixIndex;
|
|
|
|
}
|
2023-06-03 07:40:46 +00:00
|
|
|
|
2023-06-23 05:56:25 +00:00
|
|
|
|