summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchangyong guo <guo1487@163.com>2018-07-23 11:24:00 +0200
committerpeterbell10 <peterbell10@live.co.uk>2018-07-23 11:24:00 +0200
commit01e72ddb6567531b16f92af2564b853878b6ef65 (patch)
treeb91403cec84e0b405448d8fadbc2c39f2270ab47
parentKeep players in gmNotSet (#4248) (diff)
downloadcuberite-01e72ddb6567531b16f92af2564b853878b6ef65.tar
cuberite-01e72ddb6567531b16f92af2564b853878b6ef65.tar.gz
cuberite-01e72ddb6567531b16f92af2564b853878b6ef65.tar.bz2
cuberite-01e72ddb6567531b16f92af2564b853878b6ef65.tar.lz
cuberite-01e72ddb6567531b16f92af2564b853878b6ef65.tar.xz
cuberite-01e72ddb6567531b16f92af2564b853878b6ef65.tar.zst
cuberite-01e72ddb6567531b16f92af2564b853878b6ef65.zip
-rw-r--r--Server/Plugins/APIDump/APIDesc.lua10
-rw-r--r--src/ChunkMap.cpp19
-rw-r--r--src/Entities/Entity.cpp64
-rw-r--r--src/Entities/Entity.h11
-rw-r--r--src/Entities/Player.cpp28
-rw-r--r--src/Entities/Player.h2
-rw-r--r--src/World.cpp15
7 files changed, 129 insertions, 20 deletions
diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua
index ee1ed0d04..b6a4ec81e 100644
--- a/Server/Plugins/APIDump/APIDesc.lua
+++ b/Server/Plugins/APIDump/APIDesc.lua
@@ -3231,6 +3231,16 @@ local Hash = cCryptoHash.sha1HexString("DataToHash")
},
Notes = "Returns the entity classname that this class implements. Each descendant overrides this function.",
},
+ GetEnchantmentBlastKnockbackReduction =
+ {
+ Returns =
+ {
+ {
+ Type = "number",
+ },
+ },
+ Notes = "Returns explosion knock back reduction percent from blast protection level.",
+ },
GetEnchantmentCoverAgainst =
{
Params =
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index d970956f3..770d34b5a 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -1814,10 +1814,21 @@ void cChunkMap::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_
a_Entity.TakeDamage(dtExplosion, nullptr, static_cast<int>((1 / DistanceFromExplosion.Length()) * 6 * ExplosionSizeInt), 0);
}
- // Apply force to entities around the explosion - code modified from World.cpp DoExplosionAt()
- DistanceFromExplosion.Normalize();
- DistanceFromExplosion *= ExplosionSizeInt * ExplosionSizeInt;
- a_Entity.AddSpeed(DistanceFromExplosion);
+ double Length = DistanceFromExplosion.Length();
+ if (Length <= ExplosionSizeInt) // Entity is impacted by explosion
+ {
+ float EntityExposure = a_Entity.GetExplosionExposureRate(ExplosionPos, ExplosionSizeInt);
+
+ // Exposure reduced by armor
+ EntityExposure = EntityExposure * (1.0f - a_Entity.GetEnchantmentBlastKnockbackReduction());
+
+ double Impact = (1 - ((Length / ExplosionSizeInt) / 2)) * EntityExposure;
+
+ DistanceFromExplosion.Normalize();
+ DistanceFromExplosion *= Impact;
+
+ a_Entity.AddSpeed(DistanceFromExplosion);
+ }
return false;
}
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index d1fdcfd39..4ecc5c4da 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -14,7 +14,7 @@
#include "Items/ItemHandler.h"
#include "../FastRandom.h"
#include "../NetherPortalScanner.h"
-
+#include "../BoundingBox.h"
@@ -690,6 +690,33 @@ int cEntity::GetEnchantmentCoverAgainst(const cEntity * a_Attacker, eDamageType
+
+float cEntity::GetEnchantmentBlastKnockbackReduction()
+{
+ UInt32 MaxLevel = 0;
+
+ const cItem ArmorItems[] = { GetEquippedHelmet(), GetEquippedChestplate(), GetEquippedLeggings(), GetEquippedBoots() };
+
+ for (auto & Item : ArmorItems)
+ {
+ UInt32 Level = Item.m_Enchantments.GetLevel(cEnchantments::enchBlastProtection);
+ if (Level > MaxLevel)
+ {
+ // Get max blast protection
+ MaxLevel = Level;
+ }
+ }
+
+ // Max blast protect level is 4, each level provide 15% knock back reduction
+ MaxLevel = std::min<UInt32>(MaxLevel, 4);
+ return MaxLevel * 0.15f;
+}
+
+
+
+
+
+
int cEntity::GetArmorCoverAgainst(const cEntity * a_Attacker, eDamageType a_DamageType, int a_Damage)
{
// Returns the hitpoints out of a_RawDamage that the currently equipped armor would cover
@@ -2241,3 +2268,38 @@ void cEntity::RemoveLeashedMob(cMonster * a_Monster)
m_LeashedMobs.remove(a_Monster);
}
+
+
+
+
+
+
+float cEntity::GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower)
+{
+ double EntitySize = m_Width * m_Width * m_Height;
+ if (EntitySize <= 0)
+ {
+ // Handle entity with invalid size
+ return 0;
+ }
+
+ cBoundingBox EntityBox(GetPosition(), m_Width / 2, m_Height);
+ cBoundingBox ExplosionBox(a_ExplosionPosition, a_ExlosionPower * 2.0);
+ cBoundingBox IntersectionBox(EntityBox);
+
+ bool Overlap = EntityBox.Intersect(ExplosionBox, IntersectionBox);
+ if (Overlap)
+ {
+ Vector3d Diff = IntersectionBox.GetMax() - IntersectionBox.GetMin();
+ double OverlapSize = Diff.x * Diff.y * Diff.z;
+
+ return static_cast<float>(OverlapSize / EntitySize);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+
+
diff --git a/src/Entities/Entity.h b/src/Entities/Entity.h
index 7ac12c95b..ae150b4e2 100644
--- a/src/Entities/Entity.h
+++ b/src/Entities/Entity.h
@@ -333,6 +333,10 @@ public:
/** Returns the hitpoints that the currently equipped armor's enchantments would cover */
virtual int GetEnchantmentCoverAgainst(const cEntity * a_Attacker, eDamageType a_DamageType, int a_Damage);
+ /** Returns explosion knock back reduction percent from blast protection level
+ @return knock back reduce percent */
+ virtual float GetEnchantmentBlastKnockbackReduction();
+
/** Returns the knockback amount that the currently equipped items would cause to a_Receiver on a hit */
virtual double GetKnockbackAmountAgainst(const cEntity & a_Receiver);
@@ -545,6 +549,12 @@ public:
/** Returs whether the entity has any mob leashed to */
bool HasAnyMobLeashed() const { return m_LeashedMobs.size() > 0; }
+ /** a lightweight calculation approach to get explosion exposure rate
+ @param a_ExplosionPosition explosion position
+ @param a_ExlosionPower explosion power
+ @return exposure rate */
+ virtual float GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower);
+
protected:
/** Structure storing the portal delay timer and cooldown boolean */
struct sPortalCooldownData
@@ -714,5 +724,4 @@ private:
/** List of leashed mobs to this entity */
cMonsterList m_LeashedMobs;
-
} ; // tolua_export
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index d8bb22e2f..181a54870 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -3069,3 +3069,31 @@ float cPlayer::GetPlayerRelativeBlockHardness(BLOCKTYPE a_Block)
// LOGD("blockHardness: %f, digSpeed: %f, canHarvestBlockDivisor: %f\n", blockHardness, digSpeed, canHarvestBlockDivisor);
return (blockHardness < 0) ? 0 : ((digSpeed / blockHardness) / canHarvestBlockDivisor);
}
+
+
+
+
+
+
+float cPlayer::GetExplosionExposureRate(Vector3d a_ExplosionPosition, float a_ExlosionPower)
+{
+ if (
+ IsGameModeSpectator() ||
+ (IsGameModeCreative() && !IsOnGround())
+ )
+ {
+ return 0; // No impact from explosion
+ }
+
+ return super::GetExplosionExposureRate(a_ExplosionPosition, a_ExlosionPower);
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index e710e8396..c9249b2f1 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -759,6 +759,8 @@ protected:
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 adbac33bf..97155c872 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -1430,7 +1430,6 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo
}
// TODO: Implement block hardiness
- Vector3d explosion_pos = Vector3d(a_BlockX, a_BlockY, a_BlockZ);
cVector3iArray BlocksAffected;
m_ChunkMap->DoExplosionAt(a_ExplosionSize, a_BlockX, a_BlockY, a_BlockZ, BlocksAffected);
BroadcastSoundEffect("entity.generic.explode", Vector3d(a_BlockX, a_BlockY, a_BlockZ), 1.0f, 0.6f);
@@ -1445,19 +1444,7 @@ void cWorld::DoExplosionAt(double a_ExplosionSize, double a_BlockX, double a_Blo
continue;
}
- Vector3d distance_explosion = (*itr)->GetPosition() - explosion_pos;
- if (distance_explosion.SqrLength() < 4096.0)
- {
- double real_distance = std::max(0.004, distance_explosion.Length());
- double power = a_ExplosionSize / real_distance;
- if (power <= 1)
- {
- power = 0;
- }
- distance_explosion.Normalize();
- distance_explosion *= power;
- ch->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, static_cast<float>(a_ExplosionSize), BlocksAffected, distance_explosion);
- }
+ ch->SendExplosion(a_BlockX, a_BlockY, a_BlockZ, static_cast<float>(a_ExplosionSize), BlocksAffected, (*itr)->GetSpeed());
}
}