2018-03-29 17:01:57 -04:00
# include "StdAfx.h"
# include "Container.h"
# include "World.h"
# include "ObjectMsgs.h"
# include "ChatMsgs.h"
# include "Player.h"
# include "WeenieFactory.h"
# include "WorldLandBlock.h"
# include "Config.h"
CContainerWeenie : : CContainerWeenie ( )
{
for ( DWORD i = 0 ; i < MAX_WIELDED_COMBAT ; i + + )
2018-06-21 23:32:21 +01:00
m_WieldedCombat [ i ] = std : : shared_ptr < CWeenieObject > ( ) ;
2018-03-29 17:01:57 -04:00
}
CContainerWeenie : : ~ CContainerWeenie ( )
{
for ( DWORD i = 0 ; i < MAX_WIELDED_COMBAT ; i + + )
2018-06-21 23:32:21 +01:00
m_WieldedCombat [ i ] = std : : shared_ptr < CWeenieObject > ( ) ;
2018-03-29 17:01:57 -04:00
for ( auto item : m_Wielded )
{
2018-06-21 23:32:21 +01:00
g_pWorld - > RemoveEntity ( item . lock ( ) ) ;
2018-03-29 17:01:57 -04:00
}
m_Wielded . clear ( ) ;
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
g_pWorld - > RemoveEntity ( item . lock ( ) ) ;
2018-03-29 17:01:57 -04:00
}
m_Items . clear ( ) ;
for ( auto container : m_Packs )
{
2018-06-21 23:32:21 +01:00
g_pWorld - > RemoveEntity ( container . lock ( ) ) ;
2018-03-29 17:01:57 -04:00
}
m_Packs . clear ( ) ;
}
void CContainerWeenie : : ApplyQualityOverrides ( )
{
CWeenieObject : : ApplyQualityOverrides ( ) ;
if ( m_Qualities . GetInt ( ITEM_TYPE_INT , 0 ) & TYPE_CONTAINER )
{
if ( GetItemsCapacity ( ) < 0 )
{
m_Qualities . SetInt ( ITEMS_CAPACITY_INT , 120 ) ;
}
if ( GetContainersCapacity ( ) < 0 )
{
m_Qualities . SetInt ( CONTAINERS_CAPACITY_INT , 10 ) ;
}
}
}
void CContainerWeenie : : PostSpawn ( )
{
CWeenieObject : : PostSpawn ( ) ;
m_bInitiallyLocked = IsLocked ( ) ;
}
int CContainerWeenie : : GetItemsCapacity ( )
{
return InqIntQuality ( ITEMS_CAPACITY_INT , 0 ) ;
}
int CContainerWeenie : : GetContainersCapacity ( )
{
return InqIntQuality ( CONTAINERS_CAPACITY_INT , 0 ) ;
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CContainerWeenie > CContainerWeenie : : FindContainer ( DWORD container_id )
2018-03-29 17:01:57 -04:00
{
if ( GetID ( ) = = container_id )
2018-05-23 13:45:22 +01:00
return AsContainer ( ) ;
2018-03-29 17:01:57 -04:00
for ( auto pack : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pPack = pack . lock ( ) ;
if ( pPack & & pPack - > GetID ( ) = = container_id )
2018-03-29 17:01:57 -04:00
{
2018-06-21 23:32:21 +01:00
if ( std : : shared_ptr < CContainerWeenie > packContainer = pPack - > AsContainer ( ) )
2018-03-29 17:01:57 -04:00
{
return packContainer ;
}
}
}
2018-05-23 13:45:22 +01:00
if ( std : : shared_ptr < CWeenieObject > externalObject = g_pWorld - > FindObject ( container_id ) )
2018-03-29 17:01:57 -04:00
{
2018-05-23 13:45:22 +01:00
if ( std : : shared_ptr < CContainerWeenie > externalContainer = externalObject - > AsContainer ( ) )
2018-03-29 17:01:57 -04:00
{
if ( externalContainer - > _openedById = = GetTopLevelID ( ) )
{
return externalContainer ;
}
}
}
return NULL ;
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : GetWieldedCombat ( COMBAT_USE combatUse )
2018-03-29 17:01:57 -04:00
{
// The first entry is "Undef" so we omit that.
int index = combatUse - 1 ;
if ( index < 0 | | index > = MAX_WIELDED_COMBAT )
return NULL ;
2018-06-21 23:32:21 +01:00
return m_WieldedCombat [ index ] . lock ( ) ;
2018-03-29 17:01:57 -04:00
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : SetWieldedCombat ( std : : shared_ptr < CWeenieObject > wielded , COMBAT_USE combatUse )
2018-03-29 17:01:57 -04:00
{
// The first entry is "Undef" so we omit that.
int index = combatUse - 1 ;
if ( index < 0 | | index > = MAX_WIELDED_COMBAT )
return ;
m_WieldedCombat [ index ] = wielded ;
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : GetWieldedMelee ( )
2018-03-29 17:01:57 -04:00
{
return GetWieldedCombat ( COMBAT_USE_MELEE ) ;
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : GetWieldedMissile ( )
2018-03-29 17:01:57 -04:00
{
return GetWieldedCombat ( COMBAT_USE_MISSILE ) ;
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : GetWieldedAmmo ( )
2018-03-29 17:01:57 -04:00
{
return GetWieldedCombat ( COMBAT_USE_AMMO ) ;
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : GetWieldedShield ( )
2018-03-29 17:01:57 -04:00
{
return GetWieldedCombat ( COMBAT_USE_SHIELD ) ;
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : GetWieldedTwoHanded ( )
2018-03-29 17:01:57 -04:00
{
return GetWieldedCombat ( COMBAT_USE_TWO_HANDED ) ;
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : GetWieldedCaster ( )
2018-03-29 17:01:57 -04:00
{
for ( auto item : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( pItem & & pItem - > AsCaster ( ) )
return pItem ;
2018-03-29 17:01:57 -04:00
}
return NULL ;
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : Container_GetWieldedByMask ( std : : list < std : : shared_ptr < CWeenieObject > > & wielded , DWORD inv_loc_mask )
2018-03-29 17:01:57 -04:00
{
for ( auto item : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( pItem & & pItem - > InqIntQuality ( CURRENT_WIELDED_LOCATION_INT , 0 , TRUE ) & inv_loc_mask )
wielded . push_back ( pItem ) ;
2018-03-29 17:01:57 -04:00
}
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : GetWielded ( INVENTORY_LOC slot )
2018-03-29 17:01:57 -04:00
{
for ( auto item : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( pItem & & pItem - > InqIntQuality ( CURRENT_WIELDED_LOCATION_INT , 0 , TRUE ) = = slot )
return pItem ;
2018-03-29 17:01:57 -04:00
}
return NULL ;
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : ReleaseContainedItemRecursive ( std : : shared_ptr < CWeenieObject > item )
2018-03-29 17:01:57 -04:00
{
if ( ! item )
return ;
for ( DWORD i = 0 ; i < MAX_WIELDED_COMBAT ; i + + )
{
2018-06-21 23:32:21 +01:00
if ( item = = m_WieldedCombat [ i ] . lock ( ) )
m_WieldedCombat [ i ] = std : : shared_ptr < CWeenieObject > ( ) ;
2018-03-29 17:01:57 -04:00
}
2018-06-21 23:32:21 +01:00
for ( std : : vector < std : : weak_ptr < CWeenieObject > > : : iterator equipmentIterator = m_Wielded . begin ( ) ; equipmentIterator ! = m_Wielded . end ( ) ; )
2018-03-29 17:01:57 -04:00
{
2018-06-21 23:32:21 +01:00
if ( equipmentIterator - > lock ( ) ! = item )
2018-03-29 17:01:57 -04:00
{
equipmentIterator + + ;
continue ;
}
equipmentIterator = m_Wielded . erase ( equipmentIterator ) ;
}
2018-06-21 23:32:21 +01:00
for ( std : : vector < std : : weak_ptr < CWeenieObject > > : : iterator itemIterator = m_Items . begin ( ) ; itemIterator ! = m_Items . end ( ) ; )
2018-03-29 17:01:57 -04:00
{
2018-06-21 23:32:21 +01:00
if ( itemIterator - > lock ( ) ! = item )
2018-03-29 17:01:57 -04:00
{
itemIterator + + ;
continue ;
}
itemIterator = m_Items . erase ( itemIterator ) ;
}
2018-06-21 23:32:21 +01:00
for ( std : : vector < std : : weak_ptr < CWeenieObject > > : : iterator packIterator = m_Packs . begin ( ) ; packIterator ! = m_Packs . end ( ) ; )
2018-03-29 17:01:57 -04:00
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pack = packIterator - > lock ( ) ;
2018-03-29 17:01:57 -04:00
if ( pack ! = item )
{
pack - > ReleaseContainedItemRecursive ( item ) ;
packIterator + + ;
continue ;
}
packIterator = m_Packs . erase ( packIterator ) ;
}
if ( item - > GetContainerID ( ) = = GetID ( ) )
{
item - > m_Qualities . SetInstanceID ( CONTAINER_IID , 0 ) ;
}
if ( item - > GetWielderID ( ) = = GetID ( ) )
{
item - > m_Qualities . SetInstanceID ( WIELDER_IID , 0 ) ;
}
item - > RecacheHasOwner ( ) ;
}
2018-05-23 13:45:22 +01:00
BOOL CContainerWeenie : : Container_CanEquip ( std : : shared_ptr < CWeenieObject > item , DWORD location )
2018-03-29 17:01:57 -04:00
{
if ( ! item )
return FALSE ;
if ( ! item - > IsValidWieldLocation ( location ) )
return FALSE ;
for ( auto wielded : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pWielded = wielded . lock ( ) ;
if ( pWielded = = item )
2018-03-29 17:01:57 -04:00
return TRUE ;
2018-06-21 23:32:21 +01:00
if ( pWielded & & ! pWielded - > CanEquipWith ( item , location ) )
2018-03-29 17:01:57 -04:00
return FALSE ;
}
return TRUE ;
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : Container_EquipItem ( DWORD dwCell , std : : shared_ptr < CWeenieObject > item , DWORD inv_loc , DWORD child_location , DWORD placement )
2018-03-29 17:01:57 -04:00
{
if ( int combatUse = item - > InqIntQuality ( COMBAT_USE_INT , 0 , TRUE ) )
SetWieldedCombat ( item , ( COMBAT_USE ) combatUse ) ;
bool bAlreadyEquipped = false ;
for ( auto entry : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pWielded = entry . lock ( ) ;
if ( pWielded = = item )
2018-03-29 17:01:57 -04:00
{
bAlreadyEquipped = true ;
break ;
}
}
if ( ! bAlreadyEquipped )
{
m_Wielded . push_back ( item ) ;
}
if ( child_location & & placement )
{
item - > m_Qualities . SetInt ( PARENT_LOCATION_INT , child_location ) ;
2018-05-24 22:28:15 +01:00
item - > set_parent ( GetPointer < CWeenieObject > ( ) , child_location ) ;
2018-03-29 17:01:57 -04:00
item - > SetPlacementFrame ( placement , FALSE ) ;
if ( m_bWorldIsAware )
{
2018-05-23 13:45:22 +01:00
if ( std : : shared_ptr < CWeenieObject > owner = GetWorldTopLevelOwner ( ) )
2018-03-29 17:01:57 -04:00
{
if ( owner - > GetBlock ( ) )
{
owner - > GetBlock ( ) - > ExchangePVS ( item , 0 ) ;
}
}
/*
BinaryWriter * writer = item - > CreateMessage ( ) ;
g_pWorld - > BroadcastPVS ( dwCell , writer - > GetData ( ) , writer - > GetSize ( ) , OBJECT_MSG , 0 , FALSE ) ;
delete writer ;
*/
BinaryWriter Blah ;
Blah . Write < DWORD > ( 0xF749 ) ;
Blah . Write < DWORD > ( GetID ( ) ) ;
Blah . Write < DWORD > ( item - > GetID ( ) ) ;
Blah . Write < DWORD > ( child_location ) ;
Blah . Write < DWORD > ( placement ) ;
Blah . Write < WORD > ( GetPhysicsObj ( ) - > _instance_timestamp ) ;
Blah . Write < WORD > ( + + item - > _position_timestamp ) ;
g_pWorld - > BroadcastPVS ( dwCell , Blah . GetData ( ) , Blah . GetSize ( ) ) ;
}
}
else
{
if ( m_bWorldIsAware )
{
item - > _position_timestamp + + ;
BinaryWriter Blah ;
Blah . Write < DWORD > ( 0xF74A ) ;
Blah . Write < DWORD > ( item - > GetID ( ) ) ;
Blah . Write < WORD > ( item - > _instance_timestamp ) ;
Blah . Write < WORD > ( item - > _position_timestamp ) ;
g_pWorld - > BroadcastPVS ( dwCell , Blah . GetData ( ) , Blah . GetSize ( ) ) ;
}
}
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : FindContainedItem ( DWORD object_id )
2018-03-29 17:01:57 -04:00
{
for ( auto item : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( pItem & & pItem - > GetID ( ) = = object_id )
return pItem ;
2018-03-29 17:01:57 -04:00
}
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( pItem & & pItem - > GetID ( ) = = object_id )
return pItem ;
2018-03-29 17:01:57 -04:00
}
for ( auto item : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
if ( pItem - > GetID ( ) = = object_id )
return pItem ;
2018-03-29 17:01:57 -04:00
2018-06-21 23:32:21 +01:00
if ( auto subitem = pItem - > FindContainedItem ( object_id ) )
2018-03-29 17:01:57 -04:00
return subitem ;
}
return NULL ;
}
DWORD CContainerWeenie : : Container_GetNumFreeMainPackSlots ( )
{
return ( DWORD ) max ( 0 , GetItemsCapacity ( ) - ( signed ) m_Items . size ( ) ) ;
}
2018-05-23 13:45:22 +01:00
BOOL CContainerWeenie : : Container_CanStore ( std : : shared_ptr < CWeenieObject > pItem )
2018-03-29 17:01:57 -04:00
{
return Container_CanStore ( pItem , pItem - > RequiresPackSlot ( ) ) ;
}
BOOL CContainerWeenie : : IsItemsCapacityFull ( )
{
int capacity = GetItemsCapacity ( ) ;
if ( capacity > = 0 )
{
if ( m_Items . size ( ) < capacity )
return TRUE ;
return FALSE ;
}
return TRUE ;
}
BOOL CContainerWeenie : : IsContainersCapacityFull ( )
{
int capacity = GetContainersCapacity ( ) ;
if ( capacity > = 0 )
{
if ( m_Packs . size ( ) < capacity )
return TRUE ;
return FALSE ;
}
return TRUE ;
}
2018-05-23 13:45:22 +01:00
BOOL CContainerWeenie : : Container_CanStore ( std : : shared_ptr < CWeenieObject > pItem , bool bPackSlot )
2018-03-29 17:01:57 -04:00
{
// TODO handle: pItem->InqBoolQuality(REQUIRES_BACKPACK_SLOT_BOOL, FALSE)
if ( bPackSlot )
{
if ( ! pItem - > RequiresPackSlot ( ) )
return FALSE ;
int capacity = GetContainersCapacity ( ) ;
if ( capacity > = 0 )
{
if ( m_Packs . size ( ) < capacity )
return TRUE ;
for ( auto container : m_Packs )
{
2018-06-21 23:32:21 +01:00
if ( container . lock ( ) = = pItem )
2018-03-29 17:01:57 -04:00
return TRUE ;
}
return FALSE ;
}
else
{
if ( InqBoolQuality ( AI_ACCEPT_EVERYTHING_BOOL , FALSE ) )
return TRUE ;
// check emote item acceptance here
return FALSE ;
}
}
else
{
if ( pItem - > RequiresPackSlot ( ) )
return FALSE ;
int capacity = GetItemsCapacity ( ) ;
if ( capacity > = 0 )
{
if ( m_Items . size ( ) < capacity )
return TRUE ;
for ( auto container : m_Items )
{
2018-06-21 23:32:21 +01:00
if ( container . lock ( ) = = pItem )
2018-03-29 17:01:57 -04:00
return TRUE ;
}
return FALSE ;
}
else
{
if ( InqBoolQuality ( AI_ACCEPT_EVERYTHING_BOOL , FALSE ) )
return TRUE ;
// check emote item acceptance here
if ( m_Qualities . _emote_table )
{
PackableList < EmoteSet > * emoteCategory = m_Qualities . _emote_table - > _emote_table . lookup ( Give_EmoteCategory ) ;
if ( emoteCategory )
{
for ( auto & emoteSet : * emoteCategory )
{
if ( emoteSet . classID = = pItem - > m_Qualities . id )
{
return TRUE ;
}
}
}
}
return FALSE ;
}
}
}
void CContainerWeenie : : Container_DeleteItem ( DWORD item_id )
{
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > item = FindContainedItem ( item_id ) ;
2018-03-29 17:01:57 -04:00
if ( ! item )
return ;
bool bWielded = item - > IsWielded ( ) ? true : false ;
// take it out of whatever slot it is in
ReleaseContainedItemRecursive ( item ) ;
item - > SetWeenieContainer ( 0 ) ;
item - > SetWielderID ( 0 ) ;
item - > SetWieldedLocation ( INVENTORY_LOC : : NONE_LOC ) ;
if ( bWielded & & item - > AsClothing ( ) )
{
UpdateModel ( ) ;
}
DWORD RemoveObject [ 3 ] ;
RemoveObject [ 0 ] = 0xF747 ;
RemoveObject [ 1 ] = item - > GetID ( ) ;
RemoveObject [ 2 ] = item - > _instance_timestamp ;
2018-05-24 22:28:15 +01:00
g_pWorld - > BroadcastPVS ( GetPointer < CWeenieObject > ( ) , RemoveObject , sizeof ( RemoveObject ) ) ;
2018-03-29 17:01:57 -04:00
g_pWorld - > RemoveEntity ( item ) ;
}
2018-05-23 13:45:22 +01:00
DWORD CContainerWeenie : : Container_InsertInventoryItem ( DWORD dwCell , std : : shared_ptr < CWeenieObject > item , DWORD slot )
2018-03-29 17:01:57 -04:00
{
// You should check if the inventory is full before calling this.
if ( ! item - > RequiresPackSlot ( ) )
{
if ( slot > ( DWORD ) m_Items . size ( ) )
slot = ( DWORD ) m_Items . size ( ) ;
m_Items . insert ( m_Items . begin ( ) + slot , item ) ;
}
else
{
if ( slot > ( DWORD ) m_Packs . size ( ) )
slot = ( DWORD ) m_Packs . size ( ) ;
m_Packs . insert ( m_Packs . begin ( ) + slot , item ) ;
}
if ( dwCell & & m_bWorldIsAware )
{
item - > _position_timestamp + + ;
BinaryWriter Blah ;
Blah . Write < DWORD > ( 0xF74A ) ;
Blah . Write < DWORD > ( item - > GetID ( ) ) ;
Blah . Write < WORD > ( item - > _instance_timestamp ) ;
Blah . Write < WORD > ( item - > _position_timestamp ) ;
g_pWorld - > BroadcastPVS ( dwCell , Blah . GetData ( ) , Blah . GetSize ( ) ) ;
}
item - > m_Qualities . SetInt ( PARENT_LOCATION_INT , 0 ) ;
item - > unset_parent ( ) ;
item - > leave_world ( ) ;
RecalculateEncumbrance ( ) ;
return slot ;
}
bool CContainerWeenie : : SpawnTreasureInContainer ( eTreasureCategory category , int tier , int workmanship )
{
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > treasure = g_pTreasureFactory - > GenerateTreasure ( tier , category ) ;
2018-03-29 17:01:57 -04:00
if ( ! treasure )
return false ;
if ( workmanship > 0 )
{
workmanship = min ( max ( workmanship , 1 ) , 10 ) ;
treasure - > m_Qualities . SetInt ( ITEM_WORKMANSHIP_INT , workmanship ) ;
}
else if ( workmanship = = 0 )
treasure - > m_Qualities . RemoveInt ( ITEM_WORKMANSHIP_INT ) ;
return SpawnInContainer ( treasure ) ;
}
bool CContainerWeenie : : SpawnInContainer ( DWORD wcid , int amount , int ptid , float shade , bool sendEnvent )
{
if ( amount < 1 )
return false ;
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > item = g_pWeenieFactory - > CreateWeenieByClassID ( wcid , NULL , false ) ;
2018-03-29 17:01:57 -04:00
if ( ! item )
return false ;
if ( ptid )
item - > m_Qualities . SetInt ( PALETTE_TEMPLATE_INT , ptid ) ;
if ( shade > 0.0 )
item - > m_Qualities . SetFloat ( SHADE_FLOAT , shade ) ;
int maxStackSize = item - > m_Qualities . GetInt ( MAX_STACK_SIZE_INT , 1 ) ;
if ( maxStackSize > 1 )
{
//If we're stackable, first let's try stacking to existing items.
for ( auto possibleMatch : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pPossibleMatch = possibleMatch . lock ( ) ;
if ( item - > m_Qualities . id ! = pPossibleMatch - > m_Qualities . id )
2018-03-29 17:01:57 -04:00
continue ;
2018-06-21 23:32:21 +01:00
if ( ptid ! = 0 & & pPossibleMatch - > InqIntQuality ( PALETTE_TEMPLATE_INT , 0 ) ! = ptid )
2018-03-29 17:01:57 -04:00
continue ;
2018-06-21 23:32:21 +01:00
if ( shade > = 0.0 & & pPossibleMatch - > InqFloatQuality ( SHADE_FLOAT , 0 ) ! = shade )
2018-03-29 17:01:57 -04:00
continue ;
2018-06-21 23:32:21 +01:00
int possibleMatchStackSize = pPossibleMatch - > InqIntQuality ( STACK_SIZE_INT , 1 ) ;
2018-03-29 17:01:57 -04:00
if ( possibleMatchStackSize < maxStackSize )
{
//we have room.
int roomFor = maxStackSize - possibleMatchStackSize ;
if ( roomFor > = amount )
{
//room for everything!
2018-06-21 23:32:21 +01:00
pPossibleMatch - > SetStackSize ( possibleMatchStackSize + amount ) ;
2018-03-29 17:01:57 -04:00
return true ;
}
else
{
//room for some.
amount - = roomFor ;
2018-06-21 23:32:21 +01:00
pPossibleMatch - > SetStackSize ( maxStackSize ) ;
2018-03-29 17:01:57 -04:00
}
}
}
}
//We're done stacking and we still have enough for a new item.
DWORD totalSlotsRequired = 0 ;
if ( maxStackSize < 1 )
maxStackSize = 1 ;
totalSlotsRequired = amount / maxStackSize ;
if ( Container_GetNumFreeMainPackSlots ( ) < totalSlotsRequired )
return false ;
if ( amount > 1 )
{
int maxStackSize = item - > m_Qualities . GetInt ( MAX_STACK_SIZE_INT , 1 ) ;
if ( amount < = maxStackSize )
item - > SetStackSize ( amount ) ;
else
{
int amountOfStacks = amount / maxStackSize ;
int restStackSize = amount % maxStackSize ;
for ( int i = 0 ; i < amountOfStacks ; i + + )
SpawnInContainer ( wcid , maxStackSize , ptid , shade ) ;
if ( restStackSize > 0 )
item - > SetStackSize ( restStackSize ) ;
else
{
return true ;
}
}
}
SpawnInContainer ( item , sendEnvent ) ;
return true ;
}
2018-05-23 13:45:22 +01:00
bool CContainerWeenie : : SpawnCloneInContainer ( std : : shared_ptr < CWeenieObject > itemToClone , int amount , bool sendEnvent )
2018-03-29 17:01:57 -04:00
{
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > item = g_pWeenieFactory - > CloneWeenie ( itemToClone ) ;
2018-03-29 17:01:57 -04:00
if ( ! item )
return false ;
DWORD totalSlotsRequired = 0 ;
int maxStackSize = item - > InqIntQuality ( MAX_STACK_SIZE_INT , 1 ) ;
if ( maxStackSize < 1 )
maxStackSize = 1 ;
totalSlotsRequired = amount / maxStackSize ;
if ( Container_GetNumFreeMainPackSlots ( ) < totalSlotsRequired )
return false ;
if ( amount > 1 )
{
int maxStackSize = item - > m_Qualities . GetInt ( MAX_STACK_SIZE_INT , 1 ) ;
if ( amount < = maxStackSize )
item - > SetStackSize ( amount ) ;
else
{
int amountOfStacks = amount / maxStackSize ;
int restStackSize = amount % maxStackSize ;
for ( int i = 0 ; i < amountOfStacks ; i + + )
SpawnCloneInContainer ( itemToClone , maxStackSize , sendEnvent ) ;
if ( restStackSize > 0 )
item - > SetStackSize ( restStackSize ) ;
else
{
return true ;
}
}
}
else if ( item - > InqIntQuality ( STACK_SIZE_INT , 1 ) > 1 )
item - > SetStackSize ( 1 ) ;
if ( ! SpawnInContainer ( item , sendEnvent , false ) )
{
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > owner = this - > GetWorldTopLevelOwner ( ) ;
2018-03-29 17:01:57 -04:00
if ( owner )
{
item - > SetInitialPosition ( owner - > m_Position ) ;
if ( ! g_pWorld - > CreateEntity ( item ) )
{
return true ;
}
item - > _timeToRot = Timer : : cur_time + 300.0 ;
item - > _beganRot = false ;
item - > m_Qualities . SetFloat ( TIME_TO_ROT_FLOAT , item - > _timeToRot ) ;
}
else
{
return true ;
}
}
return true ;
}
2018-05-23 13:45:22 +01:00
bool CContainerWeenie : : SpawnInContainer ( std : : shared_ptr < CWeenieObject > item , bool sendEnvent , bool deleteItemOnFailure )
2018-03-29 17:01:57 -04:00
{
item - > SetID ( g_pWorld - > GenerateGUID ( eDynamicGUID ) ) ;
if ( ! Container_CanStore ( item ) )
{
if ( sendEnvent )
NotifyInventoryFailedEvent ( item - > GetID ( ) , WERROR_GIVE_NOT_ALLOWED ) ;
return false ;
}
if ( ! g_pWorld - > CreateEntity ( item ) )
{
if ( sendEnvent )
NotifyInventoryFailedEvent ( item - > GetID ( ) , WERROR_GIVE_NOT_ALLOWED ) ;
2018-05-23 13:45:22 +01:00
2018-03-29 17:01:57 -04:00
return false ;
}
if ( sendEnvent )
{
SendNetMessage ( InventoryMove ( item - > GetID ( ) , GetID ( ) , 0 , item - > RequiresPackSlot ( ) ? 1 : 0 ) , PRIVATE_MSG , TRUE ) ;
if ( item - > AsContainer ( ) )
2018-05-24 22:28:15 +01:00
item - > AsContainer ( ) - > MakeAwareViewContent ( GetPointer < CWeenieObject > ( ) ) ;
2018-03-29 17:01:57 -04:00
MakeAware ( item , true ) ;
if ( _openedById ! = 0 )
{
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > openedBy = g_pWorld - > FindObject ( _openedById ) ;
2018-03-29 17:01:57 -04:00
if ( openedBy )
{
openedBy - > SendNetMessage ( InventoryMove ( item - > GetID ( ) , GetID ( ) , 0 , item - > RequiresPackSlot ( ) ? 1 : 0 ) , PRIVATE_MSG , TRUE ) ;
if ( item - > AsContainer ( ) )
2018-05-24 22:28:15 +01:00
item - > AsContainer ( ) - > MakeAwareViewContent ( GetPointer < CWeenieObject > ( ) ) ;
2018-03-29 17:01:57 -04:00
openedBy - > MakeAware ( item , true ) ;
}
}
}
2018-05-24 22:28:15 +01:00
OnReceiveInventoryItem ( GetPointer < CWeenieObject > ( ) , item , 0 ) ;
2018-03-29 17:01:57 -04:00
return true ;
}
2018-05-23 13:45:22 +01:00
DWORD CContainerWeenie : : OnReceiveInventoryItem ( std : : shared_ptr < CWeenieObject > source , std : : shared_ptr < CWeenieObject > item , DWORD desired_slot )
2018-03-29 17:01:57 -04:00
{
2018-05-24 22:28:15 +01:00
if ( source ! = GetPointer < CWeenieObject > ( ) )
2018-03-29 17:01:57 -04:00
{
// By default, if we receive things just delete them... creatures can override this
g_pWorld - > RemoveEntity ( item ) ;
return 0 ;
}
else
{
// Unless the source is ourselves, that means the item is spawning.
item - > ReleaseFromAnyWeenieParent ( false , true ) ;
item - > SetWieldedLocation ( INVENTORY_LOC : : NONE_LOC ) ;
item - > SetWeenieContainer ( GetID ( ) ) ;
item - > ReleaseFromBlock ( ) ;
return Container_InsertInventoryItem ( 0 , item , desired_slot ) ;
}
}
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > CContainerWeenie : : FindContained ( DWORD object_id )
2018-03-29 17:01:57 -04:00
{
return FindContainedItem ( object_id ) ;
}
void CContainerWeenie : : InitPhysicsObj ( )
{
CWeenieObject : : InitPhysicsObj ( ) ;
2018-05-29 23:47:16 +01:00
if ( ! _phys_obj . lock ( ) )
2018-03-29 17:01:57 -04:00
return ;
for ( auto item : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
2018-03-29 17:01:57 -04:00
# ifdef _DEBUG
assert ( item - > GetWielderID ( ) = = GetID ( ) ) ;
# endif
2018-06-21 23:32:21 +01:00
int parentLocation = pItem - > InqIntQuality ( PARENT_LOCATION_INT , PARENT_ENUM : : PARENT_NONE ) ;
2018-03-29 17:01:57 -04:00
if ( parentLocation ! = PARENT_ENUM : : PARENT_NONE )
{
2018-06-21 23:32:21 +01:00
pItem - > set_parent ( GetPointer < CWeenieObject > ( ) , parentLocation ) ;
2018-03-29 17:01:57 -04:00
2018-06-21 23:32:21 +01:00
int placement = pItem - > InqIntQuality ( PLACEMENT_POSITION_INT , 0 ) ;
2018-03-29 17:01:57 -04:00
assert ( placement ) ;
2018-06-21 23:32:21 +01:00
pItem - > SetPlacementFrame ( placement , FALSE ) ;
2018-03-29 17:01:57 -04:00
}
}
# ifdef _DEBUG
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
assert ( pItem - > InqIntQuality ( PARENT_LOCATION_INT , PARENT_ENUM : : PARENT_NONE ) = = PARENT_ENUM : : PARENT_NONE ) ;
2018-03-29 17:01:57 -04:00
}
for ( auto pack : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pPack = pack . lock ( ) ;
if ( ! pPack )
{
continue ;
}
assert ( pPack - > InqIntQuality ( PARENT_LOCATION_INT , PARENT_ENUM : : PARENT_NONE ) = = PARENT_ENUM : : PARENT_NONE ) ;
2018-03-29 17:01:57 -04:00
}
# endif
}
void CContainerWeenie : : SaveEx ( class CWeenieSave & save )
{
CWeenieObject : : SaveEx ( save ) ;
for ( auto item : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
save . _equipment . push_back ( pItem - > GetID ( ) ) ;
pItem - > Save ( ) ;
2018-03-29 17:01:57 -04:00
}
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
save . _inventory . push_back ( pItem - > GetID ( ) ) ;
pItem - > Save ( ) ;
2018-03-29 17:01:57 -04:00
}
for ( auto item : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
save . _packs . push_back ( pItem - > GetID ( ) ) ;
pItem - > Save ( ) ;
2018-03-29 17:01:57 -04:00
}
}
void CContainerWeenie : : LoadEx ( class CWeenieSave & save )
{
CWeenieObject : : LoadEx ( save ) ;
for ( auto item : save . _equipment )
{
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > weenie = CWeenieObject : : Load ( item ) ;
2018-03-29 17:01:57 -04:00
if ( weenie )
{
if ( weenie - > RequiresPackSlot ( ) )
{
continue ;
}
assert ( weenie - > IsWielded ( ) ) ;
assert ( ! weenie - > IsContained ( ) ) ;
// make sure it has the right settings (shouldn't be necessary)
weenie - > SetWielderID ( GetID ( ) ) ;
weenie - > SetWeenieContainer ( 0 ) ;
weenie - > m_Qualities . RemovePosition ( INSTANTIATION_POSITION ) ;
weenie - > m_Qualities . RemovePosition ( LOCATION_POSITION ) ;
if ( g_pWorld - > CreateEntity ( weenie , false ) )
{
m_Wielded . push_back ( weenie ) ;
if ( int combatUse = weenie - > InqIntQuality ( COMBAT_USE_INT , 0 , TRUE ) )
SetWieldedCombat ( weenie , ( COMBAT_USE ) combatUse ) ;
assert ( weenie - > IsWielded ( ) ) ;
assert ( ! weenie - > IsContained ( ) ) ;
}
else
{
// remove any enchantments associated with this item that we failed to wield...
if ( m_Qualities . _enchantment_reg )
{
PackableListWithJson < DWORD > spells_to_remove ;
if ( m_Qualities . _enchantment_reg - > _add_list )
{
for ( const auto & entry : * m_Qualities . _enchantment_reg - > _add_list )
{
if ( entry . _caster = = item )
{
spells_to_remove . push_back ( entry . _id ) ;
}
}
}
if ( m_Qualities . _enchantment_reg - > _mult_list )
{
for ( const auto & entry : * m_Qualities . _enchantment_reg - > _mult_list )
{
if ( entry . _caster = = item )
{
spells_to_remove . push_back ( entry . _id ) ;
}
}
}
if ( m_Qualities . _enchantment_reg - > _cooldown_list )
{
for ( const auto & entry : * m_Qualities . _enchantment_reg - > _cooldown_list )
{
if ( entry . _caster = = item )
{
spells_to_remove . push_back ( entry . _id ) ;
}
}
}
if ( ! spells_to_remove . empty ( ) )
{
m_Qualities . _enchantment_reg - > RemoveEnchantments ( & spells_to_remove ) ;
}
}
}
}
}
for ( auto item : save . _inventory )
{
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > weenie = CWeenieObject : : Load ( item ) ;
2018-03-29 17:01:57 -04:00
if ( weenie )
{
DWORD correct_container_iid = weenie - > m_Qualities . GetIID ( CONTAINER_IID , 0 ) ;
if ( weenie - > RequiresPackSlot ( ) | | ( correct_container_iid & & correct_container_iid ! = GetID ( ) ) )
{
continue ;
}
assert ( ! weenie - > IsWielded ( ) ) ;
assert ( weenie - > IsContained ( ) ) ;
assert ( ! weenie - > InqIntQuality ( PARENT_LOCATION_INT , 0 ) ) ;
// make sure it has the right settings (shouldn't be necessary)
weenie - > SetWielderID ( 0 ) ;
weenie - > m_Qualities . SetInt ( PARENT_LOCATION_INT , 0 ) ;
weenie - > SetWeenieContainer ( GetID ( ) ) ;
weenie - > m_Qualities . RemovePosition ( INSTANTIATION_POSITION ) ;
weenie - > m_Qualities . RemovePosition ( LOCATION_POSITION ) ;
if ( g_pWorld - > CreateEntity ( weenie , false ) )
{
m_Items . push_back ( weenie ) ;
assert ( ! weenie - > IsWielded ( ) ) ;
assert ( weenie - > IsContained ( ) ) ;
}
}
}
for ( auto item : save . _packs )
{
2018-05-23 13:45:22 +01:00
std : : shared_ptr < CWeenieObject > weenie = CWeenieObject : : Load ( item ) ;
2018-03-29 17:01:57 -04:00
if ( weenie )
{
DWORD correct_container_iid = weenie - > m_Qualities . GetIID ( CONTAINER_IID , 0 ) ;
if ( ! weenie - > RequiresPackSlot ( ) | | ( correct_container_iid & & correct_container_iid ! = GetID ( ) ) )
{
continue ;
}
assert ( ! weenie - > IsWielded ( ) ) ;
assert ( weenie - > IsContained ( ) ) ;
assert ( ! weenie - > InqIntQuality ( PARENT_LOCATION_INT , 0 ) ) ;
// make sure it has the right settings (shouldn't be necessary)
weenie - > SetWielderID ( 0 ) ;
weenie - > m_Qualities . SetInt ( PARENT_LOCATION_INT , 0 ) ;
weenie - > SetWeenieContainer ( GetID ( ) ) ;
weenie - > m_Qualities . RemovePosition ( INSTANTIATION_POSITION ) ;
weenie - > m_Qualities . RemovePosition ( LOCATION_POSITION ) ;
if ( g_pWorld - > CreateEntity ( weenie , false ) )
{
m_Packs . push_back ( weenie ) ;
assert ( ! weenie - > IsWielded ( ) ) ;
assert ( weenie - > IsContained ( ) ) ;
}
}
}
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : MakeAwareViewContent ( std : : shared_ptr < CWeenieObject > other )
2018-03-29 17:01:57 -04:00
{
//start from the bottom of the tree so the packs have their fill bar correctly populated.
for ( auto pack : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pPack = pack . lock ( ) ;
if ( ! pPack )
{
continue ;
}
if ( pPack - > AsContainer ( ) )
pPack - > AsContainer ( ) - > MakeAwareViewContent ( other ) ;
other - > MakeAware ( pPack , true ) ;
2018-03-29 17:01:57 -04:00
}
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
other - > MakeAware ( pItem , true ) ;
2018-03-29 17:01:57 -04:00
}
PackableList < ContentProfile > inventoryList ;
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
2018-03-29 17:01:57 -04:00
ContentProfile prof ;
2018-06-21 23:32:21 +01:00
prof . m_iid = pItem - > GetID ( ) ;
2018-03-29 17:01:57 -04:00
prof . m_uContainerProperties = 0 ;
inventoryList . push_back ( prof ) ;
}
for ( auto pack : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pPack = pack . lock ( ) ;
if ( ! pPack )
{
continue ;
}
2018-03-29 17:01:57 -04:00
ContentProfile prof ;
2018-06-21 23:32:21 +01:00
prof . m_iid = pPack - > GetID ( ) ;
2018-03-29 17:01:57 -04:00
prof . m_uContainerProperties = 1 ; //todo: what about foci? Do they need a different value here?
inventoryList . push_back ( prof ) ;
}
BinaryWriter viewContent ;
viewContent . Write < DWORD > ( 0x196 ) ;
viewContent . Write < DWORD > ( GetID ( ) ) ;
inventoryList . Pack ( & viewContent ) ;
other - > SendNetMessage ( & viewContent , PRIVATE_MSG , TRUE , FALSE ) ;
}
bool CContainerWeenie : : IsGroundContainer ( )
{
if ( HasOwner ( ) )
return false ;
if ( ! InValidCell ( ) )
return false ;
return true ;
}
2018-05-23 13:45:22 +01:00
bool CContainerWeenie : : IsInOpenRange ( std : : shared_ptr < CWeenieObject > other )
2018-03-29 17:01:57 -04:00
{
if ( ! IsGroundContainer ( ) )
return false ;
if ( DistanceTo ( other , true ) > = InqFloatQuality ( USE_RADIUS_FLOAT , 1.0 ) )
return false ;
return true ;
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : OnContainerOpened ( std : : shared_ptr < CWeenieObject > other )
2018-03-29 17:01:57 -04:00
{
if ( other & & other - > _lastOpenedRemoteContainerId & & other - > _lastOpenedRemoteContainerId ! = GetID ( ) )
{
2018-05-23 13:45:22 +01:00
if ( std : : shared_ptr < CWeenieObject > otherContainerObj = g_pWorld - > FindObject ( other - > _lastOpenedRemoteContainerId ) )
2018-03-29 17:01:57 -04:00
{
2018-05-23 13:45:22 +01:00
if ( std : : shared_ptr < CContainerWeenie > otherContainer = otherContainerObj - > AsContainer ( ) )
2018-03-29 17:01:57 -04:00
{
if ( otherContainer - > _openedById = = other - > GetID ( ) )
otherContainer - > OnContainerClosed ( ) ;
}
}
}
MakeAwareViewContent ( other ) ;
_openedById = other - > GetID ( ) ;
other - > _lastOpenedRemoteContainerId = GetID ( ) ;
_failedPreviousCheckToClose = false ;
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : OnContainerClosed ( std : : shared_ptr < CWeenieObject > requestedBy )
2018-03-29 17:01:57 -04:00
{
if ( requestedBy )
{
BinaryWriter closeContent ;
closeContent . Write < DWORD > ( 0x52 ) ;
closeContent . Write < DWORD > ( GetID ( ) ) ;
requestedBy - > SendNetMessage ( & closeContent , PRIVATE_MSG , TRUE , FALSE ) ;
}
_openedById = 0 ;
if ( InqStringQuality ( QUEST_STRING , " " ) ! = " " )
ResetToInitialState ( ) ; //quest chests reset instantly
else if ( _nextReset < 0 )
{
if ( double resetInterval = InqFloatQuality ( RESET_INTERVAL_FLOAT , 0 ) )
_nextReset = Timer : : cur_time + ( resetInterval * g_pConfig - > RespawnTimeMultiplier ( ) ) ;
else if ( double regenInterval = InqFloatQuality ( REGENERATION_INTERVAL_FLOAT , 0 ) ) //if we don't have a reset interval, fall back to regen interval
_nextReset = Timer : : cur_time + ( regenInterval * g_pConfig - > RespawnTimeMultiplier ( ) ) ;
}
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : NotifyGeneratedPickedUp ( std : : shared_ptr < CWeenieObject > weenie )
2018-03-29 17:01:57 -04:00
{
//container contents do not regenerate individually. Instead once the container is closed we start a reset timer.
weenie - > m_Qualities . RemoveInstanceID ( GENERATOR_IID ) ;
}
void CContainerWeenie : : ResetToInitialState ( )
{
if ( _openedById )
OnContainerClosed ( ) ;
m_Qualities . RemoveInstanceID ( OWNER_IID ) ;
SetLocked ( m_bInitiallyLocked ? TRUE : FALSE ) ;
while ( ! m_Wielded . empty ( ) )
2018-06-21 23:32:21 +01:00
{
std : : shared_ptr < CWeenieObject > pItem = m_Wielded . begin ( ) - > lock ( ) ;
if ( ! pItem )
{
m_Wielded . erase ( m_Wielded . begin ( ) ) ;
continue ;
}
Container_DeleteItem ( pItem - > GetID ( ) ) ;
}
2018-03-29 17:01:57 -04:00
while ( ! m_Items . empty ( ) )
2018-06-21 23:32:21 +01:00
{
std : : shared_ptr < CWeenieObject > pItem = m_Items . begin ( ) - > lock ( ) ;
if ( ! pItem )
{
m_Items . erase ( m_Items . begin ( ) ) ;
continue ;
}
Container_DeleteItem ( pItem - > GetID ( ) ) ;
}
2018-03-29 17:01:57 -04:00
while ( ! m_Packs . empty ( ) )
2018-06-21 23:32:21 +01:00
{
std : : shared_ptr < CWeenieObject > pItem = m_Packs . begin ( ) - > lock ( ) ;
if ( ! pItem )
{
m_Packs . erase ( m_Packs . begin ( ) ) ;
continue ;
}
Container_DeleteItem ( pItem - > GetID ( ) ) ;
}
2018-03-29 17:01:57 -04:00
if ( m_Qualities . _generator_table )
{
if ( m_Qualities . _generator_registry | | m_Qualities . _generator_queue )
{
for ( auto & entry : m_Qualities . _generator_table - > _profile_list )
{
if ( entry . whereCreate & Contain_RegenLocationType )
{
if ( m_Qualities . _generator_registry )
{
for ( PackableHashTable < unsigned long , GeneratorRegistryNode > : : iterator i = m_Qualities . _generator_registry - > _registry . begin ( ) ; i ! = m_Qualities . _generator_registry - > _registry . end ( ) ; )
{
if ( entry . slot = = i - > second . slot )
i = m_Qualities . _generator_registry - > _registry . erase ( i ) ;
else
i + + ;
}
}
if ( m_Qualities . _generator_queue )
{
for ( auto i = m_Qualities . _generator_queue - > _queue . begin ( ) ; i ! = m_Qualities . _generator_queue - > _queue . end ( ) ; )
{
if ( entry . slot = = i - > slot )
i = m_Qualities . _generator_queue - > _queue . erase ( i ) ;
else
i + + ;
}
}
}
}
}
else
{
if ( m_Qualities . _generator_registry )
m_Qualities . _generator_registry - > _registry . clear ( ) ;
if ( m_Qualities . _generator_queue )
m_Qualities . _generator_queue - > _queue . clear ( ) ;
}
}
InitCreateGenerator ( ) ;
}
2018-05-23 13:45:22 +01:00
int CContainerWeenie : : DoUseResponse ( std : : shared_ptr < CWeenieObject > other )
2018-03-29 17:01:57 -04:00
{
if ( IsBusyOrInAction ( ) )
return WERROR_NONE ;
if ( ! ( GetItemType ( ) & ITEM_TYPE : : TYPE_CONTAINER ) )
return WERROR_NONE ;
if ( ! IsGroundContainer ( ) )
return WERROR_NONE ;
if ( ! IsInOpenRange ( other ) )
return WERROR_NONE ;
if ( IsLocked ( ) )
{
EmitSound ( Sound_OpenFailDueToLock , 1.0f ) ;
return WERROR_NONE ;
}
int openError = CheckOpenContainer ( other ) ;
if ( openError )
return WERROR_NONE ;
if ( _openedById )
{
if ( _openedById = = other - > GetID ( ) )
{
//this is actually a close container request.
OnContainerClosed ( other ) ;
return WERROR_NONE ;
}
else
return WERROR_CHEST_ALREADY_OPEN ;
}
std : : string questString ;
if ( m_Qualities . InqString ( QUEST_STRING , questString ) & & ! questString . empty ( ) )
{
if ( DWORD owner = InqIIDQuality ( OWNER_IID , 0 ) )
{
if ( owner ! = other - > GetID ( ) )
{
other - > SendText ( csprintf ( " This chest is claimed by the person who lockpicked it. " ) , LTT_DEFAULT ) ;
return WERROR_NONE ;
}
}
else
{
if ( other - > InqQuest ( questString . c_str ( ) ) )
{
int timeTilOkay = other - > InqTimeUntilOkayToComplete ( questString . c_str ( ) ) ;
if ( timeTilOkay > 0 )
{
int secs = timeTilOkay % 60 ;
timeTilOkay / = 60 ;
int mins = timeTilOkay % 60 ;
timeTilOkay / = 60 ;
int hours = timeTilOkay % 24 ;
timeTilOkay / = 24 ;
int days = timeTilOkay ;
other - > SendText ( csprintf ( " You cannot open this for another %dd %dh %dm %ds. " , days , hours , mins , secs ) , LTT_DEFAULT ) ;
}
return WERROR_CHEST_USED_TOO_RECENTLY ;
}
other - > StampQuest ( questString . c_str ( ) ) ;
}
}
OnContainerOpened ( other ) ;
return WERROR_NONE ;
}
void CContainerWeenie : : InventoryTick ( )
{
CWeenieObject : : InventoryTick ( ) ;
2018-06-21 23:32:21 +01:00
auto wielded = m_Wielded . begin ( ) ;
while ( wielded ! = m_Wielded . end ( ) )
2018-03-29 17:01:57 -04:00
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = wielded - > lock ( ) ;
if ( ! pItem )
{
m_Wielded . erase ( wielded ) ;
}
else
{
pItem - > WieldedTick ( ) ;
2018-03-29 17:01:57 -04:00
# ifdef _DEBUG
2018-06-21 23:32:21 +01:00
pItem - > DebugValidate ( ) ;
2018-03-29 17:01:57 -04:00
# endif
2018-06-21 23:32:21 +01:00
}
wielded + + ;
2018-03-29 17:01:57 -04:00
}
2018-06-21 23:32:21 +01:00
auto item = m_Items . begin ( ) ;
while ( item ! = m_Items . end ( ) )
2018-03-29 17:01:57 -04:00
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item - > lock ( ) ;
if ( ! pItem )
{
m_Items . erase ( wielded ) ;
}
else
{
pItem - > InventoryTick ( ) ;
2018-03-29 17:01:57 -04:00
# ifdef _DEBUG
2018-06-21 23:32:21 +01:00
pItem - > DebugValidate ( ) ;
2018-03-29 17:01:57 -04:00
# endif
2018-06-21 23:32:21 +01:00
}
item + + ;
2018-03-29 17:01:57 -04:00
}
2018-06-21 23:32:21 +01:00
auto pack = m_Packs . begin ( ) ;
while ( pack ! = m_Packs . end ( ) )
2018-03-29 17:01:57 -04:00
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = pack - > lock ( ) ;
if ( ! pItem )
{
m_Packs . erase ( wielded ) ;
}
else
{
pItem - > InventoryTick ( ) ;
2018-03-29 17:01:57 -04:00
# ifdef _DEBUG
2018-06-21 23:32:21 +01:00
pItem - > DebugValidate ( ) ;
2018-03-29 17:01:57 -04:00
# endif
2018-06-21 23:32:21 +01:00
}
pack + + ;
2018-03-29 17:01:57 -04:00
}
}
void CContainerWeenie : : Tick ( )
{
CWeenieObject : : Tick ( ) ;
if ( _openedById )
{
CheckToClose ( ) ;
}
if ( Timer : : cur_time < _nextInventoryTick )
{
return ;
}
2018-06-21 23:32:21 +01:00
// TODO mwnciau removed a lot of code here and replaced it with this. If problems occur...
InventoryTick ( ) ;
2018-03-29 17:01:57 -04:00
_nextInventoryTick = Timer : : cur_time + Random : : GenFloat ( 0.4 , 0.6 ) ;
}
void CContainerWeenie : : CheckToClose ( )
{
if ( _nextCheckToClose > Timer : : cur_time )
{
return ;
}
_nextCheckToClose = Timer : : cur_time + 1.0 ;
2018-05-23 13:45:22 +01:00
if ( std : : shared_ptr < CWeenieObject > other = g_pWorld - > FindObject ( _openedById ) )
2018-03-29 17:01:57 -04:00
{
if ( other - > IsDead ( ) | | ! IsInOpenRange ( other ) )
{
if ( _failedPreviousCheckToClose )
OnContainerClosed ( ) ;
else
{
_failedPreviousCheckToClose = true ; //give the client a moment to send the chest close message or we might interpret it as a open request(both use the use packet)
_nextCheckToClose = Timer : : cur_time + 2.0 ;
}
}
else
_failedPreviousCheckToClose = false ;
}
else
{
OnContainerClosed ( ) ;
}
}
2018-05-23 13:45:22 +01:00
int CContainerWeenie : : CheckOpenContainer ( std : : shared_ptr < CWeenieObject > other )
2018-03-29 17:01:57 -04:00
{
if ( _openedById )
{
if ( _openedById = = other - > GetID ( ) )
{
return WERROR_NONE ;
}
return WERROR_CHEST_ALREADY_OPEN ;
}
return WERROR_NONE ;
}
2018-05-23 13:45:22 +01:00
void CContainerWeenie : : HandleNoLongerViewing ( std : : shared_ptr < CWeenieObject > other )
2018-03-29 17:01:57 -04:00
{
if ( ! _openedById | | _openedById ! = other - > GetID ( ) )
return ;
OnContainerClosed ( ) ;
}
void CContainerWeenie : : DebugValidate ( )
{
CWeenieObject : : DebugValidate ( ) ;
# ifdef _DEBUG
assert ( ! GetWielderID ( ) ) ;
for ( auto wielded : m_Wielded )
{
assert ( wielded - > GetWielderID ( ) = = GetID ( ) ) ;
wielded - > DebugValidate ( ) ;
}
for ( auto item : m_Items )
{
assert ( item - > GetContainerID ( ) = = GetID ( ) ) ;
item - > DebugValidate ( ) ;
}
for ( auto pack : m_Packs )
{
assert ( pack - > GetContainerID ( ) = = GetID ( ) ) ;
pack - > DebugValidate ( ) ;
}
# endif
}
DWORD CContainerWeenie : : RecalculateCoinAmount ( )
{
int coinAmount = 0 ;
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
if ( pItem - > m_Qualities . id = = W_COINSTACK_CLASS )
coinAmount + = pItem - > InqIntQuality ( STACK_SIZE_INT , 1 , true ) ;
2018-03-29 17:01:57 -04:00
}
for ( auto pack : m_Packs )
2018-06-21 23:32:21 +01:00
{
std : : shared_ptr < CWeenieObject > pItem = pack . lock ( ) ;
if ( ! pItem )
{
continue ;
}
coinAmount + = pItem - > RecalculateCoinAmount ( ) ;
}
2018-03-29 17:01:57 -04:00
m_Qualities . SetInt ( COIN_VALUE_INT , coinAmount ) ;
NotifyIntStatUpdated ( COIN_VALUE_INT ) ;
return coinAmount ;
}
2018-04-15 02:21:51 -05:00
DWORD CContainerWeenie : : RecalculateAltCoinAmount ( int currencyid )
{
int coinAmount = 0 ;
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
if ( pItem - > m_Qualities . id = = currencyid )
coinAmount + = pItem - > InqIntQuality ( STACK_SIZE_INT , 1 , true ) ;
2018-04-15 02:21:51 -05:00
}
for ( auto pack : m_Packs )
2018-06-21 23:32:21 +01:00
{
std : : shared_ptr < CWeenieObject > pItem = pack . lock ( ) ;
if ( ! pItem )
{
continue ;
}
coinAmount + = pItem - > RecalculateAltCoinAmount ( currencyid ) ;
}
2018-04-15 02:21:51 -05:00
return coinAmount ;
}
2018-03-29 17:01:57 -04:00
DWORD CContainerWeenie : : ConsumeCoin ( int amountToConsume )
{
if ( amountToConsume < 1 )
return 0 ;
if ( AsPlayer ( ) ) //we don't need to recalculate this if we're a subcontainer
{
if ( RecalculateCoinAmount ( ) < amountToConsume ) //force recalculate our coin amount and check so we don't even try to consume if we don't have enough.
return 0 ;
}
2018-05-23 13:45:22 +01:00
std : : list < std : : shared_ptr < CWeenieObject > > removeList ;
2018-03-29 17:01:57 -04:00
DWORD amountConsumed = 0 ;
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
2018-03-29 17:01:57 -04:00
{
2018-06-21 23:32:21 +01:00
continue ;
}
if ( pItem - > m_Qualities . id = = W_COINSTACK_CLASS )
{
int stackSize = pItem - > InqIntQuality ( STACK_SIZE_INT , 1 , true ) ;
2018-03-29 17:01:57 -04:00
if ( stackSize < = amountToConsume )
{
2018-06-21 23:32:21 +01:00
removeList . push_back ( pItem ) ;
2018-03-29 17:01:57 -04:00
amountToConsume - = stackSize ;
amountConsumed + = stackSize ;
}
else
{
2018-06-21 23:32:21 +01:00
pItem - > SetStackSize ( stackSize - amountToConsume ) ;
2018-03-29 17:01:57 -04:00
amountConsumed + = amountToConsume ;
break ;
}
}
}
for ( auto item : removeList )
item - > Remove ( ) ;
if ( amountToConsume > 0 )
{
for ( auto pack : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = pack . lock ( ) ;
if ( ! pItem )
{
continue ;
}
DWORD amountFromPack = pItem - > ConsumeCoin ( amountToConsume ) ;
2018-03-29 17:01:57 -04:00
amountToConsume - = amountFromPack ;
amountConsumed + = amountFromPack ;
if ( amountToConsume < = 0 )
break ;
}
}
if ( AsPlayer ( ) )
RecalculateCoinAmount ( ) ;
return amountConsumed ;
}
2018-04-15 02:21:51 -05:00
DWORD CContainerWeenie : : ConsumeAltCoin ( int amountToConsume , int currencyid )
{
if ( amountToConsume < 1 )
return 0 ;
if ( AsPlayer ( ) ) //we don't need to recalculate this if we're a subcontainer
{
if ( RecalculateAltCoinAmount ( currencyid ) < amountToConsume ) //force recalculate our coin amount and check so we don't even try to consume if we don't have enough.
return 0 ;
}
2018-05-23 13:45:22 +01:00
std : : list < std : : shared_ptr < CWeenieObject > > removeList ;
2018-04-15 02:21:51 -05:00
DWORD amountConsumed = 0 ;
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
2018-04-15 02:21:51 -05:00
{
2018-06-21 23:32:21 +01:00
continue ;
}
if ( pItem - > m_Qualities . id = = currencyid )
{
int stackSize = pItem - > InqIntQuality ( STACK_SIZE_INT , 1 , true ) ;
2018-04-15 02:21:51 -05:00
if ( stackSize < = amountToConsume )
{
2018-06-21 23:32:21 +01:00
removeList . push_back ( pItem ) ;
2018-04-15 02:21:51 -05:00
amountToConsume - = stackSize ;
amountConsumed + = stackSize ;
}
else
{
2018-06-21 23:32:21 +01:00
pItem - > SetStackSize ( stackSize - amountToConsume ) ;
2018-04-15 02:21:51 -05:00
amountConsumed + = amountToConsume ;
break ;
}
}
}
for ( auto item : removeList )
item - > Remove ( ) ;
if ( amountToConsume > 0 )
{
for ( auto pack : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = pack . lock ( ) ;
if ( ! pItem )
{
continue ;
}
DWORD amountFromPack = pItem - > ConsumeAltCoin ( amountToConsume , currencyid ) ;
2018-04-15 02:21:51 -05:00
amountToConsume - = amountFromPack ;
amountConsumed + = amountFromPack ;
if ( amountToConsume < = 0 )
break ;
}
}
if ( AsPlayer ( ) )
RecalculateAltCoinAmount ( currencyid ) ;
return amountConsumed ;
}
2018-03-29 17:01:57 -04:00
void CContainerWeenie : : RecalculateEncumbrance ( )
{
int oldValue = InqIntQuality ( ENCUMB_VAL_INT , 0 ) ;
int newValue = 0 ;
for ( auto wielded : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = wielded . lock ( ) ;
if ( ! pItem )
{
continue ;
}
newValue + = pItem - > InqIntQuality ( ENCUMB_VAL_INT , 0 ) ;
2018-03-29 17:01:57 -04:00
}
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
newValue + = pItem - > InqIntQuality ( ENCUMB_VAL_INT , 0 ) ;
2018-03-29 17:01:57 -04:00
}
for ( auto pack : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = pack . lock ( ) ;
if ( ! pItem )
{
continue ;
}
pItem - > RecalculateEncumbrance ( ) ;
newValue + = pItem - > InqIntQuality ( ENCUMB_VAL_INT , 0 ) ;
2018-03-29 17:01:57 -04:00
}
if ( oldValue ! = newValue )
{
m_Qualities . SetInt ( ENCUMB_VAL_INT , newValue ) ;
NotifyIntStatUpdated ( ENCUMB_VAL_INT , true ) ;
}
}
bool CContainerWeenie : : IsAttunedOrContainsAttuned ( )
{
for ( auto wielded : m_Wielded )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = wielded . lock ( ) ;
if ( ! pItem )
{
continue ;
}
if ( pItem - > IsAttunedOrContainsAttuned ( ) )
2018-03-29 17:01:57 -04:00
return true ;
}
for ( auto item : m_Items )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = item . lock ( ) ;
if ( ! pItem )
{
continue ;
}
if ( pItem - > IsAttunedOrContainsAttuned ( ) )
2018-03-29 17:01:57 -04:00
return true ;
}
for ( auto pack : m_Packs )
{
2018-06-21 23:32:21 +01:00
std : : shared_ptr < CWeenieObject > pItem = pack . lock ( ) ;
if ( ! pItem )
{
continue ;
}
if ( pItem - > IsAttunedOrContainsAttuned ( ) )
2018-03-29 17:01:57 -04:00
return true ;
}
return CWeenieObject : : IsAttunedOrContainsAttuned ( ) ;
}
bool CContainerWeenie : : HasContainerContents ( )
{
if ( ! m_Wielded . empty ( ) | | ! m_Items . empty ( ) | | ! m_Packs . empty ( ) )
return true ;
return CWeenieObject : : HasContainerContents ( ) ;
}
void CContainerWeenie : : AdjustToNewCombatMode ( )
{
2018-05-23 13:45:22 +01:00
std : : list < std : : shared_ptr < CWeenieObject > > wielded ;
2018-03-29 17:01:57 -04:00
Container_GetWieldedByMask ( wielded , WEAPON_LOC | HELD_LOC ) ;
COMBAT_MODE newCombatMode = COMBAT_MODE : : UNDEF_COMBAT_MODE ;
for ( auto item : wielded )
{
newCombatMode = item - > GetEquippedCombatMode ( ) ;
if ( newCombatMode ! = COMBAT_MODE : : UNDEF_COMBAT_MODE )
break ;
}
if ( newCombatMode = = COMBAT_MODE : : UNDEF_COMBAT_MODE )
newCombatMode = COMBAT_MODE : : MELEE_COMBAT_MODE ;
ChangeCombatMode ( newCombatMode , false ) ;
}