1
0

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:
Tiger Wang
2014-03-05 22:12:48 +00:00
parent 7fb354e8f0
commit 53231bebd6
7 changed files with 236 additions and 213 deletions

View File

@@ -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