2012-06-14 09:06:06 -04:00
# include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
2012-09-23 18:09:57 -04:00
# include "Entity.h"
# include "World.h"
# include "Server.h"
# include "Root.h"
2012-06-14 09:06:06 -04:00
# include "Vector3d.h"
# include "Matrix4f.h"
2012-09-23 18:09:57 -04:00
# include "ReferenceManager.h"
# include "ClientHandle.h"
2013-04-22 03:18:03 -04:00
# include "Tracer.h"
# include "Chunk.h"
# include "Simulator/FluidSimulator.h"
2012-06-14 09:06:06 -04:00
int cEntity : : m_EntityCount = 0 ;
cCriticalSection cEntity : : m_CSCount ;
2012-12-21 07:52:14 -05:00
cEntity : : cEntity ( eEntityType a_EntityType , double a_X , double a_Y , double a_Z )
2013-03-03 14:05:11 -05:00
: m_UniqueID ( 0 )
, m_AttachedTo ( NULL )
, m_Attachee ( NULL )
, m_Referencers ( new cReferenceManager ( cReferenceManager : : RFMNGR_REFERENCERS ) )
, m_References ( new cReferenceManager ( cReferenceManager : : RFMNGR_REFERENCES ) )
2013-04-02 02:48:31 -04:00
, m_HeadYaw ( 0.0 )
2013-04-28 01:05:10 -04:00
, m_Rot ( 0.0 , 0.0 , 0.0 )
2013-03-03 14:05:11 -05:00
, m_Pos ( a_X , a_Y , a_Z )
2013-04-28 14:54:43 -04:00
, m_Mass ( 0.001 ) //Default 1g
2013-04-02 02:48:31 -04:00
, m_bDirtyHead ( true )
2013-03-03 14:05:11 -05:00
, m_bDirtyOrientation ( true )
2013-03-22 02:33:10 -04:00
, m_bDirtyPosition ( true )
, m_bDirtySpeed ( true )
2013-04-22 03:18:03 -04:00
, m_bOnGround ( false )
, m_Gravity ( - 9.81f )
2013-04-13 17:02:10 -04:00
, m_IsInitialized ( false )
2013-03-22 02:33:10 -04:00
, m_LastPosX ( 0.0 )
, m_LastPosY ( 0.0 )
, m_LastPosZ ( 0.0 )
, m_TimeLastTeleportPacket ( 0 )
, m_TimeLastMoveReltPacket ( 0 )
, m_TimeLastSpeedPacket ( 0 )
2012-12-21 07:52:14 -05:00
, m_EntityType ( a_EntityType )
, m_World ( NULL )
2012-08-28 17:59:49 -04:00
, m_FireDamageInterval ( 0.f )
, m_BurnPeriod ( 0.f )
2013-04-22 03:18:03 -04:00
, m_WaterSpeed ( 0.0 , 0.0 , 0.0 )
2012-06-14 09:06:06 -04:00
{
cCSLock Lock ( m_CSCount ) ;
m_EntityCount + + ;
m_UniqueID = m_EntityCount ;
}
cEntity : : ~ cEntity ( )
{
2013-04-13 17:02:10 -04:00
ASSERT ( ! m_World - > HasEntity ( m_UniqueID ) ) ; // Before deleting, the entity needs to have been removed from the world
2013-03-02 14:57:09 -05:00
LOGD ( " Deleting entity %d at pos {%.2f, %.2f, %.2f} ~ [%d, %d]; ptr %p " ,
2012-06-14 09:06:06 -04:00
m_UniqueID ,
2013-03-02 14:57:09 -05:00
m_Pos . x , m_Pos . y , m_Pos . z ,
2012-06-14 09:06:06 -04:00
( int ) ( m_Pos . x / cChunkDef : : Width ) , ( int ) ( m_Pos . z / cChunkDef : : Width ) ,
this
2013-04-02 02:48:31 -04:00
) ;
2013-03-03 14:05:11 -05:00
if ( m_AttachedTo ! = NULL )
{
Detach ( ) ;
}
if ( m_Attachee ! = NULL )
{
m_Attachee - > Detach ( ) ;
}
2013-04-02 02:48:31 -04:00
2013-04-13 17:02:10 -04:00
if ( m_IsInitialized )
2012-06-14 09:06:06 -04:00
{
2013-04-13 17:02:10 -04:00
LOGWARNING ( " ERROR: Entity deallocated without being destroyed " ) ;
2012-06-14 09:06:06 -04:00
ASSERT ( ! " Entity deallocated without being destroyed or unlinked " ) ;
}
delete m_Referencers ;
delete m_References ;
}
2013-02-02 18:55:29 -05:00
const char * cEntity : : GetClass ( void ) const
{
return " cEntity " ;
}
const char * cEntity : : GetClassStatic ( void )
{
return " cEntity " ;
}
2012-08-24 03:58:26 -04:00
2012-12-21 07:21:20 -05:00
const char * cEntity : : GetParentClass ( void ) const
{
return " " ;
}
2012-08-24 03:58:26 -04:00
void cEntity : : Initialize ( cWorld * a_World )
2012-06-14 09:06:06 -04:00
{
2013-04-13 17:02:10 -04:00
LOGD ( " Initializing entity #%d (%s) at {%.02f, %.02f, %.02f} " ,
m_UniqueID , GetClass ( ) , m_Pos . x , m_Pos . y , m_Pos . z
) ;
m_IsInitialized = true ;
2012-06-14 09:06:06 -04:00
m_World = a_World ;
2013-03-03 14:05:11 -05:00
m_World - > AddEntity ( this ) ;
2012-06-14 09:06:06 -04:00
}
2013-04-13 17:02:10 -04:00
void cEntity : : WrapHeadYaw ( void )
2013-04-02 02:48:31 -04:00
{
2013-04-13 17:02:10 -04:00
while ( m_HeadYaw > 180.f ) m_HeadYaw - = 360.f ; // Wrap it
while ( m_HeadYaw < - 180.f ) m_HeadYaw + = 360.f ;
2013-04-02 02:48:31 -04:00
}
2013-04-13 17:02:10 -04:00
void cEntity : : WrapRotation ( void )
2012-06-14 09:06:06 -04:00
{
2013-04-13 17:02:10 -04:00
while ( m_Rot . x > 180.f ) m_Rot . x - = 360.f ; // Wrap it
while ( m_Rot . x < - 180.f ) m_Rot . x + = 360.f ;
while ( m_Rot . y > 180.f ) m_Rot . y - = 360.f ;
while ( m_Rot . y < - 180.f ) m_Rot . y + = 360.f ;
2012-06-14 09:06:06 -04:00
}
2013-04-13 17:02:10 -04:00
void cEntity : : WrapSpeed ( void )
2013-03-22 02:33:10 -04:00
{
2013-04-13 17:02:10 -04:00
// There shoudn't be a need for flipping the flag on because this function is called
// after any update, so the flag is already turned on
2013-04-28 00:15:45 -04:00
if ( m_Speed . x > 78.0f ) m_Speed . x = 78.0f ;
else if ( m_Speed . x < - 78.0f ) m_Speed . x = - 78.0f ;
if ( m_Speed . y > 78.0f ) m_Speed . y = 78.0f ;
else if ( m_Speed . y < - 78.0f ) m_Speed . y = - 78.0f ;
if ( m_Speed . z > 78.0f ) m_Speed . z = 78.0f ;
else if ( m_Speed . z < - 78.0f ) m_Speed . z = - 78.0f ;
2013-03-22 02:33:10 -04:00
}
2012-06-14 09:06:06 -04:00
2013-04-13 17:02:10 -04:00
void cEntity : : Destroy ( void )
2012-06-14 09:06:06 -04:00
{
2013-04-13 17:02:10 -04:00
if ( ! m_IsInitialized )
2012-06-14 09:06:06 -04:00
{
return ;
}
2012-08-19 17:14:45 -04:00
m_World - > BroadcastDestroyEntity ( * this ) ;
2013-04-02 02:48:31 -04:00
2013-04-13 17:02:10 -04:00
m_IsInitialized = false ;
2012-06-14 09:06:06 -04:00
Destroyed ( ) ;
}
2013-04-13 17:02:10 -04:00
void cEntity : : Tick ( float a_Dt , cChunk & a_Chunk )
2012-06-14 09:06:06 -04:00
{
2013-03-03 14:05:11 -05:00
if ( m_AttachedTo ! = NULL )
{
if ( ( m_Pos - m_AttachedTo - > GetPosition ( ) ) . Length ( ) > 0.5 )
{
SetPosition ( m_AttachedTo - > GetPosition ( ) ) ;
}
}
else
{
2013-04-13 17:02:10 -04:00
HandlePhysics ( a_Dt , a_Chunk ) ;
2013-03-03 14:05:11 -05:00
}
}
2013-04-22 03:18:03 -04:00
void cEntity : : HandlePhysics ( float a_Dt , cChunk & a_Chunk )
{
//TODO Add collision detection with entities.
a_Dt / = 1000 ;
Vector3d NextPos = Vector3d ( GetPosX ( ) , GetPosY ( ) , GetPosZ ( ) ) ;
Vector3d NextSpeed = Vector3d ( GetSpeedX ( ) , GetSpeedY ( ) , GetSpeedZ ( ) ) ;
int BlockX = ( int ) floor ( NextPos . x ) ;
int BlockY = ( int ) floor ( NextPos . y ) ;
int BlockZ = ( int ) floor ( NextPos . z ) ;
//Make sure we got the correct chunk and a valid one. No one ever knows...
cChunk * NextChunk = a_Chunk . GetNeighborChunk ( BlockX , BlockZ ) ;
if ( NextChunk ! = NULL )
{
int RelBlockX = BlockX - ( NextChunk - > GetPosX ( ) * cChunkDef : : Width ) ;
int RelBlockZ = BlockZ - ( NextChunk - > GetPosZ ( ) * cChunkDef : : Width ) ;
BLOCKTYPE BlockIn = NextChunk - > GetBlock ( RelBlockX , BlockY , RelBlockZ ) ;
if ( BlockIn = = E_BLOCK_AIR | | IsBlockWater ( BlockIn ) | | BlockIn = = E_BLOCK_FIRE | | IsBlockLava ( BlockIn ) ) // If not in ground itself or in water or in fire or in lava
{
if ( m_bOnGround ) // check if it's still on the ground
{
BLOCKTYPE BlockBelow = NextChunk - > GetBlock ( RelBlockX , BlockY - 1 , RelBlockZ ) ;
if ( BlockBelow = = E_BLOCK_AIR | | IsBlockWater ( BlockBelow ) | | BlockBelow = = E_BLOCK_FIRE | | IsBlockLava ( BlockBelow ) ) //Check if block below is air or water.
{
m_bOnGround = false ;
}
}
}
else
{
//Push out entity.
m_bOnGround = true ;
NextPos . y + = 0.2 ;
LOGD ( " Entity #%d (%s) is inside a block at {%d,%d,%d} " ,
m_UniqueID , GetClass ( ) , BlockX , BlockY , BlockZ ) ;
}
if ( ! m_bOnGround )
{
float fallspeed ;
if ( ! IsBlockWater ( BlockIn ) )
{
fallspeed = m_Gravity * a_Dt ;
}
else
{
fallspeed = - 3.0f * a_Dt ; //Fall slower in water.
}
NextSpeed . y + = fallspeed ;
}
else
{
//Friction
if ( NextSpeed . SqrLength ( ) > 0.0004f )
{
NextSpeed . x * = 0.7f / ( 1 + a_Dt ) ;
if ( fabs ( NextSpeed . x ) < 0.05 ) NextSpeed . x = 0 ;
NextSpeed . z * = 0.7f / ( 1 + a_Dt ) ;
if ( fabs ( NextSpeed . z ) < 0.05 ) NextSpeed . z = 0 ;
}
}
//Get water direction
Direction WaterDir = m_World - > GetWaterSimulator ( ) - > GetFlowingDirection ( BlockX , BlockY , BlockZ ) ;
m_WaterSpeed * = 0.9f ; //Reduce speed each tick
switch ( WaterDir )
{
case X_PLUS :
m_WaterSpeed . x = 1.f ;
m_bOnGround = false ;
break ;
case X_MINUS :
m_WaterSpeed . x = - 1.f ;
m_bOnGround = false ;
break ;
case Z_PLUS :
m_WaterSpeed . z = 1.f ;
m_bOnGround = false ;
break ;
case Z_MINUS :
m_WaterSpeed . z = - 1.f ;
m_bOnGround = false ;
break ;
default :
break ;
}
if ( fabs ( m_WaterSpeed . x ) < 0.05 )
{
m_WaterSpeed . x = 0 ;
}
if ( fabs ( m_WaterSpeed . z ) < 0.05 )
{
m_WaterSpeed . z = 0 ;
}
NextSpeed + = m_WaterSpeed ;
if ( NextSpeed . SqrLength ( ) > 0.f )
{
cTracer Tracer ( GetWorld ( ) ) ;
int Ret = Tracer . Trace ( NextPos , NextSpeed , 2 ) ;
if ( Ret ) // Oh noez! we hit something
{
// Set to hit position
if ( ( Tracer . RealHit - NextPos ) . SqrLength ( ) < = ( NextSpeed * a_Dt ) . SqrLength ( ) )
{
if ( Ret = = 1 )
{
if ( Tracer . HitNormal . x ! = 0.f ) NextSpeed . x = 0.f ;
if ( Tracer . HitNormal . y ! = 0.f ) NextSpeed . y = 0.f ;
if ( Tracer . HitNormal . z ! = 0.f ) NextSpeed . z = 0.f ;
if ( Tracer . HitNormal . y > 0 ) // means on ground
{
m_bOnGround = true ;
}
}
NextPos . Set ( Tracer . RealHit . x , Tracer . RealHit . y , Tracer . RealHit . z ) ;
NextPos . x + = Tracer . HitNormal . x * 0.5f ;
NextPos . z + = Tracer . HitNormal . z * 0.5f ;
}
else
NextPos + = ( NextSpeed * a_Dt ) ;
}
else
{ // We didn't hit anything, so move =]
NextPos + = ( NextSpeed * a_Dt ) ;
}
}
BlockX = ( int ) floor ( NextPos . x ) ;
BlockZ = ( int ) floor ( NextPos . z ) ;
NextChunk = NextChunk - > GetNeighborChunk ( BlockX , BlockZ ) ;
//See if we can commit our changes. If not, we will discard them.
if ( NextChunk ! = NULL )
{
if ( NextPos . x ! = GetPosX ( ) ) SetPosX ( NextPos . x ) ;
if ( NextPos . y ! = GetPosY ( ) ) SetPosY ( NextPos . y ) ;
if ( NextPos . z ! = GetPosZ ( ) ) SetPosZ ( NextPos . z ) ;
if ( NextSpeed . x ! = GetSpeedX ( ) ) SetSpeedX ( NextSpeed . x ) ;
if ( NextSpeed . y ! = GetSpeedY ( ) ) SetSpeedY ( NextSpeed . y ) ;
if ( NextSpeed . z ! = GetSpeedZ ( ) ) SetSpeedZ ( NextSpeed . z ) ;
}
}
}
2013-03-22 02:33:10 -04:00
void cEntity : : BroadcastMovementUpdate ( const cClientHandle * a_Exclude )
{
2013-04-07 02:53:17 -04:00
//We need to keep updating the clients when there is movement or if there was a change in speed and after 2 ticks
if ( ( m_Speed . SqrLength ( ) > 0.0004f | | m_bDirtySpeed ) & & ( m_World - > GetWorldAge ( ) - m_TimeLastSpeedPacket > = 2 ) )
{
m_World - > BroadcastEntVelocity ( * this , a_Exclude ) ;
m_bDirtySpeed = false ;
m_TimeLastSpeedPacket = m_World - > GetWorldAge ( ) ;
}
//Have to process position related packets this every two ticks
2013-04-02 02:48:31 -04:00
if ( m_World - > GetWorldAge ( ) % 2 = = 0 )
2013-03-22 02:33:10 -04:00
{
2013-04-07 02:53:17 -04:00
int DiffX = ( int ) ( floor ( GetPosX ( ) * 32.0 ) - floor ( m_LastPosX * 32.0 ) ) ;
int DiffY = ( int ) ( floor ( GetPosY ( ) * 32.0 ) - floor ( m_LastPosY * 32.0 ) ) ;
int DiffZ = ( int ) ( floor ( GetPosZ ( ) * 32.0 ) - floor ( m_LastPosZ * 32.0 ) ) ;
Int64 DiffTeleportPacket = m_World - > GetWorldAge ( ) - m_TimeLastTeleportPacket ;
2013-04-02 02:48:31 -04:00
// 4 blocks is max Relative So if the Diff is greater than 127 or. Send an absolute position every 20 seconds
if ( DiffTeleportPacket > = 400 | |
( ( DiffX > 127 ) | | ( DiffX < - 128 ) | |
( DiffY > 127 ) | | ( DiffY < - 128 ) | |
( DiffZ > 127 ) | | ( DiffZ < - 128 ) ) )
2013-03-22 02:33:10 -04:00
{
2013-04-02 02:48:31 -04:00
//
2013-03-22 02:33:10 -04:00
m_World - > BroadcastTeleportEntity ( * this , a_Exclude ) ;
m_TimeLastTeleportPacket = m_World - > GetWorldAge ( ) ;
2013-04-02 02:48:31 -04:00
m_TimeLastMoveReltPacket = m_TimeLastTeleportPacket ; //Must synchronize.
2013-03-22 02:33:10 -04:00
m_LastPosX = GetPosX ( ) ;
m_LastPosY = GetPosY ( ) ;
m_LastPosZ = GetPosZ ( ) ;
m_bDirtyPosition = false ;
2013-04-02 02:48:31 -04:00
m_bDirtyOrientation = false ;
2013-03-22 02:33:10 -04:00
}
else
{
2013-04-02 02:48:31 -04:00
Int64 DiffMoveRelPacket = m_World - > GetWorldAge ( ) - m_TimeLastMoveReltPacket ;
//if the change is big enough.
if ( ( abs ( DiffX ) > = 4 | | abs ( DiffY ) > = 4 | | abs ( DiffZ ) > = 4 | | DiffMoveRelPacket > = 60 ) & & m_bDirtyPosition )
2013-03-22 02:33:10 -04:00
{
if ( m_bDirtyOrientation )
{
2013-04-02 02:48:31 -04:00
m_World - > BroadcastEntRelMoveLook ( * this , ( char ) DiffX , ( char ) DiffY , ( char ) DiffZ , a_Exclude ) ;
2013-03-22 02:33:10 -04:00
m_bDirtyOrientation = false ;
}
else
{
2013-04-02 02:48:31 -04:00
m_World - > BroadcastEntRelMove ( * this , ( char ) DiffX , ( char ) DiffY , ( char ) DiffZ , a_Exclude ) ;
2013-03-22 02:33:10 -04:00
}
m_LastPosX = GetPosX ( ) ;
m_LastPosY = GetPosY ( ) ;
m_LastPosZ = GetPosZ ( ) ;
m_bDirtyPosition = false ;
2013-04-02 02:48:31 -04:00
m_TimeLastMoveReltPacket = m_World - > GetWorldAge ( ) ;
2013-03-22 02:33:10 -04:00
}
2013-04-02 02:48:31 -04:00
else
{
if ( m_bDirtyOrientation )
{
m_World - > BroadcastEntLook ( * this , a_Exclude ) ;
m_bDirtyOrientation = false ;
}
}
}
if ( m_bDirtyHead )
{
m_World - > BroadcastEntHeadLook ( * this , a_Exclude ) ;
m_bDirtyHead = false ;
2013-03-22 02:33:10 -04:00
}
}
}
2013-03-03 14:05:11 -05:00
void cEntity : : AttachTo ( cEntity * a_AttachTo )
{
if ( m_AttachedTo = = a_AttachTo )
{
// Already attached to that entity, nothing to do here
return ;
}
2013-04-02 02:48:31 -04:00
2013-03-03 14:05:11 -05:00
// Detach from any previous entity:
Detach ( ) ;
2013-04-02 02:48:31 -04:00
2013-03-03 14:05:11 -05:00
// Attach to the new entity:
m_AttachedTo = a_AttachTo ;
a_AttachTo - > m_Attachee = this ;
m_World - > BroadcastAttachEntity ( * this , a_AttachTo ) ;
}
void cEntity : : Detach ( void )
{
if ( m_AttachedTo = = NULL )
{
// Attached to no entity, our work is done
return ;
}
m_AttachedTo - > m_Attachee = NULL ;
m_AttachedTo = NULL ;
m_World - > BroadcastAttachEntity ( * this , NULL ) ;
2012-12-22 05:15:53 -05:00
}
2012-12-21 07:21:20 -05:00
bool cEntity : : IsA ( const char * a_ClassName ) const
2012-06-14 09:06:06 -04:00
{
2012-12-21 07:21:20 -05:00
return ( strcmp ( a_ClassName , " cEntity " ) = = 0 ) ;
2012-06-14 09:06:06 -04:00
}
//////////////////////////////////////////////////////////////////////////
// Set orientations
2013-03-03 14:05:11 -05:00
void cEntity : : SetRot ( const Vector3f & a_Rot )
2012-06-14 09:06:06 -04:00
{
m_Rot = a_Rot ;
m_bDirtyOrientation = true ;
}
2013-04-02 02:48:31 -04:00
void cEntity : : SetHeadYaw ( double a_HeadYaw )
{
m_HeadYaw = a_HeadYaw ;
m_bDirtyHead = true ;
WrapHeadYaw ( ) ;
}
2013-04-28 14:54:43 -04:00
void cEntity : : SetMass ( double a_Mass )
{
if ( a_Mass > 0 )
{
m_Mass = a_Mass ;
}
else
{
//Make sure that mass is not zero. 1g is the default because we
//have to choose a number. It's perfectly legal to have a mass
//less than 1g as long as is NOT equal or less than zero.
m_Mass = 0.001 ;
}
}
2013-03-09 09:35:43 -05:00
void cEntity : : SetRotation ( double a_Rotation )
2012-06-14 09:06:06 -04:00
{
m_Rot . x = a_Rotation ;
m_bDirtyOrientation = true ;
2013-04-03 01:11:00 -04:00
WrapRotation ( ) ;
2012-06-14 09:06:06 -04:00
}
2013-03-09 09:35:43 -05:00
void cEntity : : SetPitch ( double a_Pitch )
2012-06-14 09:06:06 -04:00
{
m_Rot . y = a_Pitch ;
m_bDirtyOrientation = true ;
2013-04-03 01:11:00 -04:00
WrapRotation ( ) ;
2012-06-14 09:06:06 -04:00
}
2013-03-09 09:35:43 -05:00
void cEntity : : SetRoll ( double a_Roll )
2012-06-14 09:06:06 -04:00
{
m_Rot . z = a_Roll ;
m_bDirtyOrientation = true ;
}
2013-03-09 09:35:43 -05:00
void cEntity : : SetSpeed ( double a_SpeedX , double a_SpeedY , double a_SpeedZ )
{
m_Speed . Set ( a_SpeedX , a_SpeedY , a_SpeedZ ) ;
2013-03-22 02:33:10 -04:00
m_bDirtySpeed = true ;
WrapSpeed ( ) ;
2013-03-09 09:35:43 -05:00
}
2013-03-22 02:33:10 -04:00
void cEntity : : SetSpeedX ( double a_SpeedX )
{
m_Speed . x = a_SpeedX ;
m_bDirtySpeed = true ;
WrapSpeed ( ) ;
}
void cEntity : : SetSpeedY ( double a_SpeedY )
{
m_Speed . y = a_SpeedY ;
m_bDirtySpeed = true ;
WrapSpeed ( ) ;
}
void cEntity : : SetSpeedZ ( double a_SpeedZ )
{
m_Speed . z = a_SpeedZ ;
m_bDirtySpeed = true ;
WrapSpeed ( ) ;
}
2013-03-09 09:35:43 -05:00
2013-03-23 00:33:47 -04:00
void cEntity : : AddPosX ( double a_AddPosX )
{
m_Pos . x + = a_AddPosX ;
m_bDirtyPosition = true ;
}
void cEntity : : AddPosY ( double a_AddPosY )
{
m_Pos . y + = a_AddPosY ;
m_bDirtyPosition = true ;
}
void cEntity : : AddPosZ ( double a_AddPosZ )
{
m_Pos . z + = a_AddPosZ ;
m_bDirtyPosition = true ;
}
void cEntity : : AddPosition ( double a_AddPosX , double a_AddPosY , double a_AddPosZ )
{
m_Pos . x + = a_AddPosX ;
m_Pos . y + = a_AddPosY ;
m_Pos . z + = a_AddPosZ ;
m_bDirtyPosition = true ;
}
void cEntity : : AddSpeed ( double a_AddSpeedX , double a_AddSpeedY , double a_AddSpeedZ )
{
m_Speed . x + = a_AddSpeedX ;
m_Speed . y + = a_AddSpeedY ;
m_Speed . z + = a_AddSpeedZ ;
m_bDirtySpeed = true ;
WrapSpeed ( ) ;
}
void cEntity : : AddSpeedX ( double a_AddSpeedX )
{
m_Speed . x + = a_AddSpeedX ;
m_bDirtySpeed = true ;
WrapSpeed ( ) ;
}
void cEntity : : AddSpeedY ( double a_AddSpeedY )
{
m_Speed . y + = a_AddSpeedY ;
m_bDirtySpeed = true ;
WrapSpeed ( ) ;
}
void cEntity : : AddSpeedZ ( double a_AddSpeedZ )
2013-03-03 14:05:11 -05:00
{
2013-03-23 00:33:47 -04:00
m_Speed . z + = a_AddSpeedZ ;
2013-03-22 02:33:10 -04:00
m_bDirtySpeed = true ;
WrapSpeed ( ) ;
2013-03-03 14:05:11 -05:00
}
2012-06-14 09:06:06 -04:00
//////////////////////////////////////////////////////////////////////////
// Get look vector (this is NOT a rotation!)
2013-03-09 09:35:43 -05:00
Vector3d cEntity : : GetLookVector ( void ) const
2012-06-14 09:06:06 -04:00
{
2013-03-09 09:35:43 -05:00
Matrix4d m ;
2013-03-03 14:05:11 -05:00
m . Init ( Vector3f ( ) , 0 , m_Rot . x , - m_Rot . y ) ;
2013-03-09 09:35:43 -05:00
Vector3d Look = m . Transform ( Vector3d ( 0 , 0 , 1 ) ) ;
2012-06-14 09:06:06 -04:00
return Look ;
}
//////////////////////////////////////////////////////////////////////////
// Set position
2012-12-21 05:59:59 -05:00
void cEntity : : SetPosition ( double a_PosX , double a_PosY , double a_PosZ )
2012-06-14 09:06:06 -04:00
{
2012-12-21 05:59:59 -05:00
m_Pos . Set ( a_PosX , a_PosY , a_PosZ ) ;
2012-06-14 09:06:06 -04:00
m_bDirtyPosition = true ;
}
2012-12-21 05:59:59 -05:00
void cEntity : : SetPosX ( double a_PosX )
2012-06-14 09:06:06 -04:00
{
m_Pos . x = a_PosX ;
m_bDirtyPosition = true ;
}
2012-12-21 05:59:59 -05:00
void cEntity : : SetPosY ( double a_PosY )
2012-06-14 09:06:06 -04:00
{
m_Pos . y = a_PosY ;
m_bDirtyPosition = true ;
}
2012-12-21 05:59:59 -05:00
void cEntity : : SetPosZ ( double a_PosZ )
2012-06-14 09:06:06 -04:00
{
m_Pos . z = a_PosZ ;
m_bDirtyPosition = true ;
}
//////////////////////////////////////////////////////////////////////////
// Reference stuffs
2012-12-21 05:59:59 -05:00
void cEntity : : AddReference ( cEntity * & a_EntityPtr )
2012-06-14 09:06:06 -04:00
{
2013-03-03 14:05:11 -05:00
m_References - > AddReference ( a_EntityPtr ) ;
a_EntityPtr - > ReferencedBy ( a_EntityPtr ) ;
2012-06-14 09:06:06 -04:00
}
2012-12-21 05:59:59 -05:00
void cEntity : : ReferencedBy ( cEntity * & a_EntityPtr )
2012-06-14 09:06:06 -04:00
{
2013-03-03 14:05:11 -05:00
m_Referencers - > AddReference ( a_EntityPtr ) ;
2012-06-14 09:06:06 -04:00
}
2013-03-03 14:05:11 -05:00
void cEntity : : Dereference ( cEntity * & a_EntityPtr )
2012-06-14 09:06:06 -04:00
{
2013-03-03 14:05:11 -05:00
m_Referencers - > Dereference ( a_EntityPtr ) ;
2012-06-14 09:06:06 -04:00
}