diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp index f2c0cf59f..fdaf7390d 100644 --- a/src/ChunkMap.cpp +++ b/src/ChunkMap.cpp @@ -1313,18 +1313,19 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_ a_Entity.TakeDamage(dtExplosion, nullptr, static_cast((1 / std::max(1.0, DistanceFromExplosion.Length())) * 8 * ExplosionSizeInt), 0); } - double Length = DistanceFromExplosion.Length(); - if (Length <= ExplosionSizeInt) // Entity is impacted by explosion + float EntityExposure = a_Entity.GetExplosionExposureRate(ExplosionPos, static_cast(a_ExplosionSize)); + + // Exposure reduced by armor + EntityExposure = EntityExposure * (1.0f - a_Entity.GetEnchantmentBlastKnockbackReduction()); + + auto Impact = std::pow(std::max(0.2, DistanceFromExplosion.Length()), -1); + Impact *= EntityExposure * ExplosionSizeInt * 6.0; + + if (Impact > 0.0) { - float EntityExposure = a_Entity.GetExplosionExposureRate(ExplosionPos, static_cast(a_ExplosionSize)); - - // Exposure reduced by armor - EntityExposure = EntityExposure * (1.0f - a_Entity.GetEnchantmentBlastKnockbackReduction()); - - double Impact = (1 - ((Length / ExplosionSizeInt) / 2)) * EntityExposure; - DistanceFromExplosion.Normalize(); - DistanceFromExplosion *= Impact; + DistanceFromExplosion *= Vector3d{Impact, 0.0, Impact}; + DistanceFromExplosion.y += 0.3 * Impact; a_Entity.SetSpeed(DistanceFromExplosion); } @@ -2315,8 +2316,3 @@ void cChunkMap::DelChunkStay(cChunkStay & a_ChunkStay) } // for itr - Chunks[] a_ChunkStay.OnDisabled(); } - - - - - diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp index 8876566da..b5d7f7c83 100644 --- a/src/Entities/Player.cpp +++ b/src/Entities/Player.cpp @@ -3080,7 +3080,7 @@ float cPlayer::GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_Ex return 0; // No impact from explosion } - return super::GetExplosionExposureRate(a_ExplosionPosition, a_ExlosionPower); + return super::GetExplosionExposureRate(a_ExplosionPosition, a_ExlosionPower) / 30.0f; } diff --git a/src/Entities/Player.h b/src/Entities/Player.h index bea6e98f6..fafdd04eb 100644 --- a/src/Entities/Player.h +++ b/src/Entities/Player.h @@ -581,6 +581,9 @@ public: Otherwise it returns the dig speed (float GetDigSpeed(BLOCKTYPE a_Block)) divided by the block hardness (cBlockInfo::GetHardness(BLOCKTYPE a_Block)) divided by 30 if the player can harvest the block and divided by 100 if he can't. */ float GetPlayerRelativeBlockHardness(BLOCKTYPE a_Block); + /** get player explosion exposure rate */ + virtual float GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower) override; + protected: typedef std::vector > AStringVectorVector; @@ -759,9 +762,6 @@ protected: /** Returns the filename for the player data based on the UUID given. This can be used both for online and offline UUIDs. */ AString GetUUIDFileName(const cUUID & a_UUID); - - /** get player explosion exposure rate */ - virtual float GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower) override; private: /** Pins the player to a_Location until Unfreeze() is called. diff --git a/src/World.cpp b/src/World.cpp index a08c269d8..9c7928c89 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -1417,17 +1417,20 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo BroadcastSoundEffect("entity.generic.explode", Vector3d(a_BlockX, a_BlockY, a_BlockZ), 4.0f, SoundPitchMultiplier * 0.7f); + Vector3d ExplosionPos(a_BlockX, a_BlockY, a_BlockZ); { cCSLock Lock(m_CSPlayers); - for (cPlayerList::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + for (auto Player : m_Players) { - cClientHandle * ch = (*itr)->GetClientHandle(); + cClientHandle * ch = Player->GetClientHandle(); if (ch == nullptr) { continue; } - ch->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, static_cast(a_ExplosionSize), BlocksAffected, (*itr)->GetSpeed()); + bool InRange = (Player->GetExplosionExposureRate(ExplosionPos, static_cast(a_ExplosionSize)) > 0); + auto Speed = InRange ? Player->GetSpeed() : Vector3d{}; + ch->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, static_cast(a_ExplosionSize), BlocksAffected, Speed); } }