commit
fe6c03595f
@ -852,10 +852,14 @@ enum eExplosionSource
|
||||
esWitherSkullBlack,
|
||||
esWitherSkullBlue,
|
||||
esWitherBirth,
|
||||
esPlugin,
|
||||
|
||||
// Obsolete constants, kept for compatibility, will be removed after some time:
|
||||
esCreeper = esMonster,
|
||||
esPlugin
|
||||
} ;
|
||||
|
||||
enum eShrapnelLevel
|
||||
{
|
||||
slNone,
|
||||
slGravityAffectedOnly,
|
||||
slAll
|
||||
} ;
|
||||
|
||||
// tolua_end
|
||||
|
@ -1834,8 +1834,23 @@ 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.
|
||||
m_World->SpawnItemPickups(Drops, bx + x, by + y, bz + z);
|
||||
}
|
||||
else if ((m_World->GetTNTShrapnelLevel() > slNone) && (m_World->GetTickRandomNumber(100) < 20)) // 20% chance of flinging stuff around
|
||||
{
|
||||
if (!cBlockInfo::FullyOccupiesVoxel(Block))
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if ((m_World->GetTNTShrapnelLevel() == slGravityAffectedOnly) && ((Block != E_BLOCK_SAND) && (Block != E_BLOCK_GRAVEL)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
m_World->SpawnFallingBlock(bx + x, by + y + 5, bz + z, Block, area.GetBlockMeta(bx + x, by + y, bz + z));
|
||||
}
|
||||
|
||||
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
|
||||
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
|
||||
break;
|
||||
|
||||
}
|
||||
} // switch (BlockType)
|
||||
} // for z
|
||||
@ -1848,11 +1863,10 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
||||
public cEntityCallback
|
||||
{
|
||||
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_ExplosionPos(a_ExplosionPos),
|
||||
m_ExplosionSize(a_ExplosionSize),
|
||||
m_ExplosionSizeSq(a_ExplosionSizeSq)
|
||||
m_ExplosionSize(a_ExplosionSize)
|
||||
{
|
||||
}
|
||||
|
||||
@ -1875,14 +1889,16 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
||||
}
|
||||
|
||||
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
|
||||
AbsoluteEntityPos -= m_ExplosionPos;
|
||||
AbsoluteEntityPos = MaxExplosionBoundary - AbsoluteEntityPos;
|
||||
|
||||
double FinalDamage = ((AbsoluteEntityPos.x + AbsoluteEntityPos.y + AbsoluteEntityPos.z) / 3) * m_ExplosionSize;
|
||||
FinalDamage = a_Entity->GetMaxHealth() - abs(FinalDamage);
|
||||
// All to positive
|
||||
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
|
||||
if (FinalDamage > a_Entity->GetMaxHealth())
|
||||
@ -1890,7 +1906,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
||||
else if (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 and falling blocks, they should be invincible
|
||||
{
|
||||
a_Entity->TakeDamage(dtExplosion, NULL, (int)FinalDamage, 0);
|
||||
}
|
||||
@ -1900,7 +1916,7 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
||||
if (distance_explosion.SqrLength() < 4096.0)
|
||||
{
|
||||
distance_explosion.Normalize();
|
||||
distance_explosion *= m_ExplosionSizeSq;
|
||||
distance_explosion *= m_ExplosionSize * m_ExplosionSize;
|
||||
|
||||
a_Entity->AddSpeed(distance_explosion);
|
||||
}
|
||||
@ -1912,14 +1928,13 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
|
||||
cBoundingBox & m_bbTNT;
|
||||
Vector3d m_ExplosionPos;
|
||||
int m_ExplosionSize;
|
||||
int m_ExplosionSizeSq;
|
||||
};
|
||||
|
||||
cBoundingBox bbTNT(Vector3d(a_BlockX, a_BlockY, a_BlockZ), 0.5, 1);
|
||||
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);
|
||||
|
||||
// Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):
|
||||
|
@ -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,205 @@ 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() );
|
||||
bool HasHit = Tracer.Trace( NextPos, NextSpeed, 2 );
|
||||
if (HasHit) // 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( 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;
|
||||
}
|
||||
}
|
||||
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
|
||||
if (Tracer.HitNormal.y > 0) // means on ground
|
||||
{
|
||||
NextPos += (NextSpeed * a_Dt);
|
||||
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
|
||||
{
|
||||
// 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 +818,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 +924,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 +933,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
|
||||
|
@ -117,6 +117,7 @@ public:
|
||||
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
|
||||
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);
|
||||
|
@ -33,20 +33,16 @@ void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
|
||||
|
||||
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
|
||||
|
||||
int BlockX = m_OriginalPosition.x;
|
||||
int BlockX = POSX_TOINT;
|
||||
int BlockY = (int)(GetPosY() - 0.5);
|
||||
int BlockZ = m_OriginalPosition.z;
|
||||
int BlockZ = POSZ_TOINT;
|
||||
|
||||
if (BlockY < 0)
|
||||
{
|
||||
// Fallen out of this world, just continue falling until out of sight, then destroy:
|
||||
if (BlockY < 100)
|
||||
if (BlockY < VOID_BOUNDARY)
|
||||
{
|
||||
Destroy(true);
|
||||
}
|
||||
@ -86,6 +82,15 @@ void cFallingBlock::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
Destroy(true);
|
||||
return;
|
||||
}
|
||||
|
||||
float MilliDt = a_Dt * 0.001f;
|
||||
AddSpeedY(MilliDt * -9.8f);
|
||||
AddPosition(GetSpeed() * MilliDt);
|
||||
|
||||
if ((GetSpeedX() != 0) || (GetSpeedZ() != 0))
|
||||
{
|
||||
BroadcastMovementUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,8 +53,8 @@ public:
|
||||
{
|
||||
// Activate the TNT:
|
||||
a_World->BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 1.0f);
|
||||
a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5); // 80 ticks to boom
|
||||
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); // 80 ticks to boom
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -838,8 +838,8 @@ void cIncrementalRedstoneSimulator::HandleTNT(int a_BlockX, int a_BlockY, int a_
|
||||
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.SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5); // 80 ticks to boom
|
||||
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); // 80 ticks to boom
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,8 +250,6 @@ cWorld::cWorld(const AString & a_WorldName) :
|
||||
m_SkyDarkness(0),
|
||||
m_Weather(eWeather_Sunny),
|
||||
m_WeatherInterval(24000), // Guaranteed 1 day of sunshine at server start :)
|
||||
m_bCommandBlocksEnabled(false),
|
||||
m_bUseChatPrefixes(true),
|
||||
m_Scoreboard(this),
|
||||
m_MapManager(this),
|
||||
m_GeneratorCallbacks(*this),
|
||||
@ -579,12 +577,17 @@ void cWorld::Start(void)
|
||||
m_IsSugarcaneBonemealable = IniFile.GetValueSetB("Plants", "IsSugarcaneBonemealable", false);
|
||||
m_IsDeepSnowEnabled = IniFile.GetValueSetB("Physics", "DeepSnow", true);
|
||||
m_ShouldLavaSpawnFire = IniFile.GetValueSetB("Physics", "ShouldLavaSpawnFire", true);
|
||||
m_TNTShrapnelLevel = (eShrapnelLevel)IniFile.GetValueSetI("Physics", "TNTShrapnelLevel", 2);
|
||||
m_bCommandBlocksEnabled = IniFile.GetValueSetB("Mechanics", "CommandBlocksEnabled", false);
|
||||
m_bEnabledPVP = IniFile.GetValueSetB("Mechanics", "PVPEnabled", true);
|
||||
m_bUseChatPrefixes = IniFile.GetValueSetB("Mechanics", "UseChatPrefixes", true);
|
||||
m_VillagersShouldHarvestCrops = IniFile.GetValueSetB("Monsters", "VillagersShouldHarvestCrops", true);
|
||||
|
||||
m_GameMode = (eGameMode)IniFile.GetValueSetI("General", "Gamemode", m_GameMode);
|
||||
if (m_TNTShrapnelLevel > slAll)
|
||||
{
|
||||
m_TNTShrapnelLevel = slAll;
|
||||
}
|
||||
|
||||
// Load allowed mobs:
|
||||
const char * DefaultMonsters = "";
|
||||
@ -1730,7 +1733,11 @@ void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, int a_FuseTicks,
|
||||
UNUSED(a_InitialVelocityCoeff);
|
||||
cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTicks);
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -605,6 +605,9 @@ public:
|
||||
bool AreCommandBlocksEnabled(void) const { return m_bCommandBlocksEnabled; }
|
||||
void SetCommandBlocksEnabled(bool a_Flag) { m_bCommandBlocksEnabled = a_Flag; }
|
||||
|
||||
eShrapnelLevel GetTNTShrapnelLevel(void) const { return m_TNTShrapnelLevel; }
|
||||
void SetTNTShrapnelLevel(eShrapnelLevel a_Flag) { m_TNTShrapnelLevel = a_Flag; }
|
||||
|
||||
bool ShouldUseChatPrefixes(void) const { return m_bUseChatPrefixes; }
|
||||
void SetShouldUseChatPrefixes(bool a_Flag) { m_bUseChatPrefixes = a_Flag; }
|
||||
|
||||
@ -862,6 +865,11 @@ private:
|
||||
|
||||
/** Whether prefixes such as [INFO] are prepended to SendMessageXXX() / BroadcastChatXXX() functions */
|
||||
bool m_bUseChatPrefixes;
|
||||
|
||||
/** The level of DoExplosionAt() projecting random affected blocks as FallingBlock entities
|
||||
See the eShrapnelLevel enumeration for details
|
||||
*/
|
||||
eShrapnelLevel m_TNTShrapnelLevel;
|
||||
|
||||
|
||||
cChunkGenerator m_Generator;
|
||||
|
Loading…
Reference in New Issue
Block a user