private bool Explosion()
{
List<BData> toClean = _explosion;
if ( ++_currentR <= R ) {
_explosion = new List<BData>();
int rPrev = 0;
for ( int z = _currentR; z >= 0; --z ) {
double r2 = _currentR * _currentR - z * z;
double r = Math.Sqrt( r2 );
double yPrev = r;
for ( double x = 0; x <= Math.Round( r ); ++x ) {
if ( x > r )
x = r;
double y = Math.Sqrt( r2 - x * x );
int ix = ( int )Math.Round( x );
for ( int iy = ix > rPrev ? 0 : ( int )Math.Round( y ); iy < Math.Max( Math.Round( y ) + 1, Math.Round( yPrev ) ); ++iy ) {
for ( int mx = -1; mx < 2; mx += 2 ) {
for ( int my = -1; my < 2; my += 2 ) {
for ( int mz = -1; mz < 2; mz += 2 ) {
if ( _owner.CanPlace( _map, new Vector3I( mx * ix + _pos.X, my * iy + _pos.Y, mz * z + _pos.Z ), Block.Wood, BlockChangeContext.Manual ) == CanPlaceResult.Allowed ) {
TryAddPoint( mx * ix + _pos.X, my * iy + _pos.Y, mz * z + _pos.Z );
}
yPrev = y;
}
}
}
}
}
rPrev = ( int )Math.Round( r );
}
Util.RndPermutate( _explosion );
foreach ( BData pt in _explosion ) {
if ( _owner.CanPlace( _map, new Vector3I( pt.X, pt.Y, pt.Z ), Block.Wood, BlockChangeContext.Manual ) == CanPlaceResult.Allowed ) {
if ( _map.GetBlock( pt.X, pt.Y, pt.Z ) != Block.Lava ) //if another tnt hasnt already caused lava here
{
UpdateMap( new BlockUpdate( null, ( short )pt.X, ( short )pt.Y, ( short )pt.Z, Block.Lava ) );
foreach ( Player p in _world.Players ) {
if ( p.CanBeKilled() && p.Position.DistanceSquaredTo( ( new Vector3I( pt.X, pt.Y, pt.Z ) ).ToPlayerCoords() ) <= 64 * 64 ) //less or equal than 2 blocks
HitPlayer( _world, p, _owner );
}
}
}
}
}
if ( null != toClean ) {
foreach ( BData pt in toClean ) {
if ( _owner.CanPlace( _map, new Vector3I( pt.X, pt.Y, pt.Z ), Block.Wood, BlockChangeContext.Manual ) == CanPlaceResult.Allowed ) {
UpdateMap( new BlockUpdate( null, ( short )pt.X, ( short )pt.Y, ( short )pt.Z,
pt.PrevBlock == Block.Water ? Block.Water : Block.Air ) );
}
}
toClean.Clear();
}
return _currentR <= R;
}