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

@ -1832,8 +1832,17 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
Handler->ConvertToPickups(Drops, area.GetBlockMeta(bx + x, by + y, bz + z)); // Stone becomes cobblestone, coal ore becomes coal, etc. Handler->ConvertToPickups(Drops, area.GetBlockMeta(bx + x, by + y, bz + z)); // Stone becomes cobblestone, coal ore becomes coal, etc.
m_World->SpawnItemPickups(Drops, bx + x, by + y, bz + z); m_World->SpawnItemPickups(Drops, bx + x, by + y, bz + z);
} }
else if (m_World->GetTickRandomNumber(100) < 20) // 20% chance of flinging stuff around
{
if (!cBlockInfo::FullyOccupiesVoxel(area.GetBlockType(bx + x, by + y, bz + z)))
{
break;
}
m_World->SpawnFallingBlock(bx + x, by + y + 5, bz + z, area.GetBlockType(bx + x, by + y, bz + z), area.GetBlockMeta(bx + x, by + y, bz + z));
}
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR); area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z)); a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
break;
} }
} // switch (BlockType) } // switch (BlockType)
} // for z } // for z
@ -1846,11 +1855,10 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
public cEntityCallback public cEntityCallback
{ {
public: public:
cTNTDamageCallback(cBoundingBox & a_bbTNT, Vector3d a_ExplosionPos, int a_ExplosionSize, int a_ExplosionSizeSq) : cTNTDamageCallback(cBoundingBox & a_bbTNT, Vector3d a_ExplosionPos, int a_ExplosionSize) :
m_bbTNT(a_bbTNT), m_bbTNT(a_bbTNT),
m_ExplosionPos(a_ExplosionPos), m_ExplosionPos(a_ExplosionPos),
m_ExplosionSize(a_ExplosionSize), m_ExplosionSize(a_ExplosionSize)
m_ExplosionSizeSq(a_ExplosionSizeSq)
{ {
} }
@ -1873,14 +1881,16 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
} }
Vector3d AbsoluteEntityPos(abs(EntityPos.x), abs(EntityPos.y), abs(EntityPos.z)); Vector3d AbsoluteEntityPos(abs(EntityPos.x), abs(EntityPos.y), abs(EntityPos.z));
Vector3d MaxExplosionBoundary(m_ExplosionSizeSq, m_ExplosionSizeSq, m_ExplosionSizeSq);
// Work out how far we are from the edge of the TNT's explosive effect // Work out how far we are from the edge of the TNT's explosive effect
AbsoluteEntityPos -= m_ExplosionPos; AbsoluteEntityPos -= m_ExplosionPos;
AbsoluteEntityPos = MaxExplosionBoundary - AbsoluteEntityPos;
double FinalDamage = ((AbsoluteEntityPos.x + AbsoluteEntityPos.y + AbsoluteEntityPos.z) / 3) * m_ExplosionSize; // All to positive
FinalDamage = a_Entity->GetMaxHealth() - abs(FinalDamage); AbsoluteEntityPos.x = abs(AbsoluteEntityPos.x);
AbsoluteEntityPos.y = abs(AbsoluteEntityPos.y);
AbsoluteEntityPos.z = abs(AbsoluteEntityPos.z);
double FinalDamage = (((1 / AbsoluteEntityPos.x) + (1 / AbsoluteEntityPos.y) + (1 / AbsoluteEntityPos.z)) * 2) * m_ExplosionSize;
// Clip damage values // Clip damage values
if (FinalDamage > a_Entity->GetMaxHealth()) if (FinalDamage > a_Entity->GetMaxHealth())
@ -1888,7 +1898,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
else if (FinalDamage < 0) else if (FinalDamage < 0)
FinalDamage = 0; FinalDamage = 0;
if (!a_Entity->IsTNT()) // Don't apply damage to other TNT entities, they should be invincible if (!a_Entity->IsTNT() && !a_Entity->IsFallingBlock()) // Don't apply damage to other TNT entities, they should be invincible
{ {
a_Entity->TakeDamage(dtExplosion, NULL, (int)FinalDamage, 0); a_Entity->TakeDamage(dtExplosion, NULL, (int)FinalDamage, 0);
} }
@ -1898,7 +1908,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
if (distance_explosion.SqrLength() < 4096.0) if (distance_explosion.SqrLength() < 4096.0)
{ {
distance_explosion.Normalize(); distance_explosion.Normalize();
distance_explosion *= m_ExplosionSizeSq; distance_explosion *= m_ExplosionSize * m_ExplosionSize;
a_Entity->AddSpeed(distance_explosion); a_Entity->AddSpeed(distance_explosion);
} }
@ -1910,14 +1920,13 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
cBoundingBox & m_bbTNT; cBoundingBox & m_bbTNT;
Vector3d m_ExplosionPos; Vector3d m_ExplosionPos;
int m_ExplosionSize; int m_ExplosionSize;
int m_ExplosionSizeSq;
}; };
cBoundingBox bbTNT(Vector3d(a_BlockX, a_BlockY, a_BlockZ), 0.5, 1); cBoundingBox bbTNT(Vector3d(a_BlockX, a_BlockY, a_BlockZ), 0.5, 1);
bbTNT.Expand(ExplosionSizeInt * 2, ExplosionSizeInt * 2, ExplosionSizeInt * 2); bbTNT.Expand(ExplosionSizeInt * 2, ExplosionSizeInt * 2, ExplosionSizeInt * 2);
cTNTDamageCallback TNTDamageCallback(bbTNT, Vector3d(a_BlockX, a_BlockY, a_BlockZ), ExplosionSizeInt, ExplosionSizeSq); cTNTDamageCallback TNTDamageCallback(bbTNT, Vector3d(a_BlockX, a_BlockY, a_BlockZ), ExplosionSizeInt);
ForEachEntity(TNTDamageCallback); ForEachEntity(TNTDamageCallback);
// Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391): // Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):

