Added extra awesomeness to TNT
+ TNT now has a chance of flinging FallingBlock entities around * Improved TNT damage * Improved TNT spawning visuals * Possible fix for 'SetSwimState failure' messages in debug
This commit is contained in:
@@ -521,28 +521,36 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
if (a_Chunk.IsValid())
|
||||
{
|
||||
HandlePhysics(a_Dt, a_Chunk);
|
||||
cChunk * NextChunk = a_Chunk.GetNeighborChunk(POSX_TOINT, POSZ_TOINT);
|
||||
|
||||
if ((NextChunk == NULL) || !NextChunk->IsValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TickBurning(*NextChunk);
|
||||
|
||||
if (GetPosY() < VOID_BOUNDARY)
|
||||
{
|
||||
TickInVoid(*NextChunk);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_TicksSinceLastVoidDamage = 0;
|
||||
}
|
||||
|
||||
if (IsMob() || IsPlayer())
|
||||
{
|
||||
// Set swimming state
|
||||
SetSwimState(*NextChunk);
|
||||
|
||||
// Handle drowning
|
||||
HandleAir();
|
||||
}
|
||||
|
||||
HandlePhysics(a_Dt, *NextChunk);
|
||||
}
|
||||
}
|
||||
if (a_Chunk.IsValid())
|
||||
{
|
||||
TickBurning(a_Chunk);
|
||||
}
|
||||
if ((a_Chunk.IsValid()) && (GetPosY() < -46))
|
||||
{
|
||||
TickInVoid(a_Chunk);
|
||||
}
|
||||
else
|
||||
m_TicksSinceLastVoidDamage = 0;
|
||||
|
||||
if (IsMob() || IsPlayer())
|
||||
{
|
||||
// Set swimming state
|
||||
SetSwimState(a_Chunk);
|
||||
|
||||
// Handle drowning
|
||||
HandleAir();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -562,7 +570,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
||||
if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
|
||||
{
|
||||
// Outside 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)
|
||||
@@ -571,210 +579,208 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
||||
NextPos += (NextSpeed * a_Dt);
|
||||
SetPosition(NextPos);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 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 - (a_Chunk.GetPosX() * cChunkDef::Width);
|
||||
int RelBlockZ = BlockZ - (a_Chunk.GetPosZ() * cChunkDef::Width);
|
||||
BLOCKTYPE BlockIn = a_Chunk.GetBlock( RelBlockX, BlockY, RelBlockZ );
|
||||
BLOCKTYPE BlockBelow = (BlockY > 0) ? a_Chunk.GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
|
||||
if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
|
||||
{
|
||||
int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
|
||||
int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
|
||||
BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
|
||||
BLOCKTYPE BlockBelow = (BlockY > 0) ? NextChunk->GetBlock(RelBlockX, BlockY - 1, RelBlockZ) : E_BLOCK_AIR;
|
||||
if (!cBlockInfo::IsSolid(BlockIn)) // Making sure we are not inside a solid block
|
||||
if (m_bOnGround) // check if it's still on the ground
|
||||
{
|
||||
if (m_bOnGround) // check if it's still on the ground
|
||||
if (!cBlockInfo::IsSolid(BlockBelow)) // Check if block below is air or water.
|
||||
{
|
||||
if (!cBlockInfo::IsSolid(BlockBelow)) // Check if block below is air or water.
|
||||
{
|
||||
m_bOnGround = false;
|
||||
}
|
||||
m_bOnGround = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
// Push out entity.
|
||||
BLOCKTYPE GotBlock;
|
||||
|
||||
static const struct
|
||||
{
|
||||
// Push out entity.
|
||||
BLOCKTYPE GotBlock;
|
||||
int x, y, z;
|
||||
} gCrossCoords[] =
|
||||
{
|
||||
{ 1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
{ 0, 0, 1},
|
||||
{ 0, 0, -1},
|
||||
} ;
|
||||
|
||||
static const struct
|
||||
bool IsNoAirSurrounding = true;
|
||||
for (size_t i = 0; i < ARRAYCOUNT(gCrossCoords); i++)
|
||||
{
|
||||
if (!a_Chunk.UnboundedRelGetBlockType(RelBlockX + gCrossCoords[i].x, BlockY, RelBlockZ + gCrossCoords[i].z, GotBlock))
|
||||
{
|
||||
int x, y, z;
|
||||
} gCrossCoords[] =
|
||||
// The pickup is too close to an unloaded chunk, bail out of any physics handling
|
||||
return;
|
||||
}
|
||||
if (!cBlockInfo::IsSolid(GotBlock))
|
||||
{
|
||||
{ 1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
{ 0, 0, 1},
|
||||
{ 0, 0, -1},
|
||||
} ;
|
||||
|
||||
bool IsNoAirSurrounding = true;
|
||||
for (size_t 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 (!cBlockInfo::IsSolid(GotBlock))
|
||||
{
|
||||
NextPos.x += gCrossCoords[i].x;
|
||||
NextPos.z += gCrossCoords[i].z;
|
||||
IsNoAirSurrounding = false;
|
||||
break;
|
||||
}
|
||||
} // for i - gCrossCoords[]
|
||||
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;
|
||||
|
||||
/*
|
||||
// DEBUG:
|
||||
LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
|
||||
m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
|
||||
);
|
||||
*/
|
||||
if (IsNoAirSurrounding)
|
||||
{
|
||||
NextPos.y += 0.5;
|
||||
}
|
||||
|
||||
if (!m_bOnGround)
|
||||
m_bOnGround = true;
|
||||
|
||||
/*
|
||||
// DEBUG:
|
||||
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))
|
||||
{
|
||||
float fallspeed;
|
||||
if (IsBlockWater(BlockIn))
|
||||
{
|
||||
fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
|
||||
}
|
||||
else if (BlockIn == E_BLOCK_COBWEB)
|
||||
{
|
||||
NextSpeed.y *= 0.05; // Reduce overall falling speed
|
||||
fallspeed = 0; // No falling.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal gravity
|
||||
fallspeed = m_Gravity * a_Dt;
|
||||
}
|
||||
NextSpeed.y += fallspeed;
|
||||
fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
|
||||
}
|
||||
else if (BlockIn == E_BLOCK_COBWEB)
|
||||
{
|
||||
NextSpeed.y *= 0.05; // Reduce overall falling speed
|
||||
fallspeed = 0; // No falling.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Friction
|
||||
if (NextSpeed.SqrLength() > 0.0004f)
|
||||
// Normal gravity
|
||||
fallspeed = m_Gravity * a_Dt;
|
||||
}
|
||||
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.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;
|
||||
}
|
||||
NextSpeed.x = 0;
|
||||
}
|
||||
NextSpeed.z *= 0.7f / (1 + a_Dt);
|
||||
if (fabs(NextSpeed.z) < 0.05)
|
||||
{
|
||||
NextSpeed.z = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
|
||||
// might have different speed modifiers according to terrain.
|
||||
if (BlockIn == E_BLOCK_COBWEB)
|
||||
{
|
||||
NextSpeed.x *= 0.25;
|
||||
NextSpeed.z *= 0.25;
|
||||
}
|
||||
// Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
|
||||
// might have different speed modifiers according to terrain.
|
||||
if (BlockIn == E_BLOCK_COBWEB)
|
||||
{
|
||||
NextSpeed.x *= 0.25;
|
||||
NextSpeed.z *= 0.25;
|
||||
}
|
||||
|
||||
//Get water direction
|
||||
Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);
|
||||
//Get water direction
|
||||
Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ);
|
||||
|
||||
m_WaterSpeed *= 0.9f; //Reduce speed each tick
|
||||
m_WaterSpeed *= 0.9f; //Reduce speed each tick
|
||||
|
||||
switch(WaterDir)
|
||||
{
|
||||
case X_PLUS:
|
||||
m_WaterSpeed.x = 0.2f;
|
||||
m_bOnGround = false;
|
||||
break;
|
||||
case X_MINUS:
|
||||
m_WaterSpeed.x = -0.2f;
|
||||
m_bOnGround = false;
|
||||
break;
|
||||
case Z_PLUS:
|
||||
m_WaterSpeed.z = 0.2f;
|
||||
m_bOnGround = false;
|
||||
break;
|
||||
case Z_MINUS:
|
||||
m_WaterSpeed.z = -0.2f;
|
||||
m_bOnGround = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
switch(WaterDir)
|
||||
{
|
||||
case X_PLUS:
|
||||
m_WaterSpeed.x = 0.2f;
|
||||
m_bOnGround = false;
|
||||
break;
|
||||
}
|
||||
case X_MINUS:
|
||||
m_WaterSpeed.x = -0.2f;
|
||||
m_bOnGround = false;
|
||||
break;
|
||||
case Z_PLUS:
|
||||
m_WaterSpeed.z = 0.2f;
|
||||
m_bOnGround = false;
|
||||
break;
|
||||
case Z_MINUS:
|
||||
m_WaterSpeed.z = -0.2f;
|
||||
m_bOnGround = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (fabs(m_WaterSpeed.x) < 0.05)
|
||||
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
|
||||
{
|
||||
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() )
|
||||
{
|
||||
// Set to hit position
|
||||
if( (Tracer.RealHit - NextPos).SqrLength() <= ( NextSpeed * a_Dt ).SqrLength() )
|
||||
if( Ret == 1 )
|
||||
{
|
||||
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.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;
|
||||
}
|
||||
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.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);
|
||||
}
|
||||
NextPos.Set(Tracer.RealHit.x,Tracer.RealHit.y,Tracer.RealHit.z);
|
||||
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
|
||||
{
|
||||
// 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)
|
||||
else
|
||||
{
|
||||
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);
|
||||
// We didn't hit anything, so move =]
|
||||
NextPos += (NextSpeed * a_Dt);
|
||||
}
|
||||
}
|
||||
|
||||
BlockX = (int) floor(NextPos.x);
|
||||
BlockZ = (int) floor(NextPos.z);
|
||||
|
||||
cChunk * NextChunk = a_Chunk.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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -815,14 +821,13 @@ void cEntity::TickBurning(cChunk & a_Chunk)
|
||||
{
|
||||
int RelX = x;
|
||||
int RelZ = z;
|
||||
cChunk * CurChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelX, RelZ);
|
||||
if (CurChunk == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int y = MinY; y <= MaxY; y++)
|
||||
{
|
||||
switch (CurChunk->GetBlock(RelX, y, RelZ))
|
||||
BLOCKTYPE Block;
|
||||
a_Chunk.UnboundedRelGetBlockType(RelX, y, RelZ, Block);
|
||||
|
||||
switch (Block)
|
||||
{
|
||||
case E_BLOCK_FIRE:
|
||||
{
|
||||
@@ -922,7 +927,7 @@ void cEntity::TickInVoid(cChunk & a_Chunk)
|
||||
|
||||
void cEntity::SetSwimState(cChunk & a_Chunk)
|
||||
{
|
||||
int RelY = (int)floor(m_LastPosY + 0.1);
|
||||
int RelY = (int)floor(GetPosY() + 0.1);
|
||||
if ((RelY < 0) || (RelY >= cChunkDef::Height - 1))
|
||||
{
|
||||
m_IsSwimming = false;
|
||||
@@ -931,11 +936,10 @@ void cEntity::SetSwimState(cChunk & a_Chunk)
|
||||
}
|
||||
|
||||
BLOCKTYPE BlockIn;
|
||||
int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
|
||||
int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
|
||||
|
||||
// Check if the player is swimming:
|
||||
// Use Unbounded, because we're being called *after* processing super::Tick(), which could have changed our chunk
|
||||
if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn))
|
||||
{
|
||||
// This sometimes happens on Linux machines
|
||||
|
||||
Reference in New Issue
Block a user