summaryrefslogtreecommitdiffstats
path: root/source/Entities/Entity.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Entities/Entity.cpp')
-rw-r--r--source/Entities/Entity.cpp132
1 files changed, 108 insertions, 24 deletions
diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp
index 1a593b3d1..d465c75bd 100644
--- a/source/Entities/Entity.cpp
+++ b/source/Entities/Entity.cpp
@@ -1,4 +1,3 @@
-
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Entity.h"
@@ -13,6 +12,7 @@
#include "../Simulator/FluidSimulator.h"
#include "../PluginManager.h"
#include "../Tracer.h"
+#include "Minecart.h"
@@ -55,6 +55,7 @@ cEntity::cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, d
, m_TicksSinceLastBurnDamage(0)
, m_TicksSinceLastLavaDamage(0)
, m_TicksSinceLastFireDamage(0)
+ , m_TicksSinceLastVoidDamage(0)
, m_TicksLeftBurning(0)
, m_WaterSpeed(0, 0, 0)
, m_Width(a_Width)
@@ -505,6 +506,11 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
{
TickBurning(a_Chunk);
}
+ if ((a_Chunk.IsValid()) && (GetPosY() < -46))
+ {
+ TickInVoid(a_Chunk);
+ }
+ else { m_TicksSinceLastVoidDamage = 0; }
}
@@ -524,8 +530,15 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
{
// Outside of the world
- // TODO: Current speed should still be added to the entity position
- // Otherwise TNT explosions in the void will still effect the bottommost layers of the world
+
+ cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
+ // See if we can commit our changes. If not, we will discard them.
+ if (NextChunk != NULL)
+ {
+ SetSpeed(NextSpeed);
+ NextPos += (NextSpeed * a_Dt);
+ SetPosition(NextPos);
+ }
return;
}
@@ -536,12 +549,11 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
- BLOCKTYPE BlockBelow = NextChunk->GetBlock( RelBlockX, BlockY - 1, RelBlockZ );
+ BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
if (!g_BlockIsSolid[BlockIn]) // Making sure we are not inside a solid block
{
if (m_bOnGround) // check if it's still on the ground
{
- BLOCKTYPE BlockBelow = NextChunk->GetBlock( RelBlockX, BlockY - 1, RelBlockZ );
if (!g_BlockIsSolid[BlockBelow]) // Check if block below is air or water.
{
m_bOnGround = false;
@@ -551,8 +563,43 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
else
{
// Push out entity.
+ BLOCKTYPE GotBlock;
+
+ static const struct
+ {
+ int x, y, z;
+ } gCrossCoords[] =
+ {
+ { 1, 0, 0},
+ {-1, 0, 0},
+ { 0, 0, 1},
+ { 0, 0, -1},
+ } ;
+
+ bool IsNoAirSurrounding = true;
+ for (int i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
+ {
+ if (!NextChunk->UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
+ {
+ // The pickup is too close to an unloaded chunk, bail out of any physics handling
+ return;
+ }
+ if (!g_BlockIsSolid[GotBlock])
+ {
+ NextPos.x += gCrossCoords[i].x;
+ NextPos.z += gCrossCoords[i].z;
+ IsNoAirSurrounding = false;
+ break;
+ }
+ } // for i - gCrossCoords[]
+
+ if (IsNoAirSurrounding)
+ {
+ NextPos.y += 0.5;
+ }
+
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
);
@@ -565,6 +612,11 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
}
+ else if (IsBlockRail(BlockBelow) && IsMinecart()) // Rails aren't solid, except for Minecarts
+ {
+ fallspeed = 0;
+ m_bOnGround = true;
+ }
else if (BlockIn == E_BLOCK_COBWEB)
{
NextSpeed.y *= 0.05; // Reduce overall falling speed
@@ -579,24 +631,37 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
}
else
{
- // TODO: This condition belongs to minecarts, without it, they derails too much.
- // But it shouldn't be here for other entities. We need a complete minecart physics overhaul.
- if (
- (BlockBelow != E_BLOCK_RAIL) &&
- (BlockBelow != E_BLOCK_DETECTOR_RAIL) &&
- (BlockBelow != E_BLOCK_POWERED_RAIL) &&
- (BlockBelow != E_BLOCK_ACTIVATOR_RAIL)
- )
+ if (IsMinecart())
{
- // Friction
+ if (!IsBlockRail(BlockBelow))
+ {
+ // Friction if minecart is off track, otherwise, Minecart.cpp handles this
+ 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;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Friction for non-minecarts
if (NextSpeed.SqrLength() > 0.0004f)
{
- NextSpeed.x *= 0.6666;
+ NextSpeed.x *= 0.7f / (1 + a_Dt);
if (fabs(NextSpeed.x) < 0.05)
{
NextSpeed.x = 0;
}
- NextSpeed.z *= 0.6666;
+ NextSpeed.z *= 0.7f / (1 + a_Dt);
if (fabs(NextSpeed.z) < 0.05)
{
NextSpeed.z = 0;
@@ -621,19 +686,19 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
switch(WaterDir)
{
case X_PLUS:
- m_WaterSpeed.x = 1.f;
+ m_WaterSpeed.x = 0.2f;
m_bOnGround = false;
break;
case X_MINUS:
- m_WaterSpeed.x = -1.f;
+ m_WaterSpeed.x = -0.2f;
m_bOnGround = false;
break;
case Z_PLUS:
- m_WaterSpeed.z = 1.f;
+ m_WaterSpeed.z = 0.2f;
m_bOnGround = false;
break;
case Z_MINUS:
- m_WaterSpeed.z = -1.f;
+ m_WaterSpeed.z = -0.2f;
m_bOnGround = false;
break;
@@ -664,7 +729,6 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
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;
@@ -675,11 +739,14 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
}
}
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;
+ NextPos.x += Tracer.HitNormal.x * 0.3f;
+ NextPos.y += Tracer.HitNormal.y * 0.05f; // Any larger produces entity vibration-upon-the-spot
+ NextPos.z += Tracer.HitNormal.z * 0.3f;
}
else
+ {
NextPos += (NextSpeed * a_Dt);
+ }
}
else
{
@@ -829,6 +896,23 @@ void cEntity::TickBurning(cChunk & a_Chunk)
+void cEntity::TickInVoid(cChunk & a_Chunk)
+{
+ if (m_TicksSinceLastVoidDamage == 20)
+ {
+ TakeDamage(dtInVoid, NULL, 2, 0);
+ m_TicksSinceLastVoidDamage = 0;
+ }
+ else
+ {
+ m_TicksSinceLastVoidDamage++;
+ }
+}
+
+
+
+
+
/// Called when the entity starts burning
void cEntity::OnStartedBurning(void)
{