diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp index 1aa8dcb8b..d03919a85 100644 --- a/source/ChunkMap.cpp +++ b/source/ChunkMap.cpp @@ -1497,13 +1497,12 @@ bool cChunkMap::ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback -cVector3iArray * cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ) +void cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ, cVector3iArray & a_BlocksAffected) { cBlockArea area; - cVector3iArray * BlocksAffected = new cVector3iArray(); int ExplosionSizeInt = (int) ceil(a_ExplosionSize); int ExplosionSizeSq = ExplosionSizeInt * ExplosionSizeInt; - BlocksAffected->reserve(8 * ExplosionSizeInt * ExplosionSizeInt * ExplosionSizeInt); + a_BlocksAffected.reserve(8 * ExplosionSizeInt * ExplosionSizeInt * ExplosionSizeInt); area.Read(m_World, a_BlockX - ExplosionSizeInt, a_BlockX + ExplosionSizeInt, a_BlockY - ExplosionSizeInt, a_BlockY + ExplosionSizeInt, a_BlockZ - ExplosionSizeInt,a_BlockZ + ExplosionSizeInt); for (int x = -ExplosionSizeInt; x < ExplosionSizeInt; x++) { @@ -1516,43 +1515,42 @@ cVector3iArray * cChunkMap::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, } for (int z = -ExplosionSizeInt; z < ExplosionSizeInt; z++) { - if ((x * x + y * y + z * z) < ExplosionSizeSq) + if ((x * x + y * y + z * z) > ExplosionSizeSq) { - switch (area.GetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + 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; - cTNTEntity * TNT = new cTNTEntity(a_BlockX, a_BlockY, a_BlockZ, FuseTime); - TNT->Initialize(m_World); - area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_AIR); - BlocksAffected->push_back(Vector3i(a_BlockX + x, a_BlockY + y, a_BlockZ + z)); - break; - } - case E_BLOCK_OBSIDIAN: - case E_BLOCK_BEDROCK: - case E_BLOCK_WATER: - case E_BLOCK_STATIONARY_WATER: - case E_BLOCK_STATIONARY_LAVA: - case E_BLOCK_LAVA: - { - // These blocks are not affected by explosions - break; - } - default: - { - area.SetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + z, E_BLOCK_AIR); - BlocksAffected->push_back(Vector3i(a_BlockX + x, a_BlockY + y, a_BlockZ + z)); - } - } + // Too far away + continue; } - } - } - - } - area.Write(m_World,a_BlockX - ExplosionSizeInt,a_BlockY - ExplosionSizeInt,a_BlockZ - ExplosionSizeInt); - return BlocksAffected; + switch (area.GetBlockType(a_BlockX + x, a_BlockY + y, a_BlockZ + 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; + 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)); + break; + } + case E_BLOCK_OBSIDIAN: + case E_BLOCK_BEDROCK: + case E_BLOCK_WATER: + case E_BLOCK_STATIONARY_WATER: + case E_BLOCK_STATIONARY_LAVA: + case E_BLOCK_LAVA: + { + // These blocks are not affected by explosions + 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)); + } + } // switch (BlockType) + } // for z + } // for y + } // for x + area.Write(m_World, a_BlockX - ExplosionSizeInt, a_BlockY - ExplosionSizeInt, a_BlockZ - ExplosionSizeInt); } diff --git a/source/ChunkMap.h b/source/ChunkMap.h index f8f03e063..4139b0761 100644 --- a/source/ChunkMap.h +++ b/source/ChunkMap.h @@ -202,8 +202,8 @@ public: /// Calls the callback for each entity in the specified chunk; returns true if all entities processed, false if the callback aborted by returning true bool ForEachEntityInChunk(int a_ChunkX, int a_ChunkZ, cEntityCallback & a_Callback); // Lua-accessible - // Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates - cVector3iArray * DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ); + /// Destroys and returns a list of blocks destroyed in the explosion at the specified coordinates + void DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, int a_BlockZ, cVector3iArray & a_BlockAffected); /// Calls the callback if the entity with the specified ID is found, with the entity object as the callback param. Returns true if entity found and callback returned false. bool DoWithEntityByID(int a_UniqueID, cEntityCallback & a_Callback); // Lua-accessible diff --git a/source/ClientHandle.cpp b/source/ClientHandle.cpp index cbe544c1f..13b7e64c9 100644 --- a/source/ClientHandle.cpp +++ b/source/ClientHandle.cpp @@ -1561,7 +1561,7 @@ void cClientHandle::SendEntityStatus(const cEntity & a_Entity, char a_Status) -void cClientHandle::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) +void cClientHandle::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) { m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotion); } diff --git a/source/ClientHandle.h b/source/ClientHandle.h index 886a34322..4568f1a58 100644 --- a/source/ClientHandle.h +++ b/source/ClientHandle.h @@ -98,7 +98,7 @@ public: void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ); void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item); void SendEntityStatus (const cEntity & a_Entity, char a_Status); - void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion); + void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion); void SendGameMode (eGameMode a_GameMode); void SendHealth (void); void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value); diff --git a/source/Items/ItemLighter.h b/source/Items/ItemLighter.h index bcea8545f..dcca08d47 100644 --- a/source/Items/ItemLighter.h +++ b/source/Items/ItemLighter.h @@ -34,8 +34,7 @@ public: { // Activate the TNT: a_World->BroadcastSoundEffect("random.fuse", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f); - cTNTEntity * TNT = new cTNTEntity(a_BlockX, a_BlockY, a_BlockZ, 4); // 4 seconds to boom - TNT->Initialize(a_World); + 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); break; } diff --git a/source/Protocol/Protocol.h b/source/Protocol/Protocol.h index 91017dbaf..2dd80fc5f 100644 --- a/source/Protocol/Protocol.h +++ b/source/Protocol/Protocol.h @@ -67,7 +67,7 @@ public: virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) = 0; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) = 0; virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) = 0; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) = 0; virtual void SendGameMode (eGameMode a_GameMode) = 0; virtual void SendHealth (void) = 0; virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) = 0; diff --git a/source/Protocol/Protocol125.cpp b/source/Protocol/Protocol125.cpp index a4b5feb82..bce24498a 100644 --- a/source/Protocol/Protocol125.cpp +++ b/source/Protocol/Protocol125.cpp @@ -352,7 +352,7 @@ void cProtocol125::SendEntityStatus(const cEntity & a_Entity, char a_Status) -void cProtocol125::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) +void cProtocol125::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) { cCSLock Lock(m_CSPacket); WriteByte(PACKET_EXPLOSION); diff --git a/source/Protocol/Protocol125.h b/source/Protocol/Protocol125.h index b7c5ff424..2e0c04212 100644 --- a/source/Protocol/Protocol125.h +++ b/source/Protocol/Protocol125.h @@ -44,7 +44,7 @@ public: virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) override; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (void) override; virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) override; diff --git a/source/Protocol/ProtocolRecognizer.cpp b/source/Protocol/ProtocolRecognizer.cpp index 3b971cf49..518d03058 100644 --- a/source/Protocol/ProtocolRecognizer.cpp +++ b/source/Protocol/ProtocolRecognizer.cpp @@ -267,7 +267,7 @@ void cProtocolRecognizer::SendEntityStatus(const cEntity & a_Entity, char a_Stat -void cProtocolRecognizer::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) +void cProtocolRecognizer::SendExplosion(double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) { ASSERT(m_Protocol != NULL); m_Protocol->SendExplosion(a_BlockX,a_BlockY,a_BlockZ,a_Radius, a_BlocksAffected, a_PlayerMotion); diff --git a/source/Protocol/ProtocolRecognizer.h b/source/Protocol/ProtocolRecognizer.h index 768eb64c7..75a4d828a 100644 --- a/source/Protocol/ProtocolRecognizer.h +++ b/source/Protocol/ProtocolRecognizer.h @@ -72,7 +72,7 @@ public: virtual void SendEntRelMoveLook (const cEntity & a_Entity, char a_RelX, char a_RelY, char a_RelZ) override; virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override; virtual void SendEntityStatus (const cEntity & a_Entity, char a_Status) override; - virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, cVector3iArray a_BlocksAffected, const Vector3d & a_PlayerMotion) override; + virtual void SendExplosion (double a_BlockX, double a_BlockY, double a_BlockZ, float a_Radius, const cVector3iArray & a_BlocksAffected, const Vector3d & a_PlayerMotion) override; virtual void SendGameMode (eGameMode a_GameMode) override; virtual void SendHealth (void) override; virtual void SendInventoryProgress (char a_WindowID, short a_Progressbar, short a_Value) override; diff --git a/source/TNTEntity.cpp b/source/TNTEntity.cpp index ec4bc6dfa..32850e246 100644 --- a/source/TNTEntity.cpp +++ b/source/TNTEntity.cpp @@ -8,22 +8,22 @@ -cTNTEntity::cTNTEntity(int a_X,int a_Y,int a_Z,float a_MaxFuseTime) : - super(etTNT, a_X + 0.5f, a_Y + 0.5f, a_Z + 0.5f) +cTNTEntity::cTNTEntity(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec) : + super(etTNT, a_X, a_Y, a_Z), + m_Counter(0), + m_MaxFuseTime(a_FuseTimeInSec) { - m_MaxFuseTime = a_MaxFuseTime; - m_Counter = 0; } -cTNTEntity::cTNTEntity(const Vector3i a_Pos,float a_MaxFuseTime) : - super(etTNT, a_Pos.x,a_Pos.y,a_Pos.z) +cTNTEntity::cTNTEntity(const Vector3d & a_Pos, float a_FuseTimeInSec) : + super(etTNT, a_Pos.x, a_Pos.y, a_Pos.z), + m_Counter(0), + m_MaxFuseTime(a_FuseTimeInSec) { - m_MaxFuseTime = a_MaxFuseTime; - m_Counter = 0; } diff --git a/source/TNTEntity.h b/source/TNTEntity.h index 8414b2430..d20b6aca4 100644 --- a/source/TNTEntity.h +++ b/source/TNTEntity.h @@ -11,21 +11,22 @@ class cTNTEntity : public cEntity { -typedef cEntity super; + typedef cEntity super; public: CLASS_PROTODEF(cTNTEntity); - cTNTEntity(int a_X,int a_Y,int a_Z,float a_MaxFuseTime); - cTNTEntity(const Vector3i a_Pos,float a_MaxFuseTime); + cTNTEntity(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec); + cTNTEntity(const Vector3d & a_Pos, float a_FuseTimeInSec); // cEntity overrides: virtual void Initialize(cWorld * a_World) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void Tick(float a_Dt, cChunk & a_Chunk) override; -private: - float m_Counter; //In seconds too - float m_MaxFuseTime; //in seconds + +protected: + float m_Counter; ///< How much time has elapsed since the object was created, in seconds + float m_MaxFuseTime; ///< How long the fuse is, in seconds }; diff --git a/source/World.cpp b/source/World.cpp index 51863919f..398077c61 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -55,6 +55,7 @@ #include "PluginManager.h" #include "Blocks/BlockHandler.h" #include "Vector3d.h" +#include "TNTEntity.h" #include "tolua++.h" @@ -737,7 +738,8 @@ void cWorld::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, i { // TODO: Add damage to entities, add support for pickups, and implement block hardiness Vector3d explosion_pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ); - cVector3iArray * BlocksAffected = m_ChunkMap->DoExplosiontAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ); + cVector3iArray BlocksAffected; + m_ChunkMap->DoExplosiontAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ, BlocksAffected); BroadcastSoundEffect("random.explode", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.6f); { cCSLock Lock(m_CSPlayers); @@ -759,11 +761,10 @@ void cWorld::DoExplosiontAt(float a_ExplosionSize, int a_BlockX, int a_BlockY, i } distance_explosion.Normalize(); distance_explosion *= power; - ch->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, a_ExplosionSize, *BlocksAffected, distance_explosion); + ch->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, a_ExplosionSize, BlocksAffected, distance_explosion); } } } - delete BlocksAffected; } @@ -1314,6 +1315,17 @@ void cWorld::SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double +void cWorld::SpawnPrimedTNT(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec) +{ + cTNTEntity * TNT = new cTNTEntity(a_X, a_Y, a_Z, a_FuseTimeInSec); + TNT->Initialize(this); + // TODO: Add a bit of speed in horiz and vert axes +} + + + + + void cWorld::ReplaceBlocks(const sSetBlockVector & a_Blocks, BLOCKTYPE a_FilterBlockType) { m_ChunkMap->ReplaceBlocks(a_Blocks, a_FilterBlockType); diff --git a/source/World.h b/source/World.h index fe339ea61..6bc6cb4c7 100644 --- a/source/World.h +++ b/source/World.h @@ -329,6 +329,9 @@ public: /// Spawns item pickups for each item in the list. May compress pickups if too many entities. All pickups get the speed specified: void SpawnItemPickups(const cItems & a_Pickups, double a_BlockX, double a_BlockY, double a_BlockZ, double a_SpeedX, double a_SpeedY, double a_SpeedZ); + + /// Spawns a new primed TNT entity at the specified block coords and specified fuse duration + void SpawnPrimedTNT(double a_X, double a_Y, double a_Z, float a_FuseTimeInSec); // tolua_end