View File

@ -521,28 +521,36 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
{ {
if (a_Chunk.IsValid()) 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)) if ((BlockY >= cChunkDef::Height) || (BlockY < 0))
{ {
// Outside of the world // Outside of the world
cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ); cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
// See if we can commit our changes. If not, we will discard them. // See if we can commit our changes. If not, we will discard them.
if (NextChunk != NULL) if (NextChunk != NULL)
@ -571,210 +579,208 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
NextPos += (NextSpeed * a_Dt); NextPos += (NextSpeed * a_Dt);
SetPosition(NextPos); SetPosition(NextPos);
} }
return; return;
} }
// Make sure we got the correct chunk and a valid one. No one ever knows... int RelBlockX = BlockX - (a_Chunk.GetPosX() * cChunkDef::Width);
cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ); int RelBlockZ = BlockZ - (a_Chunk.GetPosZ() * cChunkDef::Width);
if (NextChunk != NULL) 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); if (m_bOnGround) // check if it's still on the ground
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 (!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. int x, y, z;
BLOCKTYPE GotBlock; } 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; // The pickup is too close to an unloaded chunk, bail out of any physics handling
} gCrossCoords[] = return;
}
if (!cBlockInfo::IsSolid(GotBlock))
{ {
{ 1, 0, 0}, NextPos.x += gCrossCoords[i].x;
{-1, 0, 0}, NextPos.z += gCrossCoords[i].z;
{ 0, 0, 1}, IsNoAirSurrounding = false;
{ 0, 0, -1}, break;
} ; }
} // for i - gCrossCoords[]
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[]
if (IsNoAirSurrounding) if (IsNoAirSurrounding)
{ {
NextPos.y += 0.5; 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 (!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; fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
if (IsBlockWater(BlockIn)) }
{ else if (BlockIn == E_BLOCK_COBWEB)
fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water. {
} NextSpeed.y *= 0.05; // Reduce overall falling speed
else if (BlockIn == E_BLOCK_COBWEB) fallspeed = 0; // No falling.
{
NextSpeed.y *= 0.05; // Reduce overall falling speed
fallspeed = 0; // No falling.
}
else
{
// Normal gravity
fallspeed = m_Gravity * a_Dt;
}
NextSpeed.y += fallspeed;
} }
else else
{ {
// Friction // Normal gravity
if (NextSpeed.SqrLength() > 0.0004f) 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); NextSpeed.x = 0;
if (fabs(NextSpeed.x) < 0.05) }
{ NextSpeed.z *= 0.7f / (1 + a_Dt);
NextSpeed.x = 0; if (fabs(NextSpeed.z) < 0.05)
} {
NextSpeed.z *= 0.7f / (1 + a_Dt); NextSpeed.z = 0;
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 // 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. // might have different speed modifiers according to terrain.
if (BlockIn == E_BLOCK_COBWEB) if (BlockIn == E_BLOCK_COBWEB)
{ {
NextSpeed.x *= 0.25; NextSpeed.x *= 0.25;
NextSpeed.z *= 0.25; NextSpeed.z *= 0.25;
} }
//Get water direction //Get water direction
Direction WaterDir = m_World->GetWaterSimulator()->GetFlowingDirection(BlockX, BlockY, BlockZ); 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) switch(WaterDir)
{ {
case X_PLUS: case X_PLUS:
m_WaterSpeed.x = 0.2f; m_WaterSpeed.x = 0.2f;
m_bOnGround = false; 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; 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; // Set to hit position
} if( (Tracer.RealHit - NextPos).SqrLength() <= ( NextSpeed * a_Dt ).SqrLength() )
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( Ret == 1 )
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.x != 0.f ) NextSpeed.x = 0.f; if( Tracer.HitNormal.z != 0.f ) NextSpeed.z = 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 if( Tracer.HitNormal.y > 0 ) // means on ground
{ {
m_bOnGround = true; 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 else
{ {
// We didn't hit anything, so move =]
NextPos += (NextSpeed * a_Dt); NextPos += (NextSpeed * a_Dt);
} }
} }
BlockX = (int) floor(NextPos.x); else
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); // We didn't hit anything, so move =]
if (NextPos.y != GetPosY()) SetPosY(NextPos.y); NextPos += (NextSpeed * a_Dt);
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);
} }
} }
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 RelX = x;
int RelZ = z; int RelZ = z;
cChunk * CurChunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelX, RelZ);
if (CurChunk == NULL)
{
continue;
}
for (int y = MinY; y <= MaxY; y++) 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: case E_BLOCK_FIRE:
{ {
@ -922,7 +927,7 @@ void cEntity::TickInVoid(cChunk & a_Chunk)
void cEntity::SetSwimState(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)) if ((RelY < 0) || (RelY >= cChunkDef::Height - 1))
{ {
m_IsSwimming = false; m_IsSwimming = false;
@ -931,11 +936,10 @@ void cEntity::SetSwimState(cChunk & a_Chunk)
} }
BLOCKTYPE BlockIn; BLOCKTYPE BlockIn;
int RelX = (int)floor(m_LastPosX) - a_Chunk.GetPosX() * cChunkDef::Width; int RelX = POSX_TOINT - a_Chunk.GetPosX() * cChunkDef::Width;
int RelZ = (int)floor(m_LastPosZ) - a_Chunk.GetPosZ() * cChunkDef::Width; int RelZ = POSZ_TOINT - a_Chunk.GetPosZ() * cChunkDef::Width;
// Check if the player is swimming: // 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)) if (!a_Chunk.UnboundedRelGetBlockType(RelX, RelY, RelZ, BlockIn))
{ {
// This sometimes happens on Linux machines // This sometimes happens on Linux machines

View File

@ -119,6 +119,7 @@ public:
BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire BURN_TICKS = 200, ///< How long to keep an entity burning after it has stood in lava / fire
MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have MAX_AIR_LEVEL = 300, ///< Maximum air an entity can have
DROWNING_TICKS = 20, ///< Number of ticks per heart of damage DROWNING_TICKS = 20, ///< Number of ticks per heart of damage
VOID_BOUNDARY = -46 ///< At what position Y to begin applying void damage
} ; } ;
cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height); cEntity(eEntityType a_EntityType, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);

