2013-07-29 07:13:03 -04:00
// DropSpenserEntity.cpp
// Declares the cDropSpenserEntity class representing a common ancestor to the cDispenserEntity and cDropperEntity
// The dropper and dispenser only needs to override the DropSpenseFromSlot() function to provide the specific item behavior
# include "Globals.h"
# include "DropSpenserEntity.h"
2015-11-23 18:39:19 -05:00
# include "../EffectID.h"
2013-08-19 05:39:13 -04:00
# include "../Entities/Player.h"
2013-07-29 07:13:03 -04:00
# include "../Chunk.h"
2014-12-13 09:06:55 -05:00
# include "../UI/DropSpenserWindow.h"
2013-07-29 07:13:03 -04:00
cDropSpenserEntity : : cDropSpenserEntity ( BLOCKTYPE a_BlockType , int a_BlockX , int a_BlockY , int a_BlockZ , cWorld * a_World ) :
super ( a_BlockType , a_BlockX , a_BlockY , a_BlockZ , ContentsWidth , ContentsHeight , a_World ) ,
2015-06-26 18:24:51 -04:00
m_ShouldDropSpense ( false )
2013-07-29 07:13:03 -04:00
{
}
cDropSpenserEntity : : ~ cDropSpenserEntity ( )
{
// Tell window its owner is destroyed
cWindow * Window = GetWindow ( ) ;
2014-10-20 16:55:07 -04:00
if ( Window ! = nullptr )
2013-07-29 07:13:03 -04:00
{
Window - > OwnerDestroyed ( ) ;
}
}
void cDropSpenserEntity : : AddDropSpenserDir ( int & a_BlockX , int & a_BlockY , int & a_BlockZ , NIBBLETYPE a_Direction )
{
2016-06-04 08:16:35 -04:00
switch ( a_Direction & E_META_DROPSPENSER_FACING_MASK )
2013-07-29 07:13:03 -04:00
{
case E_META_DROPSPENSER_FACING_YM : a_BlockY - - ; return ;
case E_META_DROPSPENSER_FACING_YP : a_BlockY + + ; return ;
case E_META_DROPSPENSER_FACING_ZM : a_BlockZ - - ; return ;
case E_META_DROPSPENSER_FACING_ZP : a_BlockZ + + ; return ;
case E_META_DROPSPENSER_FACING_XM : a_BlockX - - ; return ;
case E_META_DROPSPENSER_FACING_XP : a_BlockX + + ; return ;
}
LOGWARNING ( " %s: Unhandled direction: %d " , __FUNCTION__ , a_Direction ) ;
return ;
}
void cDropSpenserEntity : : DropSpense ( cChunk & a_Chunk )
{
// Pick one of the occupied slots:
int OccupiedSlots [ 9 ] ;
int SlotsCnt = 0 ;
for ( int i = m_Contents . GetNumSlots ( ) - 1 ; i > = 0 ; i - - )
{
if ( ! m_Contents . GetSlot ( i ) . IsEmpty ( ) )
{
OccupiedSlots [ SlotsCnt ] = i ;
SlotsCnt + + ;
}
} // for i - m_Contents[]
2016-02-05 16:45:45 -05:00
2013-07-29 07:13:03 -04:00
if ( SlotsCnt = = 0 )
{
// Nothing in the dropspenser, play the click sound
2015-07-12 11:56:11 -04:00
m_World - > BroadcastSoundEffect ( " random.click " , static_cast < double > ( m_PosX ) , static_cast < double > ( m_PosY ) , static_cast < double > ( m_PosZ ) , 1.0f , 1.2f ) ;
2013-07-29 07:13:03 -04:00
return ;
}
2016-02-05 16:45:45 -05:00
2013-07-29 07:13:03 -04:00
int RandomSlot = m_World - > GetTickRandomNumber ( SlotsCnt - 1 ) ;
2016-02-05 16:45:45 -05:00
2013-07-29 07:13:03 -04:00
// DropSpense the item, using the specialized behavior in the subclasses:
DropSpenseFromSlot ( a_Chunk , OccupiedSlots [ RandomSlot ] ) ;
2016-02-05 16:45:45 -05:00
2013-07-29 07:13:03 -04:00
// Broadcast a smoke and click effects:
NIBBLETYPE Meta = a_Chunk . GetMeta ( m_RelX , m_PosY , m_RelZ ) ;
int SmokeDir = 0 ;
2016-06-04 08:16:35 -04:00
switch ( Meta & E_META_DROPSPENSER_FACING_MASK )
2013-07-29 07:13:03 -04:00
{
2015-11-23 18:39:19 -05:00
case E_META_DROPSPENSER_FACING_YP : SmokeDir = static_cast < int > ( SmokeDirection : : CENTRE ) ; break ; // YP & YM don't have associated smoke dirs, just do 4 (centre of block)
case E_META_DROPSPENSER_FACING_YM : SmokeDir = static_cast < int > ( SmokeDirection : : CENTRE ) ; break ;
case E_META_DROPSPENSER_FACING_XM : SmokeDir = static_cast < int > ( SmokeDirection : : EAST ) ; break ;
case E_META_DROPSPENSER_FACING_XP : SmokeDir = static_cast < int > ( SmokeDirection : : WEST ) ; break ;
case E_META_DROPSPENSER_FACING_ZM : SmokeDir = static_cast < int > ( SmokeDirection : : SOUTH ) ; break ;
case E_META_DROPSPENSER_FACING_ZP : SmokeDir = static_cast < int > ( SmokeDirection : : NORTH ) ; break ;
2013-07-29 07:13:03 -04:00
}
2015-11-23 18:39:19 -05:00
m_World - > BroadcastSoundParticleEffect ( EffectID : : PARTICLE_SMOKE , m_PosX , m_PosY , m_PosZ , SmokeDir ) ;
2015-07-12 11:56:11 -04:00
m_World - > BroadcastSoundEffect ( " random.click " , static_cast < double > ( m_PosX ) , static_cast < double > ( m_PosY ) , static_cast < double > ( m_PosZ ) , 1.0f , 1.0f ) ;
2014-07-17 16:50:58 -04:00
}
2013-07-29 07:13:03 -04:00
void cDropSpenserEntity : : Activate ( void )
{
m_ShouldDropSpense = true ;
}
2015-01-11 16:12:26 -05:00
bool cDropSpenserEntity : : Tick ( std : : chrono : : milliseconds a_Dt , cChunk & a_Chunk )
2013-07-29 07:13:03 -04:00
{
2014-02-24 14:29:59 -05:00
UNUSED ( a_Dt ) ;
2013-07-29 07:13:03 -04:00
if ( ! m_ShouldDropSpense )
{
return false ;
}
2016-02-05 16:45:45 -05:00
2013-07-29 07:13:03 -04:00
m_ShouldDropSpense = false ;
DropSpense ( a_Chunk ) ;
return true ;
}
void cDropSpenserEntity : : SendTo ( cClientHandle & a_Client )
{
// Nothing needs to be sent
UNUSED ( a_Client ) ;
}
2015-12-01 17:12:44 -05:00
bool cDropSpenserEntity : : UsedBy ( cPlayer * a_Player )
2013-07-29 07:13:03 -04:00
{
cWindow * Window = GetWindow ( ) ;
2014-10-20 16:55:07 -04:00
if ( Window = = nullptr )
2013-07-29 07:13:03 -04:00
{
OpenWindow ( new cDropSpenserWindow ( m_PosX , m_PosY , m_PosZ , this ) ) ;
Window = GetWindow ( ) ;
}
2016-02-05 16:45:45 -05:00
2014-10-20 16:55:07 -04:00
if ( Window ! = nullptr )
2013-07-29 07:13:03 -04:00
{
if ( a_Player - > GetWindow ( ) ! = Window )
{
a_Player - > OpenWindow ( Window ) ;
}
}
2015-12-01 17:12:44 -05:00
return true ;
2013-07-29 07:13:03 -04:00
}
void cDropSpenserEntity : : DropFromSlot ( cChunk & a_Chunk , int a_SlotNum )
{
int DispX = m_PosX ;
int DispY = m_PosY ;
int DispZ = m_PosZ ;
NIBBLETYPE Meta = a_Chunk . GetMeta ( m_RelX , m_PosY , m_RelZ ) ;
AddDropSpenserDir ( DispX , DispY , DispZ , Meta ) ;
cItems Pickups ;
Pickups . push_back ( m_Contents . RemoveOneItem ( a_SlotNum ) ) ;
2013-11-02 10:09:07 -04:00
2014-07-17 16:15:34 -04:00
const int PickupSpeed = m_World - > GetTickRandomNumber ( 4 ) + 2 ; // At least 2, at most 6
2013-11-02 10:09:07 -04:00
int PickupSpeedX = 0 , PickupSpeedY = 0 , PickupSpeedZ = 0 ;
2016-06-04 08:16:35 -04:00
switch ( Meta & E_META_DROPSPENSER_FACING_MASK )
2013-11-02 10:09:07 -04:00
{
case E_META_DROPSPENSER_FACING_YP : PickupSpeedY = PickupSpeed ; break ;
case E_META_DROPSPENSER_FACING_YM : PickupSpeedY = - PickupSpeed ; break ;
case E_META_DROPSPENSER_FACING_XM : PickupSpeedX = - PickupSpeed ; break ;
case E_META_DROPSPENSER_FACING_XP : PickupSpeedX = PickupSpeed ; break ;
case E_META_DROPSPENSER_FACING_ZM : PickupSpeedZ = - PickupSpeed ; break ;
case E_META_DROPSPENSER_FACING_ZP : PickupSpeedZ = PickupSpeed ; break ;
}
double MicroX , MicroY , MicroZ ;
MicroX = DispX + 0.5 ;
2014-07-17 16:15:34 -04:00
MicroY = DispY + 0.4 ; // Slightly less than half, to accomodate actual texture hole on DropSpenser
2013-11-02 10:09:07 -04:00
MicroZ = DispZ + 0.5 ;
m_World - > SpawnItemPickups ( Pickups , MicroX , MicroY , MicroZ , PickupSpeedX , PickupSpeedY , PickupSpeedZ ) ;
2013-07-29 07:13:03 -04:00
}
2014-10-20 16:55:07 -04:00