2021-12-05 17:54:36 +00:00
# include "VendorComponent.h"
2023-08-03 10:51:52 +00:00
# include "BitStream.h"
2022-04-26 10:41:16 +00:00
# include "dServer.h"
2023-08-03 10:51:52 +00:00
# include "dZoneManager.h"
# include "WorldConfig.h"
2023-03-17 14:36:21 +00:00
# include "CDComponentsRegistryTable.h"
# include "CDVendorComponentTable.h"
# include "CDLootMatrixTable.h"
# include "CDLootTableTable.h"
2023-08-03 10:51:52 +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-08-03 10:51:52 +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
}
2023-08-10 21:33:15 +00:00
void VendorComponent : : Serialize ( RakNet : : BitStream * outBitStream , bool bIsInitialUpdate ) {
2023-08-03 10:51:52 +00:00
outBitStream - > Write ( bIsInitialUpdate | | m_DirtyVendor ) ;
if ( bIsInitialUpdate | | m_DirtyVendor ) {
outBitStream - > Write ( m_HasStandardCostItems ) ;
outBitStream - > Write ( m_HasMultiCostItems ) ;
if ( ! bIsInitialUpdate ) m_DirtyVendor = false ;
}
2021-12-05 17:54:36 +00:00
}
void VendorComponent : : OnUse ( Entity * originator ) {
2022-04-26 10:41:16 +00:00
GameMessages : : SendVendorOpenWindow ( m_Parent , originator - > GetSystemAddress ( ) ) ;
GameMessages : : SendVendorStatusUpdate ( m_Parent , originator - > GetSystemAddress ( ) ) ;
2021-12-05 17:54:36 +00:00
}
2022-04-26 10:41:16 +00:00
void VendorComponent : : RefreshInventory ( bool isCreation ) {
2023-08-03 10:51:52 +00:00
SetHasStandardCostItems ( false ) ;
SetHasMultiCostItems ( false ) ;
m_Inventory . clear ( ) ;
// Custom code for Max vanity NPC and Mr.Ree cameras
if ( isCreation & & m_Parent - > GetLOT ( ) = = 9749 & & Game : : server - > GetZoneID ( ) = = 1201 ) {
SetupMaxCustomVendor ( ) ;
2022-04-26 10:41:16 +00:00
return ;
}
2023-08-03 10:51:52 +00:00
2023-03-17 14:36:21 +00:00
auto * lootMatrixTable = CDClientManager : : Instance ( ) . GetTable < CDLootMatrixTable > ( ) ;
2023-10-09 20:33:22 +00:00
const auto & lootMatrices = lootMatrixTable - > GetMatrix ( m_LootMatrixID ) ;
2022-04-26 10:41:16 +00:00
if ( lootMatrices . empty ( ) ) return ;
2023-03-17 14:36:21 +00:00
auto * lootTableTable = CDClientManager : : Instance ( ) . GetTable < CDLootTableTable > ( ) ;
2023-08-03 10:51:52 +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 ) {
2023-10-09 20:33:22 +00:00
auto vendorItems = lootTableTable - > GetTable ( lootMatrix . LootTableIndex ) ;
2022-04-26 10:41:16 +00:00
if ( lootMatrix . maxToDrop = = 0 | | lootMatrix . minToDrop = = 0 ) {
2023-08-03 10:51:52 +00:00
for ( const auto & item : vendorItems ) {
if ( ! m_HasStandardCostItems | | ! m_HasMultiCostItems ) {
auto itemComponentID = compRegistryTable - > GetByIDAndType ( item . itemid , eReplicaComponentType : : ITEM , - 1 ) ;
if ( itemComponentID = = - 1 ) {
Game : : logger - > Log ( " VendorComponent " , " Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item! " , itemComponentID , m_Parent - > GetLOT ( ) ) ;
continue ;
}
auto itemComponent = itemComponentTable - > GetItemComponentByID ( itemComponentID ) ;
if ( ! m_HasStandardCostItems & & itemComponent . baseValue ! = - 1 ) SetHasStandardCostItems ( true ) ;
if ( ! m_HasMultiCostItems & & ! itemComponent . currencyCosts . empty ( ) ) SetHasMultiCostItems ( true ) ;
}
m_Inventory . push_back ( SoldItem ( item . itemid , item . sortPriority ) ) ;
2022-04-26 10:41:16 +00:00
}
} 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 ) ;
2023-08-03 10:51:52 +00:00
const auto & randomItem = vendorItems . at ( randomItemIndex ) ;
2022-04-26 10:41:16 +00:00
vendorItems . erase ( vendorItems . begin ( ) + randomItemIndex ) ;
2023-08-03 10:51:52 +00:00
if ( ! m_HasStandardCostItems | | ! m_HasMultiCostItems ) {
auto itemComponentID = compRegistryTable - > GetByIDAndType ( randomItem . itemid , eReplicaComponentType : : ITEM , - 1 ) ;
if ( itemComponentID = = - 1 ) {
Game : : logger - > Log ( " VendorComponent " , " Attempted to add item %i with ItemComponent ID -1 to vendor %i inventory. Not adding item! " , itemComponentID , m_Parent - > GetLOT ( ) ) ;
continue ;
}
auto itemComponent = itemComponentTable - > GetItemComponentByID ( itemComponentID ) ;
if ( ! m_HasStandardCostItems & & itemComponent . baseValue ! = - 1 ) SetHasStandardCostItems ( true ) ;
if ( ! m_HasMultiCostItems & & ! itemComponent . currencyCosts . empty ( ) ) SetHasMultiCostItems ( true ) ;
}
m_Inventory . push_back ( SoldItem ( randomItem . itemid , randomItem . sortPriority ) ) ;
2022-04-26 10:41:16 +00:00
}
}
}
2023-08-03 10:51:52 +00:00
HandleMrReeCameras ( ) ;
2022-04-26 10:41:16 +00:00
// Callback timer to refresh this inventory.
2023-08-03 10:51:52 +00:00
if ( m_RefreshTimeSeconds > 0.0 ) {
m_Parent - > AddCallbackTimer ( m_RefreshTimeSeconds , [ this ] ( ) {
RefreshInventory ( ) ;
2022-07-28 13:39:57 +00:00
} ) ;
2023-08-03 10:51:52 +00:00
}
Game : : entityManager - > SerializeEntity ( m_Parent ) ;
2022-04-27 08:35:46 +00:00
GameMessages : : SendVendorStatusUpdate ( m_Parent , 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-03-04 07:16:37 +00:00
int componentID = compRegistryTable - > GetByIDAndType ( m_Parent - > 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 ;
2023-08-03 10:51:52 +00:00
auto vendorData = vendorComps . at ( 0 ) ;
if ( vendorData . buyScalar = = 0.0 ) m_BuyScalar = Game : : zoneManager - > GetWorldConfig ( ) - > vendorBuyMultiplier ;
else m_BuyScalar = vendorData . buyScalar ;
m_SellScalar = vendorData . sellScalar ;
m_RefreshTimeSeconds = vendorData . refreshTimeSeconds ;
m_LootMatrixID = vendorData . LootMatrixIndex ;
2022-07-28 13:39:57 +00:00
}
2023-06-03 07:40:46 +00:00
bool VendorComponent : : SellsItem ( const LOT item ) const {
2023-08-03 10:51:52 +00:00
return std : : count_if ( m_Inventory . begin ( ) , m_Inventory . end ( ) , [ item ] ( const SoldItem & lhs ) {
return lhs . lot = = item ;
} ) > 0 ;
}
void VendorComponent : : SetupMaxCustomVendor ( ) {
SetHasStandardCostItems ( true ) ;
m_Inventory . push_back ( SoldItem ( 11909 , 0 ) ) ; // Top hat w frog
m_Inventory . push_back ( SoldItem ( 7785 , 0 ) ) ; // Flash bulb
m_Inventory . push_back ( SoldItem ( 12764 , 0 ) ) ; // Big fountain soda
m_Inventory . push_back ( SoldItem ( 12241 , 0 ) ) ; // Hot cocoa (from fb)
}
void VendorComponent : : HandleMrReeCameras ( ) {
if ( m_Parent - > GetLOT ( ) = = 13569 ) {
SetHasStandardCostItems ( true ) ;
auto randomCamera = GeneralUtils : : GenerateRandomNumber < int32_t > ( 0 , 2 ) ;
LOT camera = 0 ;
DluAssert ( randomCamera > = 0 & & randomCamera < = 2 ) ;
switch ( randomCamera ) {
case 0 :
camera = 16253 ; // Grungagroid
break ;
case 1 :
camera = 16254 ; // Hipstabrick
break ;
case 2 :
camera = 16204 ; // Megabrixel snapshot
break ;
}
m_Inventory . push_back ( SoldItem ( camera , 0 ) ) ;
}
2023-06-03 07:40:46 +00:00
}