1
0

Added OnExploding() and OnExploded() hooks.

As requested in FS 413, with extra parameters:
World, BlockX, BlockY, BlockZ, Size, CanCauseFire, Source, SourceData

OnExploding() can return 3 values:
StopHook, CanCauseFire, ExplosionSize
This commit is contained in:
madmaxoft
2013-08-09 14:58:43 +02:00
parent 6f2c099f70
commit d4a3c451c4
16 changed files with 686 additions and 62 deletions

View File

@@ -1546,16 +1546,16 @@ bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback
void cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ, cVector3iArray & a_BlocksAffected)
void cChunkMap::DoExplosiontAt(double a_ExplosionSize, double a_BlockX, double a_BlockY, double a_BlockZ, cVector3iArray & a_BlocksAffected)
{
// Don't explode if outside of Y range (prevents the following test running into unallocated memory):
if ((a_BlockY < 0) || (a_BlockY >= cChunkDef::Height))
if ((a_BlockY < 0) || (a_BlockY > cChunkDef::Height - 1))
{
return;
}
// Don't explode if the explosion center is inside a liquid block:
switch (m_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ))
switch (m_World->GetBlock((int)floor(a_BlockX), (int)floor(a_BlockY), (int)floor(a_BlockZ)))
{
case E_BLOCK_WATER:
case E_BLOCK_STATIONARY_WATER:
@@ -1567,17 +1567,20 @@ void cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY
}
cBlockArea area;
int bx = (int)floor(a_BlockX);
int by = (int)floor(a_BlockY);
int bz = (int)floor(a_BlockZ);
int ExplosionSizeInt = (int) ceil(a_ExplosionSize);
int ExplosionSizeSq = ExplosionSizeInt * ExplosionSizeInt;
a_BlocksAffected.reserve(8 * ExplosionSizeInt * ExplosionSizeInt * ExplosionSizeInt);
int MinY = std::max(a_BlockY - ExplosionSizeInt, 0);
int MaxY = std::min(a_BlockY + ExplosionSizeInt, cChunkDef::Height - 1);
area.Read(m_World, a_BlockX - ExplosionSizeInt, a_BlockX + ExplosionSizeInt, MinY, MaxY, a_BlockZ - ExplosionSizeInt,a_BlockZ + ExplosionSizeInt);
int MinY = std::max((int)floor(a_BlockY - ExplosionSizeInt), 0);
int MaxY = std::min((int)ceil(a_BlockY + ExplosionSizeInt), cChunkDef::Height - 1);
area.Read(m_World, bx - ExplosionSizeInt, (int)ceil(a_BlockX + ExplosionSizeInt), MinY, MaxY, bz - ExplosionSizeInt, (int)ceil(a_BlockZ + ExplosionSizeInt));
for (int x = -ExplosionSizeInt; x < ExplosionSizeInt; x++)
{
for (int y = -ExplosionSizeInt; y < ExplosionSizeInt; y++)
{
if ((a_BlockY + y >= cChunkDef::Height) || (a_BlockY + y < 0))
if ((by + y >= cChunkDef::Height) || (by + y < 0))
{
// Outside of the world
continue;
@@ -1589,15 +1592,15 @@ void cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY
// Too far away
continue;
}
switch (area.GetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z))
switch (area.GetBlockType(bx + x, by + y, bz + z))
{
case E_BLOCK_TNT:
{
// Activate the TNT, with a random fuse between 10 to 30 game ticks
float FuseTime = (float)(10 + m_World->GetTickRandomNumber(20)) / 20;
double FuseTime = (double)(10 + m_World->GetTickRandomNumber(20)) / 20;
m_World->SpawnPrimedTNT(a_BlockX + x + 0.5, a_BlockY + y + 0.5, a_BlockZ + z + 0.5, FuseTime);
area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_AIR);
a_BlocksAffected.push_back(Vector3i(a_BlockX + x, a_BlockY + y, a_BlockZ + z));
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
break;
}
case E_BLOCK_OBSIDIAN:
@@ -1612,33 +1615,33 @@ void cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY
case E_BLOCK_STATIONARY_WATER:
{
// Turn into simulated water:
area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_WATER);
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_WATER);
break;
}
case E_BLOCK_STATIONARY_LAVA:
{
// Turn into simulated lava:
area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_LAVA);
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_LAVA);
break;
}
default:
{
area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_AIR);
a_BlocksAffected.push_back(Vector3i(a_BlockX + x, a_BlockY + y, a_BlockZ + z));
area.SetBlockType(bx + x, by + y, bz + z, E_BLOCK_AIR);
a_BlocksAffected.push_back(Vector3i(bx + x, by + y, bz + z));
}
} // switch (BlockType)
} // for z
} // for y
} // for x
area.Write(m_World, a_BlockX - ExplosionSizeInt, MinY, a_BlockZ - ExplosionSizeInt);
area.Write(m_World, bx - ExplosionSizeInt, MinY, bz - ExplosionSizeInt);
// Wake up all simulators for the area, so that water and lava flows and sand falls into the blasted holes (FS #391):
WakeUpSimulatorsInArea(
a_BlockX - ExplosionSizeInt, a_BlockX + ExplosionSizeInt,
bx - ExplosionSizeInt, bx + ExplosionSizeInt + 1,
MinY, MaxY,
a_BlockZ - ExplosionSizeInt, a_BlockZ + ExplosionSizeInt
bz - ExplosionSizeInt, bz + ExplosionSizeInt + 1
);
}