summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/BlockTracer.h4
-rw-r--r--source/Entities/ProjectileEntity.cpp147
-rw-r--r--source/Entities/ProjectileEntity.h9
-rw-r--r--source/LineBlockTracer.cpp11
-rw-r--r--source/LineBlockTracer.h3
-rw-r--r--source/ManualBindings.cpp6
-rw-r--r--source/Vector3d.h13
7 files changed, 157 insertions, 36 deletions
diff --git a/source/BlockTracer.h b/source/BlockTracer.h
index 6d67f1052..d0a34811d 100644
--- a/source/BlockTracer.h
+++ b/source/BlockTracer.h
@@ -31,12 +31,12 @@ public:
/** Called on each block encountered along the path, including the first block (path start)
When this callback returns true, the tracing is aborted.
*/
- virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) = 0;
/** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
When this callback returns true, the tracing is aborted.
*/
- virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) { return false; }
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) { return false; }
/** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
The coords specify the exact point at which the path exited the world.
diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp
index 350cad95b..4983943a9 100644
--- a/source/Entities/ProjectileEntity.cpp
+++ b/source/Entities/ProjectileEntity.cpp
@@ -7,6 +7,57 @@
#include "ProjectileEntity.h"
#include "../ClientHandle.h"
#include "Player.h"
+#include "../LineBlockTracer.h"
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cProjectileTracerCallback:
+
+class cProjectileTracerCallback :
+ public cBlockTracer::cCallbacks
+{
+public:
+ cProjectileTracerCallback(cProjectileEntity * a_Projectile) :
+ m_Projectile(a_Projectile)
+ {
+ }
+
+protected:
+ cProjectileEntity * m_Projectile;
+
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
+ {
+ if (g_BlockIsSolid[a_BlockType])
+ {
+ // The projectile hit a solid block
+ m_Projectile->OnHitSolidBlock(a_BlockX, a_BlockY, a_BlockZ, a_EntryFace);
+ return true;
+ }
+
+ // Convey some special effects from special blocks:
+ switch (a_BlockType)
+ {
+ case E_BLOCK_LAVA:
+ case E_BLOCK_STATIONARY_LAVA:
+ {
+ m_Projectile->StartBurning(30);
+ break;
+ }
+ case E_BLOCK_WATER:
+ case E_BLOCK_STATIONARY_WATER:
+ {
+ m_Projectile->StopBurning();
+ break;
+ }
+ } // switch (a_BlockType)
+
+ // Continue tracing
+ return false;
+ }
+} ;
@@ -18,7 +69,8 @@
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
m_ProjectileKind(a_Kind),
- m_Creator(a_Creator)
+ m_Creator(a_Creator),
+ m_IsInGround(false)
{
}
@@ -29,7 +81,8 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
m_ProjectileKind(a_Kind),
- m_Creator(a_Creator)
+ m_Creator(a_Creator),
+ m_IsInGround(false)
{
SetSpeed(a_Speed);
}
@@ -60,6 +113,35 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
+void cProjectileEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
+{
+ // TODO: Set proper position based on what face was hit
+ switch (a_BlockFace)
+ {
+ case BLOCK_FACE_TOP: SetPosition(0.5 + a_BlockX, 1.0 + a_BlockY, 0.5 + a_BlockZ); break;
+ case BLOCK_FACE_BOTTOM: SetPosition(0.5 + a_BlockX, a_BlockY, 0.5 + a_BlockZ); break;
+ case BLOCK_FACE_EAST: SetPosition( a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
+ case BLOCK_FACE_WEST: SetPosition(1.0 + a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
+ case BLOCK_FACE_NORTH: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, 1.0 + a_BlockZ); break;
+ case BLOCK_FACE_SOUTH: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, a_BlockZ); break;
+ case BLOCK_FACE_NONE: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
+ }
+ SetSpeed(0, 0, 0);
+
+ // DEBUG:
+ LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, hit solid block at face %d",
+ m_UniqueID,
+ GetPosX(), GetPosY(), GetPosZ(),
+ a_BlockFace
+ );
+
+ m_IsInGround = true;
+}
+
+
+
+
+
AString cProjectileEntity::GetMCAClassName(void) const
{
switch (m_ProjectileKind)
@@ -83,6 +165,51 @@ AString cProjectileEntity::GetMCAClassName(void) const
+void cProjectileEntity::Tick(float a_Dt, cChunk & a_Chunk)
+{
+ super::Tick(a_Dt, a_Chunk);
+ BroadcastMovementUpdate();
+}
+
+
+
+
+
+void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
+{
+ if (m_IsInGround)
+ {
+ // Already-grounded projectiles don't move at all
+ return;
+ }
+
+ Vector3d PerTickSpeed = GetSpeed() / 20;
+ Vector3d Pos = GetPosition();
+
+ // Trace the tick's worth of movement as a line:
+ Vector3d NextPos = Pos + PerTickSpeed;
+ cProjectileTracerCallback TracerCallback(this);
+ if (cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
+ {
+ // Nothing in the way, update the position
+ SetPosition(NextPos);
+ }
+
+ // Add gravity effect to the vertical speed component:
+ SetSpeedY(GetSpeedY() + m_Gravity / 20);
+
+ // DEBUG:
+ LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}",
+ m_UniqueID,
+ GetPosX(), GetPosY(), GetPosZ(),
+ GetSpeedX(), GetSpeedY(), GetSpeedZ()
+ );
+}
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cArrowEntity:
@@ -118,22 +245,6 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
-void cArrowEntity::Tick(float a_Dt, cChunk & a_Chunk)
-{
- super::Tick(a_Dt, a_Chunk);
-
- // DEBUG:
- LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}",
- m_UniqueID,
- GetPosX(), GetPosY(), GetPosZ(),
- GetSpeedX(), GetSpeedY(), GetSpeedZ()
- );
-}
-
-
-
-
-
void cArrowEntity::SpawnOn(cClientHandle & a_Client)
{
a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0);
diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h
index 345730d19..7a97a2215 100644
--- a/source/Entities/ProjectileEntity.h
+++ b/source/Entities/ProjectileEntity.h
@@ -47,8 +47,8 @@ public:
static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed = NULL);
- /// Called by the physics blocktracer when the entity hits a solid block, the coords and the face hit is given
- virtual void OnHitSolidBlock(double a_BlockX, double a_BlockY, double a_BlockZ, char a_BlockFace) {};
+ /// Called by the physics blocktracer when the entity hits a solid block, the block's coords and the face hit is given
+ virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
// tolua_begin
@@ -72,6 +72,10 @@ protected:
/// True if the projectile has hit the ground and is stuck there
bool m_IsInGround;
+
+ // cEntity overrides:
+ virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
} ;
@@ -127,7 +131,6 @@ protected:
double m_DamageCoeff;
// cEntity overrides:
- virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void SpawnOn(cClientHandle & a_Client) override;
// tolua_begin
diff --git a/source/LineBlockTracer.cpp b/source/LineBlockTracer.cpp
index 03464314a..7cc14089d 100644
--- a/source/LineBlockTracer.cpp
+++ b/source/LineBlockTracer.cpp
@@ -55,6 +55,7 @@ bool cLineBlockTracer::Trace(double a_StartX, double a_StartY, double a_StartZ,
m_DirX = (m_StartX < m_EndX) ? 1 : -1;
m_DirY = (m_StartY < m_EndY) ? 1 : -1;
m_DirZ = (m_StartZ < m_EndZ) ? 1 : -1;
+ m_CurrentFace = BLOCK_FACE_NONE;
// Check the start coords, adjust into the world:
if (m_StartY < 0)
@@ -178,9 +179,9 @@ bool cLineBlockTracer::MoveToNextBlock(void)
// Based on the wall hit, adjust the current coords
switch (Direction)
{
- case dirX: m_CurrentX += m_DirX; break;
- case dirY: m_CurrentY += m_DirY; break;
- case dirZ: m_CurrentZ += m_DirZ; break;
+ case dirX: m_CurrentX += m_DirX; m_CurrentFace = (m_DirX > 0) ? BLOCK_FACE_EAST : BLOCK_FACE_WEST; break;
+ case dirY: m_CurrentY += m_DirY; m_CurrentFace = (m_DirY > 0) ? BLOCK_FACE_BOTTOM : BLOCK_FACE_TOP; break;
+ case dirZ: m_CurrentZ += m_DirZ; m_CurrentFace = (m_DirZ > 0) ? BLOCK_FACE_SOUTH : BLOCK_FACE_NORTH; break;
case dirNONE: return false;
}
return true;
@@ -211,7 +212,7 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk)
int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
- if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta))
+ if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta, m_CurrentFace))
{
// The callback terminated the trace
return false;
@@ -219,7 +220,7 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk)
}
else
{
- if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ))
+ if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ, m_CurrentFace))
{
// The callback terminated the trace
return false;
diff --git a/source/LineBlockTracer.h b/source/LineBlockTracer.h
index 4616cb191..ccbb70ea6 100644
--- a/source/LineBlockTracer.h
+++ b/source/LineBlockTracer.h
@@ -60,6 +60,9 @@ protected:
// The current block
int m_CurrentX, m_CurrentY, m_CurrentZ;
+
+ // The face through which the current block has been entered
+ char m_CurrentFace;
/// Adjusts the start point above the world to just at the world's top
diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp
index 27c6684f2..87efecd35 100644
--- a/source/ManualBindings.cpp
+++ b/source/ManualBindings.cpp
@@ -1649,7 +1649,7 @@ public:
{
}
- virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlock"))
{
@@ -1661,6 +1661,7 @@ public:
m_LuaState.Push(a_BlockZ);
m_LuaState.Push(a_BlockType);
m_LuaState.Push(a_BlockMeta);
+ m_LuaState.Push(a_EntryFace);
if (!m_LuaState.CallFunction(1))
{
return false;
@@ -1674,7 +1675,7 @@ public:
return res;
}
- virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) override
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) override
{
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlockNoData"))
{
@@ -1684,6 +1685,7 @@ public:
m_LuaState.Push(a_BlockX);
m_LuaState.Push(a_BlockY);
m_LuaState.Push(a_BlockZ);
+ m_LuaState.Push(a_EntryFace);
if (!m_LuaState.CallFunction(1))
{
return false;
diff --git a/source/Vector3d.h b/source/Vector3d.h
index 6f28a857b..ecc72e421 100644
--- a/source/Vector3d.h
+++ b/source/Vector3d.h
@@ -30,12 +30,13 @@ public: // tolua_export
void operator -= ( Vector3d* a_V ) { x -= a_V->x; y -= a_V->y; z -= a_V->z; }
void operator *= ( double a_f ) { x *= a_f; y *= a_f; z *= a_f; }
- Vector3d operator + ( const Vector3d& v2 ) const { return Vector3d( x + v2.x, y + v2.y, z + v2.z ); } // tolua_export
- Vector3d operator + ( const Vector3d* v2 ) const { return Vector3d( x + v2->x, y + v2->y, z + v2->z ); } // tolua_export
- Vector3d operator - ( const Vector3d& v2 ) const { return Vector3d( x - v2.x, y - v2.y, z - v2.z ); } // tolua_export
- Vector3d operator - ( const Vector3d* v2 ) const { return Vector3d( x - v2->x, y - v2->y, z - v2->z ); } // tolua_export
- Vector3d operator * ( const double f ) const { return Vector3d( x * f, y * f, z * f ); } // tolua_export
- Vector3d operator * ( const Vector3d& v2 ) const { return Vector3d( x * v2.x, y * v2.y, z * v2.z ); } // tolua_export
+ Vector3d operator + (const Vector3d & v2) const { return Vector3d(x + v2.x, y + v2.y, z + v2.z ); } // tolua_export
+ Vector3d operator + (const Vector3d * v2) const { return Vector3d(x + v2->x, y + v2->y, z + v2->z ); } // tolua_export
+ Vector3d operator - (const Vector3d & v2) const { return Vector3d(x - v2.x, y - v2.y, z - v2.z ); } // tolua_export
+ Vector3d operator - (const Vector3d * v2) const { return Vector3d(x - v2->x, y - v2->y, z - v2->z ); } // tolua_export
+ Vector3d operator * (const double f) const { return Vector3d(x * f, y * f, z * f ); } // tolua_export
+ Vector3d operator * (const Vector3d & v2) const { return Vector3d(x * v2.x, y * v2.y, z * v2.z ); } // tolua_export
+ Vector3d operator / (const double f) const { return Vector3d(x / f, y / f, z / f ); } // tolua_export
double x, y, z; // tolua_export