View File

@ -33,20 +33,16 @@ void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk) void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
{ {
float MilliDt = a_Dt * 0.001f;
AddSpeedY(MilliDt * -9.8f);
AddPosY(GetSpeedY() * MilliDt);
// GetWorld()->BroadcastTeleportEntity(*this); // Test position // GetWorld()->BroadcastTeleportEntity(*this); // Test position
int BlockX = m_OriginalPosition.x; int BlockX = POSX_TOINT;
int BlockY = (int)(GetPosY() - 0.5); int BlockY = (int)(GetPosY() - 0.5);
int BlockZ = m_OriginalPosition.z; int BlockZ = POSZ_TOINT;
if (BlockY < 0) if (BlockY < 0)
{ {
// Fallen out of this world, just continue falling until out of sight, then destroy: // Fallen out of this world, just continue falling until out of sight, then destroy:
if (BlockY < 100) if (BlockY < VOID_BOUNDARY)
{ {
Destroy(true); Destroy(true);
} }
@ -86,6 +82,15 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
Destroy(true); Destroy(true);
return; return;
} }
float MilliDt = a_Dt * 0.001f;
AddSpeedY(MilliDt * -9.8f);
AddPosition(GetSpeed() * MilliDt);
if ((GetSpeedX() != 0) || (GetSpeedZ() != 0))
{
BroadcastMovementUpdate();
}
} }

View File

@ -34,8 +34,8 @@ public:
{ {
// Activate the TNT: // Activate the TNT:
a_World->BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f); a_World->BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0); a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0);
a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
break; break;
} }
default: default:

View File

@ -838,8 +838,8 @@ void cIncrementalRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_
if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ)) if (AreCoordsPowered(a_BlockX, a_BlockY, a_BlockZ))
{ {
m_World.BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f); m_World.BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
m_World.SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0); m_World.SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
m_World.SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5, 4); // 4 seconds to boom
} }
} }

View File

@ -1696,7 +1696,11 @@ void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, double a_FuseTim
UNUSED(a_InitialVelocityCoeff); UNUSED(a_InitialVelocityCoeff);
cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTimeInSec); cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTimeInSec);
TNT->Initialize(this); TNT->Initialize(this);
// TODO: Add a bit of speed in horiz and vert axes, based on the a_InitialVelocityCoeff TNT->SetSpeed(
a_InitialVelocityCoeff * (GetTickRandomNumber(2) - 1), /** -1, 0, 1 */
a_InitialVelocityCoeff * 2,
a_InitialVelocityCoeff * (GetTickRandomNumber(2) - 1)
);
} }