2013-07-29 07:13:03 -04:00
// Minecart.cpp
// Implements the cMinecart class representing a minecart in the world
2014-01-13 17:37:09 -05:00
// Handles physics when a minecart is on any type of rail (overrides simulator in Entity.cpp)
2013-08-27 15:38:11 -04:00
// Indiana Jones!
2013-07-29 07:13:03 -04:00
# include "Globals.h"
# include "Minecart.h"
2013-08-19 05:39:13 -04:00
# include "../ClientHandle.h"
2013-09-22 15:43:00 -04:00
# include "../Chunk.h"
2013-07-29 07:13:03 -04:00
# include "Player.h"
2014-01-13 17:37:09 -05:00
# include "../BoundingBox.h"
2013-07-29 07:13:03 -04:00
2014-09-22 18:23:56 -04:00
# define NO_SPEED 0.0
2014-01-12 08:28:37 -05:00
# define MAX_SPEED 8
# define MAX_SPEED_NEGATIVE -MAX_SPEED
2013-07-29 07:13:03 -04:00
2014-01-18 15:58:26 -05:00
class cMinecartCollisionCallback :
public cEntityCallback
{
public :
cMinecartCollisionCallback ( Vector3d a_Pos , double a_Height , double a_Width , int a_UniqueID , int a_AttacheeUniqueID ) :
2014-02-05 12:43:49 -05:00
m_DoesInteserct ( false ) ,
m_CollidedEntityPos ( 0 , 0 , 0 ) ,
2014-01-18 15:58:26 -05:00
m_Pos ( a_Pos ) ,
m_Height ( a_Height ) ,
m_Width ( a_Width ) ,
m_UniqueID ( a_UniqueID ) ,
m_AttacheeUniqueID ( a_AttacheeUniqueID )
{
}
virtual bool Item ( cEntity * a_Entity ) override
{
ASSERT ( a_Entity ! = NULL ) ;
if ( ! a_Entity - > IsPlayer ( ) & & ! a_Entity - > IsMob ( ) & & ! a_Entity - > IsMinecart ( ) & & ! a_Entity - > IsBoat ( ) )
{
return false ;
}
else if ( ( a_Entity - > GetUniqueID ( ) = = m_UniqueID ) | | ( a_Entity - > GetUniqueID ( ) = = m_AttacheeUniqueID ) )
{
return false ;
}
cBoundingBox bbEntity ( a_Entity - > GetPosition ( ) , a_Entity - > GetWidth ( ) / 2 , a_Entity - > GetHeight ( ) ) ;
cBoundingBox bbMinecart ( Vector3d ( m_Pos . x , floor ( m_Pos . y ) , m_Pos . z ) , m_Width / 2 , m_Height ) ;
if ( bbEntity . DoesIntersect ( bbMinecart ) )
{
m_CollidedEntityPos = a_Entity - > GetPosition ( ) ;
m_DoesInteserct = true ;
return true ;
}
return false ;
}
bool FoundIntersection ( void ) const
{
return m_DoesInteserct ;
}
Vector3d GetCollidedEntityPosition ( void ) const
{
return m_CollidedEntityPos ;
}
protected :
bool m_DoesInteserct ;
Vector3d m_CollidedEntityPos ;
Vector3d m_Pos ;
double m_Height , m_Width ;
int m_UniqueID ;
int m_AttacheeUniqueID ;
} ;
2013-07-29 07:13:03 -04:00
cMinecart : : cMinecart ( ePayload a_Payload , double a_X , double a_Y , double a_Z ) :
super ( etMinecart , a_X , a_Y , a_Z , 0.98 , 0.7 ) ,
2013-10-08 14:20:49 -04:00
m_Payload ( a_Payload ) ,
2014-01-13 17:37:09 -05:00
m_LastDamage ( 0 ) ,
m_DetectorRailPosition ( 0 , 0 , 0 ) ,
m_bIsOnDetectorRail ( false )
2013-07-29 07:13:03 -04:00
{
2013-08-28 17:13:27 -04:00
SetMass ( 20.f ) ;
SetMaxHealth ( 6 ) ;
2013-09-02 07:01:49 -04:00
SetHealth ( 6 ) ;
2014-01-18 15:58:26 -05:00
SetWidth ( 1 ) ;
2014-01-13 17:37:09 -05:00
SetHeight ( 0.9 ) ;
2013-07-29 07:13:03 -04:00
}
void cMinecart : : SpawnOn ( cClientHandle & a_ClientHandle )
{
2014-07-19 05:55:36 -04:00
a_ClientHandle . SendSpawnVehicle ( * this , 10 , ( char ) m_Payload ) ; // 10 = Minecarts
2014-01-12 12:04:41 -05:00
a_ClientHandle . SendEntityMetadata ( * this ) ;
2013-07-29 07:13:03 -04:00
}
2013-09-02 07:01:49 -04:00
void cMinecart : : HandlePhysics ( float a_Dt , cChunk & a_Chunk )
2013-07-29 07:13:03 -04:00
{
2014-07-17 16:15:34 -04:00
if ( IsDestroyed ( ) ) // Mainly to stop detector rails triggering again after minecart is dead
2014-01-13 17:37:09 -05:00
{
return ;
}
2014-04-17 13:50:25 -04:00
int PosY = POSY_TOINT ;
2013-09-22 15:43:00 -04:00
if ( ( PosY < = 0 ) | | ( PosY > = cChunkDef : : Height ) )
2013-09-02 07:01:49 -04:00
{
2013-09-22 15:43:00 -04:00
// Outside the world, just process normal falling physics
super : : HandlePhysics ( a_Dt , a_Chunk ) ;
BroadcastMovementUpdate ( ) ;
return ;
}
2014-04-17 13:50:25 -04:00
int RelPosX = POSX_TOINT - a_Chunk . GetPosX ( ) * cChunkDef : : Width ;
int RelPosZ = POSZ_TOINT - a_Chunk . GetPosZ ( ) * cChunkDef : : Width ;
2013-09-22 15:43:00 -04:00
cChunk * Chunk = a_Chunk . GetRelNeighborChunkAdjustCoords ( RelPosX , RelPosZ ) ;
if ( Chunk = = NULL )
{
// Inside an unloaded chunk, bail out all processing
return ;
}
2013-09-02 07:01:49 -04:00
2014-01-12 08:28:37 -05:00
BLOCKTYPE InsideType ;
NIBBLETYPE InsideMeta ;
Chunk - > GetBlockTypeMeta ( RelPosX , PosY , RelPosZ , InsideType , InsideMeta ) ;
if ( ! IsBlockRail ( InsideType ) )
2013-09-22 15:43:00 -04:00
{
2014-07-17 16:15:34 -04:00
Chunk - > GetBlockTypeMeta ( RelPosX , PosY + 1 , RelPosZ , InsideType , InsideMeta ) ; // When an descending minecart hits a flat rail, it goes through the ground; check for this
if ( IsBlockRail ( InsideType ) ) AddPosY ( 1 ) ; // Push cart upwards
2013-09-22 15:43:00 -04:00
}
2014-01-12 08:28:37 -05:00
2014-01-19 13:27:06 -05:00
bool WasDetectorRail = false ;
2014-01-12 08:28:37 -05:00
if ( IsBlockRail ( InsideType ) )
2013-09-22 15:43:00 -04:00
{
2014-01-19 13:27:06 -05:00
if ( InsideType = = E_BLOCK_RAIL )
{
SnapToRail ( InsideMeta ) ;
}
else
{
SnapToRail ( InsideMeta & 0x07 ) ;
}
2014-01-12 08:28:37 -05:00
switch ( InsideType )
2013-09-02 07:01:49 -04:00
{
2014-01-13 17:37:09 -05:00
case E_BLOCK_RAIL : HandleRailPhysics ( InsideMeta , a_Dt ) ; break ;
2014-01-12 08:28:37 -05:00
case E_BLOCK_ACTIVATOR_RAIL : break ;
case E_BLOCK_POWERED_RAIL : HandlePoweredRailPhysics ( InsideMeta ) ; break ;
2014-01-13 17:37:09 -05:00
case E_BLOCK_DETECTOR_RAIL :
{
HandleDetectorRailPhysics ( InsideMeta , a_Dt ) ;
WasDetectorRail = true ;
break ;
}
2014-01-12 08:28:37 -05:00
default : VERIFY ( ! " Unhandled rail type despite checking if block was rail! " ) ; break ;
2013-09-02 07:01:49 -04:00
}
2014-01-12 08:28:37 -05:00
2014-07-17 16:15:34 -04:00
AddPosition ( GetSpeed ( ) * ( a_Dt / 1000 ) ) ; // Commit changes; as we use our own engine when on rails, this needs to be done, whereas it is normally in Entity.cpp
2014-01-12 08:28:37 -05:00
}
else
{
2014-01-13 17:37:09 -05:00
// Not on rail, default physics
2014-07-17 16:15:34 -04:00
SetPosY ( floor ( GetPosY ( ) ) + 0.35 ) ; // HandlePhysics overrides this if minecart can fall, else, it is to stop ground clipping minecart bottom when off-rail
2014-01-12 08:28:37 -05:00
super : : HandlePhysics ( a_Dt , * Chunk ) ;
2013-09-02 07:01:49 -04:00
}
2014-01-19 13:27:06 -05:00
2014-04-17 13:50:25 -04:00
if ( m_bIsOnDetectorRail & & ! Vector3i ( POSX_TOINT , POSY_TOINT , POSZ_TOINT ) . Equals ( m_DetectorRailPosition ) )
2014-01-19 13:27:06 -05:00
{
m_World - > SetBlock ( m_DetectorRailPosition . x , m_DetectorRailPosition . y , m_DetectorRailPosition . z , E_BLOCK_DETECTOR_RAIL , m_World - > GetBlockMeta ( m_DetectorRailPosition ) & 0x07 ) ;
m_bIsOnDetectorRail = false ;
}
else if ( WasDetectorRail )
{
m_bIsOnDetectorRail = true ;
2014-04-17 13:50:25 -04:00
m_DetectorRailPosition = Vector3i ( POSX_TOINT , POSY_TOINT , POSZ_TOINT ) ;
2014-01-19 13:27:06 -05:00
}
2014-01-12 08:28:37 -05:00
2014-01-13 17:37:09 -05:00
// Broadcast positioning changes to client
2014-01-12 08:28:37 -05:00
BroadcastMovementUpdate ( ) ;
2013-09-02 07:01:49 -04:00
}
2014-01-13 17:37:09 -05:00
void cMinecart : : HandleRailPhysics ( NIBBLETYPE a_RailMeta , float a_Dt )
2013-09-02 07:01:49 -04:00
{
2013-08-27 15:38:11 -04:00
/*
NOTE : Please bear in mind that taking away from negatives make them even more negative ,
2013-08-29 08:47:22 -04:00
adding to negatives make them positive , etc .
2013-08-27 15:38:11 -04:00
*/
2014-01-12 08:28:37 -05:00
switch ( a_RailMeta )
2013-08-27 15:38:11 -04:00
{
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ZM_ZP : // NORTHSOUTH
2013-08-27 15:38:11 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 270 ) ;
2014-01-12 08:28:37 -05:00
SetPosY ( floor ( GetPosY ( ) ) + 0.55 ) ;
2014-07-17 16:15:34 -04:00
SetSpeedY ( 0 ) ; // Don't move vertically as on ground
SetSpeedX ( 0 ) ; // Correct diagonal movement from curved rails
2014-01-13 17:37:09 -05:00
2014-01-18 15:58:26 -05:00
// Execute both the entity and block collision checks
bool BlckCol = TestBlockCollision ( a_RailMeta ) , EntCol = TestEntityCollision ( a_RailMeta ) ;
if ( EntCol | | BlckCol ) return ;
2013-09-02 07:01:49 -04:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) ! = NO_SPEED ) // Don't do anything if cart is stationary
2013-08-27 15:38:11 -04:00
{
2014-01-12 08:28:37 -05:00
if ( GetSpeedZ ( ) > 0 )
2013-09-02 07:01:49 -04:00
{
// Going SOUTH, slow down
2014-01-12 08:28:37 -05:00
AddSpeedZ ( - 0.1 ) ;
2013-09-02 07:01:49 -04:00
}
else
2013-08-27 15:38:11 -04:00
{
2013-09-02 07:01:49 -04:00
// Going NORTH, slow down
2014-01-12 08:28:37 -05:00
AddSpeedZ ( 0.1 ) ;
2013-08-27 15:38:11 -04:00
}
}
2013-09-02 07:01:49 -04:00
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_XM_XP : // EASTWEST
2013-09-02 07:01:49 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 180 ) ;
2014-01-12 08:28:37 -05:00
SetPosY ( floor ( GetPosY ( ) ) + 0.55 ) ;
2014-09-22 18:23:56 -04:00
SetSpeedY ( NO_SPEED ) ;
SetSpeedZ ( NO_SPEED ) ;
2013-08-27 15:38:11 -04:00
2014-01-18 15:58:26 -05:00
bool BlckCol = TestBlockCollision ( a_RailMeta ) , EntCol = TestEntityCollision ( a_RailMeta ) ;
if ( EntCol | | BlckCol ) return ;
2014-01-13 17:37:09 -05:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) ! = NO_SPEED )
2013-09-02 07:01:49 -04:00
{
2014-01-12 08:28:37 -05:00
if ( GetSpeedX ( ) > 0 )
2013-08-27 15:38:11 -04:00
{
2014-01-12 08:28:37 -05:00
AddSpeedX ( - 0.1 ) ;
2013-09-02 07:01:49 -04:00
}
else
{
2014-01-12 08:28:37 -05:00
AddSpeedX ( 0.1 ) ;
2013-08-27 15:38:11 -04:00
}
}
2013-09-02 07:01:49 -04:00
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ASCEND_ZM : // ASCEND NORTH
2013-09-02 07:01:49 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 270 ) ;
2014-01-12 08:28:37 -05:00
SetSpeedX ( 0 ) ;
2013-08-27 15:38:11 -04:00
2014-01-12 08:28:37 -05:00
if ( GetSpeedZ ( ) > = 0 )
2013-08-27 15:38:11 -04:00
{
2013-09-02 07:01:49 -04:00
// SpeedZ POSITIVE, going SOUTH
2014-07-17 16:15:34 -04:00
if ( GetSpeedZ ( ) < = MAX_SPEED ) // Speed limit
2013-08-27 15:38:11 -04:00
{
2014-07-17 16:15:34 -04:00
AddSpeedZ ( 0.5 ) ; // Speed up
SetSpeedY ( - GetSpeedZ ( ) ) ; // Downward movement is negative (0 minus positive numbers is negative)
2013-08-27 15:38:11 -04:00
}
}
2013-09-02 07:01:49 -04:00
else
{
// SpeedZ NEGATIVE, going NORTH
2014-07-17 16:15:34 -04:00
AddSpeedZ ( 1 ) ; // Slow down
SetSpeedY ( - GetSpeedZ ( ) ) ; // Upward movement is positive (0 minus negative number is positive number)
2013-09-02 07:01:49 -04:00
}
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ASCEND_ZP : // ASCEND SOUTH
2013-09-02 07:01:49 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 270 ) ;
2014-01-12 08:28:37 -05:00
SetSpeedX ( 0 ) ;
2013-08-27 15:38:11 -04:00
2014-01-12 08:28:37 -05:00
if ( GetSpeedZ ( ) > 0 )
2013-08-27 15:38:11 -04:00
{
2013-09-02 07:01:49 -04:00
// SpeedZ POSITIVE, going SOUTH
2014-07-17 16:15:34 -04:00
AddSpeedZ ( - 1 ) ; // Slow down
SetSpeedY ( GetSpeedZ ( ) ) ; // Upward movement positive
2013-09-02 07:01:49 -04:00
}
else
{
2014-07-17 16:15:34 -04:00
if ( GetSpeedZ ( ) > = MAX_SPEED_NEGATIVE ) // Speed limit
2013-08-27 15:38:11 -04:00
{
2013-09-02 07:01:49 -04:00
// SpeedZ NEGATIVE, going NORTH
2014-07-17 16:15:34 -04:00
AddSpeedZ ( - 0.5 ) ; // Speed up
SetSpeedY ( GetSpeedZ ( ) ) ; // Downward movement negative
2013-08-27 15:38:11 -04:00
}
}
2013-09-02 07:01:49 -04:00
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ASCEND_XM : // ASCEND EAST
2013-09-02 07:01:49 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 180 ) ;
2014-09-22 18:23:56 -04:00
SetSpeedZ ( NO_SPEED ) ;
2013-08-27 15:38:11 -04:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) > = NO_SPEED )
2013-08-27 15:38:11 -04:00
{
2014-01-12 08:28:37 -05:00
if ( GetSpeedX ( ) < = MAX_SPEED )
2013-08-27 15:38:11 -04:00
{
2014-01-12 08:28:37 -05:00
AddSpeedX ( 0.5 ) ;
SetSpeedY ( - GetSpeedX ( ) ) ;
2013-08-27 15:38:11 -04:00
}
}
2013-09-02 07:01:49 -04:00
else
{
2014-01-12 08:28:37 -05:00
AddSpeedX ( 1 ) ;
SetSpeedY ( - GetSpeedX ( ) ) ;
2013-09-02 07:01:49 -04:00
}
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ASCEND_XP : // ASCEND WEST
2013-09-02 07:01:49 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 180 ) ;
2014-01-12 08:28:37 -05:00
SetSpeedZ ( 0 ) ;
2013-08-27 15:38:11 -04:00
2014-01-12 08:28:37 -05:00
if ( GetSpeedX ( ) > 0 )
2013-08-27 15:38:11 -04:00
{
2014-01-12 08:28:37 -05:00
AddSpeedX ( - 1 ) ;
SetSpeedY ( GetSpeedX ( ) ) ;
2013-09-02 07:01:49 -04:00
}
else
{
2014-01-12 08:28:37 -05:00
if ( GetSpeedX ( ) > = MAX_SPEED_NEGATIVE )
2013-08-27 15:38:11 -04:00
{
2014-01-12 08:28:37 -05:00
AddSpeedX ( - 0.5 ) ;
SetSpeedY ( GetSpeedX ( ) ) ;
2013-08-27 15:38:11 -04:00
}
}
2013-09-02 07:01:49 -04:00
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_CURVED_ZM_XM : // Ends pointing NORTH and WEST
2013-09-02 07:01:49 -04:00
{
2014-07-17 16:15:34 -04:00
SetYaw ( 315 ) ; // Set correct rotation server side
SetPosY ( floor ( GetPosY ( ) ) + 0.55 ) ; // Levitate dat cart
2014-01-19 14:31:17 -05:00
SetSpeedY ( 0 ) ;
2014-01-13 17:37:09 -05:00
2014-01-18 15:58:26 -05:00
TestBlockCollision ( a_RailMeta ) ;
TestEntityCollision ( a_RailMeta ) ;
// SnapToRail handles turning
2013-09-02 07:01:49 -04:00
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_CURVED_ZM_XP : // Curved NORTH EAST
2013-09-02 07:01:49 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 225 ) ;
2014-01-13 17:37:09 -05:00
SetPosY ( floor ( GetPosY ( ) ) + 0.55 ) ;
2014-01-19 14:31:17 -05:00
SetSpeedY ( 0 ) ;
2014-01-13 17:37:09 -05:00
2014-01-18 15:58:26 -05:00
TestBlockCollision ( a_RailMeta ) ;
TestEntityCollision ( a_RailMeta ) ;
2013-09-02 07:01:49 -04:00
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_CURVED_ZP_XM : // Curved SOUTH WEST
2013-09-02 07:01:49 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 135 ) ;
2014-01-13 17:37:09 -05:00
SetPosY ( floor ( GetPosY ( ) ) + 0.55 ) ;
2014-01-19 14:31:17 -05:00
SetSpeedY ( 0 ) ;
2014-01-13 17:37:09 -05:00
2014-01-18 15:58:26 -05:00
TestBlockCollision ( a_RailMeta ) ;
TestEntityCollision ( a_RailMeta ) ;
2013-09-02 07:01:49 -04:00
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_CURVED_ZP_XP : // Curved SOUTH EAST
2013-09-02 07:01:49 -04:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 45 ) ;
2014-01-13 17:37:09 -05:00
SetPosY ( floor ( GetPosY ( ) ) + 0.55 ) ;
2014-01-19 14:31:17 -05:00
SetSpeedY ( 0 ) ;
2014-01-13 17:37:09 -05:00
2014-01-18 15:58:26 -05:00
TestBlockCollision ( a_RailMeta ) ;
TestEntityCollision ( a_RailMeta ) ;
2013-09-02 07:01:49 -04:00
break ;
}
default :
{
2014-07-17 16:15:34 -04:00
ASSERT ( ! " Unhandled rail meta! " ) ; // Dun dun DUN!
2013-09-02 07:01:49 -04:00
break ;
2013-08-27 15:38:11 -04:00
}
}
2014-01-12 08:28:37 -05:00
}
2013-09-02 07:01:49 -04:00
2013-08-27 15:38:11 -04:00
2013-09-02 07:01:49 -04:00
2014-01-12 08:28:37 -05:00
void cMinecart : : HandlePoweredRailPhysics ( NIBBLETYPE a_RailMeta )
{
2014-01-13 17:37:09 -05:00
// Initialise to 'slow down' values
2014-01-25 15:33:23 -05:00
int AccelDecelSpeed = - 2 ;
int AccelDecelNegSpeed = 2 ;
2014-01-13 17:37:09 -05:00
2014-01-12 08:28:37 -05:00
if ( ( a_RailMeta & 0x8 ) = = 0x8 )
{
2014-01-13 17:37:09 -05:00
// Rail powered - set variables to 'speed up' values
AccelDecelSpeed = 1 ;
AccelDecelNegSpeed = - 1 ;
}
switch ( a_RailMeta & 0x07 )
{
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ZM_ZP : // NORTHSOUTH
2014-01-12 08:28:37 -05:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 270 ) ;
2014-01-13 17:37:09 -05:00
SetPosY ( floor ( GetPosY ( ) ) + 0.55 ) ;
SetSpeedY ( 0 ) ;
SetSpeedX ( 0 ) ;
2014-01-19 14:31:17 -05:00
bool BlckCol = TestBlockCollision ( a_RailMeta ) , EntCol = TestEntityCollision ( a_RailMeta ) ;
if ( EntCol | | BlckCol ) return ;
2014-01-12 08:28:37 -05:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) ! = NO_SPEED )
2014-01-13 17:37:09 -05:00
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) > NO_SPEED )
2014-01-12 08:28:37 -05:00
{
2014-01-19 13:27:06 -05:00
AddSpeedZ ( AccelDecelSpeed ) ;
2014-01-13 17:37:09 -05:00
}
else
{
2014-01-19 13:27:06 -05:00
AddSpeedZ ( AccelDecelNegSpeed ) ;
2014-01-12 08:28:37 -05:00
}
}
2014-01-13 17:37:09 -05:00
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_XM_XP : // EASTWEST
2014-01-13 17:37:09 -05:00
{
2014-01-16 14:00:49 -05:00
SetYaw ( 180 ) ;
2014-01-13 17:37:09 -05:00
SetPosY ( floor ( GetPosY ( ) ) + 0.55 ) ;
2014-09-22 18:23:56 -04:00
SetSpeedY ( NO_SPEED ) ;
SetSpeedZ ( NO_SPEED ) ;
2014-01-12 08:28:37 -05:00
2014-01-19 14:31:17 -05:00
bool BlckCol = TestBlockCollision ( a_RailMeta ) , EntCol = TestEntityCollision ( a_RailMeta ) ;
if ( EntCol | | BlckCol ) return ;
2014-01-13 17:37:09 -05:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) ! = NO_SPEED )
2014-01-13 17:37:09 -05:00
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) > NO_SPEED )
2014-01-12 08:28:37 -05:00
{
2014-01-13 17:37:09 -05:00
AddSpeedX ( AccelDecelSpeed ) ;
}
else
{
AddSpeedX ( AccelDecelNegSpeed ) ;
2014-01-12 08:28:37 -05:00
}
}
2014-01-13 17:37:09 -05:00
break ;
2014-01-12 08:28:37 -05:00
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ASCEND_XM : // ASCEND EAST
2014-01-19 14:31:17 -05:00
{
SetYaw ( 180 ) ;
2014-09-22 18:23:56 -04:00
SetSpeedZ ( NO_SPEED ) ;
2014-01-19 14:31:17 -05:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) > = NO_SPEED )
2014-01-19 14:31:17 -05:00
{
if ( GetSpeedX ( ) < = MAX_SPEED )
{
2014-01-24 14:39:39 -05:00
AddSpeedX ( AccelDecelSpeed ) ;
2014-01-19 14:31:17 -05:00
SetSpeedY ( - GetSpeedX ( ) ) ;
}
}
else
{
2014-01-24 14:39:39 -05:00
AddSpeedX ( AccelDecelNegSpeed ) ;
2014-01-19 14:31:17 -05:00
SetSpeedY ( - GetSpeedX ( ) ) ;
}
break ;
2014-07-17 16:59:02 -04:00
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ASCEND_XP : // ASCEND WEST
2014-01-24 14:39:39 -05:00
{
SetYaw ( 180 ) ;
2014-09-22 18:23:56 -04:00
SetSpeedZ ( NO_SPEED ) ;
2014-01-24 14:39:39 -05:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) > NO_SPEED )
2014-01-24 14:39:39 -05:00
{
AddSpeedX ( AccelDecelSpeed ) ;
SetSpeedY ( GetSpeedX ( ) ) ;
}
else
{
if ( GetSpeedX ( ) > = MAX_SPEED_NEGATIVE )
{
AddSpeedX ( AccelDecelNegSpeed ) ;
SetSpeedY ( GetSpeedX ( ) ) ;
}
}
break ;
2014-07-17 16:59:02 -04:00
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ASCEND_ZM : // ASCEND NORTH
2014-01-24 14:39:39 -05:00
{
SetYaw ( 270 ) ;
2014-09-22 18:23:56 -04:00
SetSpeedX ( NO_SPEED ) ;
2014-01-24 14:39:39 -05:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) > = NO_SPEED )
2014-01-24 14:39:39 -05:00
{
if ( GetSpeedZ ( ) < = MAX_SPEED )
{
AddSpeedZ ( AccelDecelSpeed ) ;
SetSpeedY ( - GetSpeedZ ( ) ) ;
}
}
else
{
AddSpeedZ ( AccelDecelNegSpeed ) ;
SetSpeedY ( - GetSpeedZ ( ) ) ;
}
break ;
}
2014-07-17 16:15:34 -04:00
case E_META_RAIL_ASCEND_ZP : // ASCEND SOUTH
2014-01-24 14:39:39 -05:00
{
SetYaw ( 270 ) ;
2014-09-22 18:23:56 -04:00
SetSpeedX ( NO_SPEED ) ;
2014-01-24 14:39:39 -05:00
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) > NO_SPEED )
2014-01-24 14:39:39 -05:00
{
AddSpeedZ ( AccelDecelSpeed ) ;
SetSpeedY ( GetSpeedZ ( ) ) ;
}
else
{
if ( GetSpeedZ ( ) > = MAX_SPEED_NEGATIVE )
{
AddSpeedZ ( AccelDecelNegSpeed ) ;
SetSpeedY ( GetSpeedZ ( ) ) ;
}
}
break ;
2014-01-19 14:31:17 -05:00
}
default : ASSERT ( ! " Unhandled powered rail metadata! " ) ; break ;
2014-01-12 08:28:37 -05:00
}
}
2014-01-13 17:37:09 -05:00
void cMinecart : : HandleDetectorRailPhysics ( NIBBLETYPE a_RailMeta , float a_Dt )
{
m_World - > SetBlockMeta ( m_DetectorRailPosition , a_RailMeta | 0x08 ) ;
2014-01-19 14:31:17 -05:00
// No special handling
HandleRailPhysics ( a_RailMeta & 0x07 , a_Dt ) ;
}
void cMinecart : : HandleActivatorRailPhysics ( NIBBLETYPE a_RailMeta , float a_Dt )
{
2014-01-13 17:37:09 -05:00
HandleRailPhysics ( a_RailMeta & 0x07 , a_Dt ) ;
}
2014-01-12 08:28:37 -05:00
void cMinecart : : SnapToRail ( NIBBLETYPE a_RailMeta )
{
switch ( a_RailMeta )
{
case E_META_RAIL_ASCEND_XM :
case E_META_RAIL_ASCEND_XP :
case E_META_RAIL_XM_XP :
{
2014-09-22 18:23:56 -04:00
SetSpeedZ ( NO_SPEED ) ;
2014-01-13 17:37:09 -05:00
SetPosZ ( floor ( GetPosZ ( ) ) + 0.5 ) ;
2014-01-12 08:28:37 -05:00
break ;
}
case E_META_RAIL_ASCEND_ZM :
case E_META_RAIL_ASCEND_ZP :
case E_META_RAIL_ZM_ZP :
{
2014-09-22 18:23:56 -04:00
SetSpeedX ( NO_SPEED ) ;
2014-01-13 17:37:09 -05:00
SetPosX ( floor ( GetPosX ( ) ) + 0.5 ) ;
2014-01-12 08:28:37 -05:00
break ;
}
2014-01-19 13:27:06 -05:00
// Curved rail physics: once minecart has reached more than half of the block in the direction that it is travelling in, jerk it in the direction of curvature
2014-01-18 15:58:26 -05:00
case E_META_RAIL_CURVED_ZM_XM :
{
2014-01-19 13:27:06 -05:00
if ( GetPosZ ( ) > floor ( GetPosZ ( ) ) + 0.5 )
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) > NO_SPEED )
2014-01-19 13:27:06 -05:00
{
SetSpeedX ( - GetSpeedZ ( ) * 0.7 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedZ ( NO_SPEED ) ;
2014-01-19 13:27:06 -05:00
SetPosZ ( floor ( GetPosZ ( ) ) + 0.5 ) ;
}
else if ( GetPosX ( ) > floor ( GetPosX ( ) ) + 0.5 )
2014-01-18 15:58:26 -05:00
{
if ( GetSpeedX ( ) > 0 )
{
SetSpeedZ ( - GetSpeedX ( ) * 0.7 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedX ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
SetPosX ( floor ( GetPosX ( ) ) + 0.5 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedY ( NO_SPEED ) ;
2014-01-19 13:27:06 -05:00
break ;
}
case E_META_RAIL_CURVED_ZM_XP :
{
if ( GetPosZ ( ) > floor ( GetPosZ ( ) ) + 0.5 )
2014-01-18 15:58:26 -05:00
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) > NO_SPEED )
2014-01-18 15:58:26 -05:00
{
2014-01-19 13:27:06 -05:00
SetSpeedX ( GetSpeedZ ( ) * 0.7 ) ;
2014-01-18 15:58:26 -05:00
}
2014-09-22 18:23:56 -04:00
SetSpeedZ ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
SetPosZ ( floor ( GetPosZ ( ) ) + 0.5 ) ;
}
2014-01-19 13:27:06 -05:00
else if ( GetPosX ( ) < floor ( GetPosX ( ) ) + 0.5 )
2014-01-18 15:58:26 -05:00
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) < NO_SPEED )
2014-01-18 15:58:26 -05:00
{
SetSpeedZ ( GetSpeedX ( ) * 0.7 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedX ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
SetPosX ( floor ( GetPosX ( ) ) + 0.5 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedY ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
break ;
}
case E_META_RAIL_CURVED_ZP_XM :
{
if ( GetPosZ ( ) < floor ( GetPosZ ( ) ) + 0.5 )
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) < NO_SPEED )
2014-01-18 15:58:26 -05:00
{
SetSpeedX ( GetSpeedZ ( ) * 0.7 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedZ ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
SetPosZ ( floor ( GetPosZ ( ) ) + 0.5 ) ;
}
2014-01-19 13:27:06 -05:00
else if ( GetPosX ( ) > floor ( GetPosX ( ) ) + 0.5 )
2014-01-18 15:58:26 -05:00
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) > NO_SPEED )
2014-01-18 15:58:26 -05:00
{
SetSpeedZ ( GetSpeedX ( ) * 0.7 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedX ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
SetPosX ( floor ( GetPosX ( ) ) + 0.5 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedY ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
break ;
}
case E_META_RAIL_CURVED_ZP_XP :
{
if ( GetPosZ ( ) < floor ( GetPosZ ( ) ) + 0.5 )
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedZ ( ) < NO_SPEED )
2014-01-18 15:58:26 -05:00
{
SetSpeedX ( - GetSpeedZ ( ) * 0.7 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedZ ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
SetPosZ ( floor ( GetPosZ ( ) ) + 0.5 ) ;
}
2014-01-19 13:27:06 -05:00
else if ( GetPosX ( ) < floor ( GetPosX ( ) ) + 0.5 )
2014-01-18 15:58:26 -05:00
{
2014-09-22 18:23:56 -04:00
if ( GetSpeedX ( ) < NO_SPEED )
2014-01-18 15:58:26 -05:00
{
SetSpeedZ ( - GetSpeedX ( ) * 0.7 ) ;
}
2014-09-22 18:23:56 -04:00
SetSpeedX ( NO_SPEED ) ;
2014-01-18 15:58:26 -05:00
SetPosX ( floor ( GetPosX ( ) ) + 0.5 ) ;
}
2014-01-19 14:31:17 -05:00
SetSpeedY ( 0 ) ;
2014-01-18 15:58:26 -05:00
break ;
}
2014-01-12 08:28:37 -05:00
default : break ;
}
2013-09-02 07:01:49 -04:00
}
2013-08-27 15:38:11 -04:00
2013-09-02 07:01:49 -04:00
2014-01-13 17:37:09 -05:00
bool cMinecart : : TestBlockCollision ( NIBBLETYPE a_RailMeta )
{
switch ( a_RailMeta )
{
case E_META_RAIL_ZM_ZP :
{
if ( GetSpeedZ ( ) > 0 )
{
2014-04-17 13:50:25 -04:00
BLOCKTYPE Block = m_World - > GetBlock ( POSX_TOINT , POSY_TOINT , ( int ) ceil ( GetPosZ ( ) ) ) ;
2014-03-01 14:34:19 -05:00
if ( ! IsBlockRail ( Block ) & & cBlockInfo : : IsSolid ( Block ) )
2014-01-13 17:37:09 -05:00
{
// We could try to detect a block in front based purely on coordinates, but xoft made a bounding box system - why not use? :P
2014-04-17 13:50:25 -04:00
cBoundingBox bbBlock ( Vector3d ( POSX_TOINT , POSY_TOINT , ( int ) ceil ( GetPosZ ( ) ) ) , 0.5 , 1 ) ;
2014-01-13 17:37:09 -05:00
cBoundingBox bbMinecart ( Vector3d ( GetPosX ( ) , floor ( GetPosY ( ) ) , GetPosZ ( ) ) , GetWidth ( ) / 2 , GetHeight ( ) ) ;
if ( bbBlock . DoesIntersect ( bbMinecart ) )
{
SetSpeed ( 0 , 0 , 0 ) ;
SetPosZ ( floor ( GetPosZ ( ) ) + 0.4 ) ;
return true ;
}
}
}
2014-01-18 15:58:26 -05:00
else if ( GetSpeedZ ( ) < 0 )
2014-01-13 17:37:09 -05:00
{
2014-04-17 13:50:25 -04:00
BLOCKTYPE Block = m_World - > GetBlock ( POSX_TOINT , POSY_TOINT , POSZ_TOINT - 1 ) ;
2014-03-01 14:34:19 -05:00
if ( ! IsBlockRail ( Block ) & & cBlockInfo : : IsSolid ( Block ) )
2014-01-13 17:37:09 -05:00
{
2014-04-17 13:50:25 -04:00
cBoundingBox bbBlock ( Vector3d ( POSX_TOINT , POSY_TOINT , POSZ_TOINT - 1 ) , 0.5 , 1 ) ;
2014-01-13 17:37:09 -05:00
cBoundingBox bbMinecart ( Vector3d ( GetPosX ( ) , floor ( GetPosY ( ) ) , GetPosZ ( ) - 1 ) , GetWidth ( ) / 2 , GetHeight ( ) ) ;
if ( bbBlock . DoesIntersect ( bbMinecart ) )
{
SetSpeed ( 0 , 0 , 0 ) ;
SetPosZ ( floor ( GetPosZ ( ) ) + 0.65 ) ;
return true ;
}
}
}
break ;
}
case E_META_RAIL_XM_XP :
{
if ( GetSpeedX ( ) > 0 )
{
2014-04-17 13:50:25 -04:00
BLOCKTYPE Block = m_World - > GetBlock ( ( int ) ceil ( GetPosX ( ) ) , POSY_TOINT , POSZ_TOINT ) ;
2014-03-01 14:34:19 -05:00
if ( ! IsBlockRail ( Block ) & & cBlockInfo : : IsSolid ( Block ) )
2014-01-13 17:37:09 -05:00
{
2014-04-17 13:50:25 -04:00
cBoundingBox bbBlock ( Vector3d ( ( int ) ceil ( GetPosX ( ) ) , POSY_TOINT , POSZ_TOINT ) , 0.5 , 1 ) ;
2014-01-13 17:37:09 -05:00
cBoundingBox bbMinecart ( Vector3d ( GetPosX ( ) , floor ( GetPosY ( ) ) , GetPosZ ( ) ) , GetWidth ( ) / 2 , GetHeight ( ) ) ;
if ( bbBlock . DoesIntersect ( bbMinecart ) )
{
SetSpeed ( 0 , 0 , 0 ) ;
SetPosX ( floor ( GetPosX ( ) ) + 0.4 ) ;
return true ;
}
}
}
2014-01-18 15:58:26 -05:00
else if ( GetSpeedX ( ) < 0 )
2014-01-13 17:37:09 -05:00
{
2014-04-17 13:50:25 -04:00
BLOCKTYPE Block = m_World - > GetBlock ( POSX_TOINT - 1 , POSY_TOINT , POSZ_TOINT ) ;
2014-03-01 14:34:19 -05:00
if ( ! IsBlockRail ( Block ) & & cBlockInfo : : IsSolid ( Block ) )
2014-01-13 17:37:09 -05:00
{
2014-04-17 13:50:25 -04:00
cBoundingBox bbBlock ( Vector3d ( POSX_TOINT - 1 , POSY_TOINT , POSZ_TOINT ) , 0.5 , 1 ) ;
2014-01-13 17:37:09 -05:00
cBoundingBox bbMinecart ( Vector3d ( GetPosX ( ) - 1 , floor ( GetPosY ( ) ) , GetPosZ ( ) ) , GetWidth ( ) / 2 , GetHeight ( ) ) ;
if ( bbBlock . DoesIntersect ( bbMinecart ) )
{
SetSpeed ( 0 , 0 , 0 ) ;
SetPosX ( floor ( GetPosX ( ) ) + 0.65 ) ;
return true ;
}
}
}
break ;
2014-07-17 16:59:02 -04:00
}
2014-01-13 17:37:09 -05:00
case E_META_RAIL_CURVED_ZM_XM :
case E_META_RAIL_CURVED_ZM_XP :
case E_META_RAIL_CURVED_ZP_XM :
case E_META_RAIL_CURVED_ZP_XP :
{
2014-04-17 13:50:25 -04:00
BLOCKTYPE BlockXM = m_World - > GetBlock ( POSX_TOINT - 1 , POSY_TOINT , POSZ_TOINT ) ;
BLOCKTYPE BlockXP = m_World - > GetBlock ( POSX_TOINT + 1 , POSY_TOINT , POSZ_TOINT ) ;
2014-04-18 15:44:58 -04:00
BLOCKTYPE BlockZM = m_World - > GetBlock ( POSX_TOINT , POSY_TOINT , POSZ_TOINT - 1 ) ;
2014-04-21 08:04:36 -04:00
BLOCKTYPE BlockZP = m_World - > GetBlock ( POSX_TOINT , POSY_TOINT , POSZ_TOINT + 1 ) ;
2014-01-13 17:37:09 -05:00
if (
2014-03-01 14:34:19 -05:00
( ! IsBlockRail ( BlockXM ) & & cBlockInfo : : IsSolid ( BlockXM ) ) | |
( ! IsBlockRail ( BlockXP ) & & cBlockInfo : : IsSolid ( BlockXP ) ) | |
( ! IsBlockRail ( BlockZM ) & & cBlockInfo : : IsSolid ( BlockZM ) ) | |
( ! IsBlockRail ( BlockZP ) & & cBlockInfo : : IsSolid ( BlockZP ) )
2014-01-13 17:37:09 -05:00
)
{
SetSpeed ( 0 , 0 , 0 ) ;
2014-04-17 13:50:25 -04:00
SetPosition ( POSX_TOINT + 0.5 , GetPosY ( ) , POSZ_TOINT + 0.5 ) ;
2014-01-13 17:37:09 -05:00
return true ;
}
break ;
}
default : break ;
}
return false ;
}
2014-01-18 15:58:26 -05:00
bool cMinecart : : TestEntityCollision ( NIBBLETYPE a_RailMeta )
{
2014-01-19 13:42:05 -05:00
cMinecartCollisionCallback MinecartCollisionCallback ( GetPosition ( ) , GetHeight ( ) , GetWidth ( ) , GetUniqueID ( ) , ( ( m_Attachee = = NULL ) ? - 1 : m_Attachee - > GetUniqueID ( ) ) ) ;
int ChunkX , ChunkZ ;
2014-04-17 13:50:25 -04:00
cChunkDef : : BlockToChunk ( POSX_TOINT , POSZ_TOINT , ChunkX , ChunkZ ) ;
2014-01-19 13:42:05 -05:00
m_World - > ForEachEntityInChunk ( ChunkX , ChunkZ , MinecartCollisionCallback ) ;
if ( ! MinecartCollisionCallback . FoundIntersection ( ) )
{
return false ;
}
2014-01-18 15:58:26 -05:00
switch ( a_RailMeta )
{
case E_META_RAIL_ZM_ZP :
{
2014-01-19 13:42:05 -05:00
if ( MinecartCollisionCallback . GetCollidedEntityPosition ( ) . z > = GetPosZ ( ) )
2014-01-18 15:58:26 -05:00
{
2014-01-19 13:42:05 -05:00
if ( ( - GetSpeedZ ( ) * 0.4 ) < 0.01 )
2014-01-18 15:58:26 -05:00
{
2014-01-19 13:42:05 -05:00
AddSpeedZ ( - 4 ) ;
2014-01-18 15:58:26 -05:00
}
else
{
2014-01-19 13:42:05 -05:00
SetSpeedZ ( - GetSpeedZ ( ) * 0.4 ) ;
2014-01-18 15:58:26 -05:00
}
}
2014-01-19 13:42:05 -05:00
else
{
if ( ( GetSpeedZ ( ) * 0.4 ) < 0.01 )
{
AddSpeedZ ( 4 ) ;
}
else
{
SetSpeedZ ( GetSpeedZ ( ) * 0.4 ) ;
}
}
return true ;
2014-01-18 15:58:26 -05:00
}
case E_META_RAIL_XM_XP :
{
2014-01-19 13:42:05 -05:00
if ( MinecartCollisionCallback . GetCollidedEntityPosition ( ) . x > = GetPosX ( ) )
{
if ( ( - GetSpeedX ( ) * 0.4 ) < 0.01 )
{
AddSpeedX ( - 4 ) ;
}
else
{
SetSpeedX ( - GetSpeedX ( ) * 0.4 ) ;
}
}
else
{
if ( ( GetSpeedX ( ) * 0.4 ) < 0.01 )
{
AddSpeedX ( 4 ) ;
}
else
{
SetSpeedX ( GetSpeedX ( ) * 0.4 ) ;
}
}
return true ;
2014-07-17 16:59:02 -04:00
}
2014-01-18 15:58:26 -05:00
case E_META_RAIL_CURVED_ZM_XM :
2014-08-13 12:53:23 -04:00
case E_META_RAIL_CURVED_ZP_XP :
{
2014-08-14 08:29:46 -04:00
Vector3d Distance = MinecartCollisionCallback . GetCollidedEntityPosition ( ) - Vector3d ( GetPosX ( ) , 0 , GetPosZ ( ) ) ;
2014-08-13 12:53:23 -04:00
2014-08-15 07:40:56 -04:00
// Prevent division by small numbers
2014-09-22 03:22:36 -04:00
if ( std : : abs ( Distance . z ) < 0.001 )
2014-08-15 11:54:43 -04:00
{
Distance . z = 0.001 ;
}
2014-08-13 13:18:11 -04:00
2014-08-15 07:40:56 -04:00
/* Check to which side the minecart is to be pushed.
Let ' s consider a z - x - coordinate system where the minecart is the center ( 0 / 0 ) .
2014-08-15 08:00:51 -04:00
The minecart moves along the line x = - z , the perpendicular line to this is x = z .
2014-08-15 07:43:45 -04:00
In order to decide to which side the minecart is to be pushed , it must be checked on what side of the perpendicular line the pushing entity is located . */
2014-08-14 08:29:46 -04:00
if (
( ( Distance . z > 0 ) & & ( ( Distance . x / Distance . z ) > = 1 ) ) | |
( ( Distance . z < 0 ) & & ( ( Distance . x / Distance . z ) < = 1 ) )
)
2014-08-17 19:57:44 -04:00
{
2014-08-24 09:03:02 -04:00
// Moving -X +Z
2014-08-30 16:11:09 -04:00
if ( ( - GetSpeedX ( ) * 0.4 / sqrt ( 2.0 ) ) < 0.01 )
2014-08-17 19:57:44 -04:00
{
2014-08-24 09:03:02 -04:00
// ~ SpeedX >= 0 Immobile or not moving in the "right" direction. Give it a bump!
2014-08-30 16:11:09 -04:00
AddSpeedX ( - 4 / sqrt ( 2.0 ) ) ;
AddSpeedZ ( 4 / sqrt ( 2.0 ) ) ;
2014-08-13 12:53:23 -04:00
}
2014-08-17 19:57:44 -04:00
else
{
2014-08-24 09:03:02 -04:00
// ~ SpeedX < 0 Moving in the "right" direction. Only accelerate it a bit.
2014-08-30 16:11:09 -04:00
SetSpeedX ( GetSpeedX ( ) * 0.4 / sqrt ( 2.0 ) ) ;
SetSpeedZ ( GetSpeedZ ( ) * 0.4 / sqrt ( 2.0 ) ) ;
2014-08-13 12:53:23 -04:00
}
2014-08-17 19:57:44 -04:00
}
2014-08-30 16:11:09 -04:00
else if ( ( GetSpeedX ( ) * 0.4 / sqrt ( 2.0 ) ) < 0.01 )
2014-08-17 19:57:44 -04:00
{
2014-08-28 10:04:26 -04:00
// Moving +X -Z
2014-08-24 09:03:02 -04:00
// ~ SpeedX <= 0 Immobile or not moving in the "right" direction
2014-08-30 16:11:09 -04:00
AddSpeedX ( 4 / sqrt ( 2.0 ) ) ;
AddSpeedZ ( - 4 / sqrt ( 2.0 ) ) ;
2014-08-13 13:47:43 -04:00
}
2014-08-17 19:57:44 -04:00
else
{
2014-08-24 09:03:02 -04:00
// ~ SpeedX > 0 Moving in the "right" direction
2014-08-30 16:11:09 -04:00
SetSpeedX ( GetSpeedX ( ) * 0.4 / sqrt ( 2.0 ) ) ;
SetSpeedZ ( GetSpeedZ ( ) * 0.4 / sqrt ( 2.0 ) ) ;
2014-08-13 12:53:23 -04:00
}
break ;
}
2014-01-18 15:58:26 -05:00
case E_META_RAIL_CURVED_ZM_XP :
case E_META_RAIL_CURVED_ZP_XM :
{
2014-08-14 08:29:46 -04:00
Vector3d Distance = MinecartCollisionCallback . GetCollidedEntityPosition ( ) - Vector3d ( GetPosX ( ) , 0 , GetPosZ ( ) ) ;
2014-08-13 12:53:23 -04:00
2014-08-15 07:40:56 -04:00
// Prevent division by small numbers
2014-09-22 03:22:36 -04:00
if ( std : : abs ( Distance . z ) < 0.001 )
2014-08-15 11:54:43 -04:00
{
Distance . z = 0.001 ;
}
2014-08-13 13:16:00 -04:00
2014-08-15 07:40:56 -04:00
/* Check to which side the minecart is to be pushed.
Let ' s consider a z - x - coordinate system where the minecart is the center ( 0 / 0 ) .
2014-08-15 08:00:51 -04:00
The minecart moves along the line x = z , the perpendicular line to this is x = - z .
2014-08-15 07:40:56 -04:00
In order to decide to which side the minecart is to be pushed , it must be checked on what side of the perpendicular line the pushing entity is located . */
2014-08-17 19:57:44 -04:00
if (
2014-08-14 08:29:46 -04:00
( ( Distance . z > 0 ) & & ( ( Distance . x / Distance . z ) < = - 1 ) ) | |
( ( Distance . z < 0 ) & & ( ( Distance . x / Distance . z ) > = - 1 ) )
)
2014-08-13 12:53:23 -04:00
{
2014-08-24 09:03:02 -04:00
// Moving +X +Z
2014-08-17 19:57:44 -04:00
if ( ( GetSpeedX ( ) * 0.4 ) < 0.01 )
{
2014-08-24 09:03:02 -04:00
// ~ SpeedX <= 0 Immobile or not moving in the "right" direction
2014-08-30 16:11:09 -04:00
AddSpeedX ( 4 / sqrt ( 2.0 ) ) ;
AddSpeedZ ( 4 / sqrt ( 2.0 ) ) ;
2014-08-13 12:53:23 -04:00
}
2014-08-17 19:57:44 -04:00
else
{
2014-08-24 09:03:02 -04:00
// ~ SpeedX > 0 Moving in the "right" direction
2014-08-30 16:11:09 -04:00
SetSpeedX ( GetSpeedX ( ) * 0.4 / sqrt ( 2.0 ) ) ;
SetSpeedZ ( GetSpeedZ ( ) * 0.4 / sqrt ( 2.0 ) ) ;
2014-08-13 12:53:23 -04:00
}
2014-08-17 19:57:44 -04:00
}
else if ( ( - GetSpeedX ( ) * 0.4 ) < 0.01 )
{
2014-08-24 09:03:02 -04:00
// Moving -X -Z
// ~ SpeedX >= 0 Immobile or not moving in the "right" direction
2014-08-30 16:11:09 -04:00
AddSpeedX ( - 4 / sqrt ( 2.0 ) ) ;
AddSpeedZ ( - 4 / sqrt ( 2.0 ) ) ;
2014-08-13 13:47:43 -04:00
}
2014-08-17 19:57:44 -04:00
else
{
2014-08-24 09:03:02 -04:00
// ~ SpeedX < 0 Moving in the "right" direction
2014-08-30 16:11:09 -04:00
SetSpeedX ( GetSpeedX ( ) * 0.4 / sqrt ( 2.0 ) ) ;
SetSpeedZ ( GetSpeedZ ( ) * 0.4 / sqrt ( 2.0 ) ) ;
2014-08-13 12:53:23 -04:00
}
2014-01-18 15:58:26 -05:00
break ;
}
default : break ;
}
2014-01-19 13:42:05 -05:00
2014-01-18 15:58:26 -05:00
return false ;
}
2014-01-13 17:37:09 -05:00
2014-04-25 18:32:30 -04:00
bool cMinecart : : DoTakeDamage ( TakeDamageInfo & TDI )
2013-09-02 07:01:49 -04:00
{
2014-01-18 15:58:26 -05:00
if ( ( TDI . Attacker ! = NULL ) & & TDI . Attacker - > IsPlayer ( ) & & ( ( cPlayer * ) TDI . Attacker ) - > IsGameModeCreative ( ) )
2014-01-12 08:28:37 -05:00
{
Destroy ( ) ;
2014-07-17 16:15:34 -04:00
TDI . FinalDamage = GetMaxHealth ( ) ; // Instant hit for creative
2014-04-25 18:32:30 -04:00
SetInvulnerableTicks ( 0 ) ;
return super : : DoTakeDamage ( TDI ) ; // No drops for creative
2014-01-12 08:28:37 -05:00
}
2013-10-08 14:20:49 -04:00
m_LastDamage = TDI . FinalDamage ;
2014-04-25 18:32:30 -04:00
if ( ! super : : DoTakeDamage ( TDI ) )
{
return false ;
}
2013-09-02 07:01:49 -04:00
2013-10-08 14:20:49 -04:00
m_World - > BroadcastEntityMetadata ( * this ) ;
2013-09-09 13:55:42 -04:00
if ( GetHealth ( ) < = 0 )
2013-09-02 07:01:49 -04:00
{
2014-01-12 08:28:37 -05:00
Destroy ( ) ;
2013-10-08 14:20:49 -04:00
cItems Drops ;
switch ( m_Payload )
{
case mpNone :
{
Drops . push_back ( cItem ( E_ITEM_MINECART , 1 , 0 ) ) ;
break ;
}
case mpChest :
{
Drops . push_back ( cItem ( E_ITEM_CHEST_MINECART , 1 , 0 ) ) ;
break ;
}
case mpFurnace :
{
Drops . push_back ( cItem ( E_ITEM_FURNACE_MINECART , 1 , 0 ) ) ;
break ;
}
case mpTNT :
{
2013-10-09 16:02:59 -04:00
Drops . push_back ( cItem ( E_ITEM_MINECART_WITH_TNT , 1 , 0 ) ) ;
2013-10-08 14:20:49 -04:00
break ;
}
case mpHopper :
{
2013-10-09 16:02:59 -04:00
Drops . push_back ( cItem ( E_ITEM_MINECART_WITH_HOPPER , 1 , 0 ) ) ;
2013-10-08 14:20:49 -04:00
break ;
}
default :
{
ASSERT ( ! " Unhandled minecart type when spawning pickup! " ) ;
2014-04-25 18:32:30 -04:00
return true ;
2013-10-08 14:20:49 -04:00
}
}
m_World - > SpawnItemPickups ( Drops , GetPosX ( ) , GetPosY ( ) , GetPosZ ( ) ) ;
2013-09-02 07:01:49 -04:00
}
2014-04-25 18:32:30 -04:00
return true ;
2013-07-29 07:13:03 -04:00
}
2014-01-13 17:37:09 -05:00
void cMinecart : : Destroyed ( )
{
if ( m_bIsOnDetectorRail )
{
m_World - > SetBlock ( m_DetectorRailPosition . x , m_DetectorRailPosition . y , m_DetectorRailPosition . z , E_BLOCK_DETECTOR_RAIL , m_World - > GetBlockMeta ( m_DetectorRailPosition ) & 0x07 ) ;
}
}
2014-07-17 16:15:34 -04:00
////////////////////////////////////////////////////////////////////////////////
2014-01-12 12:04:41 -05:00
// cRideableMinecart:
2013-07-29 07:13:03 -04:00
2014-01-12 12:04:41 -05:00
cRideableMinecart : : cRideableMinecart ( double a_X , double a_Y , double a_Z , const cItem & a_Content , int a_Height ) :
2014-01-12 09:27:50 -05:00
super ( mpNone , a_X , a_Y , a_Z ) ,
m_Content ( a_Content ) ,
m_Height ( a_Height )
2013-07-29 07:13:03 -04:00
{
}
2014-01-12 12:04:41 -05:00
void cRideableMinecart : : OnRightClicked ( cPlayer & a_Player )
2013-07-29 07:13:03 -04:00
{
2014-09-01 15:05:45 -04:00
super : : OnRightClicked ( a_Player ) ;
2013-07-29 07:13:03 -04:00
if ( m_Attachee ! = NULL )
{
if ( m_Attachee - > GetUniqueID ( ) = = a_Player . GetUniqueID ( ) )
{
// This player is already sitting in, they want out.
a_Player . Detach ( ) ;
return ;
}
if ( m_Attachee - > IsPlayer ( ) )
{
// Another player is already sitting in here, cannot attach
return ;
}
// Detach whatever is sitting in this minecart now:
m_Attachee - > Detach ( ) ;
}
// Attach the player to this minecart
a_Player . AttachTo ( this ) ;
}
2014-07-17 16:15:34 -04:00
////////////////////////////////////////////////////////////////////////////////
2013-07-29 07:13:03 -04:00
// cMinecartWithChest:
cMinecartWithChest : : cMinecartWithChest ( double a_X , double a_Y , double a_Z ) :
2014-09-12 18:18:02 -04:00
super ( mpChest , a_X , a_Y , a_Z ) ,
2014-09-28 08:11:41 -04:00
cEntityWindowOwner ( this ) ,
m_Contents ( ContentsWidth , ContentsHeight )
2013-07-29 07:13:03 -04:00
{
2014-09-12 18:18:02 -04:00
m_Contents . AddListener ( * this ) ;
2013-07-29 07:13:03 -04:00
}
2014-09-12 18:18:02 -04:00
void cMinecartWithChest : : OnRightClicked ( cPlayer & a_Player )
2013-07-29 07:13:03 -04:00
{
2014-09-12 18:18:02 -04:00
// If the window is not created, open it anew:
cWindow * Window = GetWindow ( ) ;
if ( Window = = NULL )
{
OpenNewWindow ( ) ;
Window = GetWindow ( ) ;
}
// Open the window for the player:
if ( Window ! = NULL )
{
if ( a_Player . GetWindow ( ) ! = Window )
{
a_Player . OpenWindow ( Window ) ;
}
}
2013-07-29 07:13:03 -04:00
}
2014-09-12 18:18:02 -04:00
void cMinecartWithChest : : OpenNewWindow ( )
{
OpenWindow ( new cMinecartWithChestWindow ( this ) ) ;
}
void cMinecartWithChest : : Destroyed ( )
2013-07-29 07:13:03 -04:00
{
2014-09-12 18:18:02 -04:00
cItems Pickups ;
m_Contents . CopyToItems ( Pickups ) ;
GetWorld ( ) - > SpawnItemPickups ( Pickups , GetPosX ( ) , GetPosY ( ) + 1 , GetPosZ ( ) , 4 ) ;
2013-07-29 07:13:03 -04:00
}
2014-07-17 16:15:34 -04:00
////////////////////////////////////////////////////////////////////////////////
2013-07-29 07:13:03 -04:00
// cMinecartWithFurnace:
cMinecartWithFurnace : : cMinecartWithFurnace ( double a_X , double a_Y , double a_Z ) :
2013-10-08 14:20:49 -04:00
super ( mpFurnace , a_X , a_Y , a_Z ) ,
2014-02-05 12:43:49 -05:00
m_FueledTimeLeft ( - 1 ) ,
m_IsFueled ( false )
2013-07-29 07:13:03 -04:00
{
}
void cMinecartWithFurnace : : OnRightClicked ( cPlayer & a_Player )
{
2013-10-08 14:20:49 -04:00
if ( a_Player . GetEquippedItem ( ) . m_ItemType = = E_ITEM_COAL )
{
if ( ! a_Player . IsGameModeCreative ( ) )
{
a_Player . GetInventory ( ) . RemoveOneEquippedItem ( ) ;
}
2014-07-17 16:15:34 -04:00
if ( ! m_IsFueled ) // We don't want to change the direction by right clicking it.
2014-01-15 08:03:09 -05:00
{
AddSpeed ( a_Player . GetLookVector ( ) . x , 0 , a_Player . GetLookVector ( ) . z ) ;
}
2013-10-08 14:20:49 -04:00
m_IsFueled = true ;
2014-07-17 16:15:34 -04:00
m_FueledTimeLeft = m_FueledTimeLeft + 600 ; // The minecart will be active 600 more ticks.
2013-10-08 14:20:49 -04:00
m_World - > BroadcastEntityMetadata ( * this ) ;
}
2013-07-29 07:13:03 -04:00
}
2014-01-15 08:03:09 -05:00
void cMinecartWithFurnace : : Tick ( float a_Dt , cChunk & a_Chunk )
{
super : : Tick ( a_Dt , a_Chunk ) ;
if ( m_IsFueled )
{
2014-01-15 08:38:54 -05:00
m_FueledTimeLeft - - ;
if ( m_FueledTimeLeft < 0 )
{
m_IsFueled = false ;
m_World - > BroadcastEntityMetadata ( * this ) ;
return ;
}
2014-01-15 08:03:09 -05:00
if ( GetSpeed ( ) . Length ( ) > 6 )
{
return ;
}
AddSpeed ( GetSpeed ( ) / 4 ) ;
}
}
2014-07-17 16:15:34 -04:00
////////////////////////////////////////////////////////////////////////////////
2013-08-16 06:23:24 -04:00
// cMinecartWithTNT:
cMinecartWithTNT : : cMinecartWithTNT ( double a_X , double a_Y , double a_Z ) :
super ( mpTNT , a_X , a_Y , a_Z )
{
}
// TODO: Make it activate when passing over activator rail
2014-07-17 16:15:34 -04:00
////////////////////////////////////////////////////////////////////////////////
2013-08-16 06:23:24 -04:00
// cMinecartWithHopper:
cMinecartWithHopper : : cMinecartWithHopper ( double a_X , double a_Y , double a_Z ) :
super ( mpHopper , a_X , a_Y , a_Z )
{
}
// TODO: Make it suck up blocks and travel further than any other cart and physics and put and take blocks
2014-02-05 12:43:49 -05:00
// AND AVARYTHING!!