summaryrefslogtreecommitdiffstats
path: root/src/Entities
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Entities/ArrowEntity.cpp14
-rw-r--r--src/Entities/FireChargeEntity.cpp4
-rw-r--r--src/Entities/Player.cpp39
-rw-r--r--src/Entities/Player.h3
-rw-r--r--src/Entities/ProjectileEntity.cpp69
-rw-r--r--src/Entities/ProjectileEntity.h40
-rw-r--r--src/Entities/ThrownSnowballEntity.cpp4
7 files changed, 123 insertions, 50 deletions
diff --git a/src/Entities/ArrowEntity.cpp b/src/Entities/ArrowEntity.cpp
index 76b4c9758..47789992c 100644
--- a/src/Entities/ArrowEntity.cpp
+++ b/src/Entities/ArrowEntity.cpp
@@ -102,6 +102,8 @@ void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFa
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
{
+ super::OnHitEntity(a_EntityHit, a_HitPos);
+
int Damage = static_cast<int>(GetSpeed().Length() / 20 * m_DamageCoeff + 0.5);
if (m_IsCritical)
{
@@ -140,7 +142,7 @@ void cArrowEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
// Broadcast successful hit sound
GetWorld()->BroadcastSoundEffect("random.successful_hit", GetPosX(), GetPosY(), GetPosZ(), 0.5, static_cast<float>(0.75 + (static_cast<float>((GetUniqueID() * 23) % 32)) / 64));
-
+
Destroy();
}
@@ -177,7 +179,7 @@ void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
m_Timer += a_Dt;
-
+
if (m_bIsCollected)
{
if (m_Timer > std::chrono::milliseconds(500))
@@ -191,7 +193,7 @@ void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
Destroy();
return;
}
-
+
if (m_IsInGround)
{
if (!m_HasTeleported) // Sent a teleport already, don't do again
@@ -206,17 +208,17 @@ void cArrowEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
m_HitGroundTimer += a_Dt;
}
}
-
+
int RelPosX = m_HitBlockPos.x - a_Chunk.GetPosX() * cChunkDef::Width;
int RelPosZ = m_HitBlockPos.z - a_Chunk.GetPosZ() * cChunkDef::Width;
cChunk * Chunk = a_Chunk.GetRelNeighborChunkAdjustCoords(RelPosX, RelPosZ);
-
+
if (Chunk == nullptr)
{
// Inside an unloaded chunk, abort
return;
}
-
+
if (Chunk->GetBlock(RelPosX, m_HitBlockPos.y, RelPosZ) == E_BLOCK_AIR) // Block attached to was destroyed?
{
m_IsInGround = false; // Yes, begin simulating physics again
diff --git a/src/Entities/FireChargeEntity.cpp b/src/Entities/FireChargeEntity.cpp
index 0db4b66d3..56ce9ef3f 100644
--- a/src/Entities/FireChargeEntity.cpp
+++ b/src/Entities/FireChargeEntity.cpp
@@ -43,9 +43,11 @@ void cFireChargeEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_
void cFireChargeEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
{
+ super::OnHitEntity(a_EntityHit, a_HitPos);
+
Destroy();
Explode(a_HitPos.Floor());
-
+
if (!a_EntityHit.IsFireproof())
{
// TODO Damage Entity with 5 damage(from http://minecraft.gamepedia.com/Blaze#Blaze_fireball)
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 80f07cb65..c5a1e0f95 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -2,6 +2,8 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Player.h"
+#include "Mobs/Wolf.h"
+#include "../BoundingBox.h"
#include <unordered_map>
#include "../ChatColor.h"
#include "../Server.h"
@@ -850,6 +852,7 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
AddFoodExhaustion(0.3f);
SendHealth();
+ NotifyFriendlyWolves(a_TDI.Attacker);
m_Stats.AddValue(statDamageTaken, FloorC<StatValue>(a_TDI.FinalDamage * 10 + 0.5));
return true;
}
@@ -860,6 +863,42 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
+void cPlayer::NotifyFriendlyWolves(cEntity * a_Opponent)
+{
+ class LookForWolves : public cEntityCallback
+ {
+ public:
+ cPlayer * m_Player;
+ cEntity * m_Attacker;
+
+ LookForWolves(cPlayer * a_Me, cEntity * a_MyAttacker) :
+ m_Player(a_Me),
+ m_Attacker(a_MyAttacker)
+ {
+ }
+
+ virtual bool Item(cEntity * a_Entity) override
+ {
+ if (a_Entity->IsMob())
+ {
+ cMonster * Mob = static_cast<cMonster*>(a_Entity);
+ if (Mob->GetMobType() == mtWolf)
+ {
+ cWolf * Wolf = static_cast<cWolf*>(Mob);
+ Wolf->NearbyPlayerIsFighting(m_Player, m_Attacker);
+ }
+ }
+ return false;
+ }
+ } Callback(this, a_Opponent);
+
+ m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 16, 16), Callback);
+}
+
+
+
+
+
void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
{
super::KilledBy(a_TDI);
diff --git a/src/Entities/Player.h b/src/Entities/Player.h
index 10c9106a3..47f98c157 100644
--- a/src/Entities/Player.h
+++ b/src/Entities/Player.h
@@ -499,6 +499,9 @@ public:
Assumes that all the blocks are in currently loaded chunks. */
bool PlaceBlocks(const sSetBlockVector & a_Blocks);
+ /** Notify friendly wolves that we took damage or did damage to an entity so that they might assist us. */
+ void NotifyFriendlyWolves(cEntity * a_Opponent);
+
// cEntity overrides:
virtual bool IsCrouched (void) const override { return m_IsCrouched; }
virtual bool IsSprinting(void) const override { return m_IsSprinting; }
diff --git a/src/Entities/ProjectileEntity.cpp b/src/Entities/ProjectileEntity.cpp
index 064076456..4c89ea965 100644
--- a/src/Entities/ProjectileEntity.cpp
+++ b/src/Entities/ProjectileEntity.cpp
@@ -48,13 +48,13 @@ public:
m_SlowdownCoeff(0.99) // Default slowdown when not in water
{
}
-
+
double GetSlowdownCoeff(void) const { return m_SlowdownCoeff; }
-
+
protected:
cProjectileEntity * m_Projectile;
double m_SlowdownCoeff;
-
+
// cCallbacks overrides:
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
{
@@ -67,7 +67,7 @@ protected:
ItemToString(cItem(a_BlockType, 1, a_BlockMeta)).c_str()
);
*/
-
+
if (cBlockInfo::IsSolid(a_BlockType))
{
// The projectile hit a solid block, calculate the exact hit coords:
@@ -94,7 +94,7 @@ protected:
LOGD("WEIRD! block tracer reports a hit, but BBox tracer doesn't. Ignoring the hit.");
}
}
-
+
// Convey some special effects from special blocks:
switch (a_BlockType)
{
@@ -113,7 +113,7 @@ protected:
break;
}
} // switch (a_BlockType)
-
+
// Continue tracing
return false;
}
@@ -138,8 +138,8 @@ public:
m_HitEntity(nullptr)
{
}
-
-
+
+
virtual bool Item(cEntity * a_Entity) override
{
if (
@@ -153,9 +153,9 @@ public:
return false;
}
}
-
+
cBoundingBox EntBox(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
-
+
// Instead of colliding the bounding box with another bounding box in motion, we collide an enlarged bounding box with a hairline.
// The results should be good enough for our purposes
double LineCoeff;
@@ -178,27 +178,27 @@ public:
// A plugin disagreed.
return false;
}
-
+
if (LineCoeff < m_MinCoeff)
{
// The entity is closer than anything we've stored so far, replace it as the potential victim
m_MinCoeff = LineCoeff;
m_HitEntity = a_Entity;
}
-
+
// Don't break the enumeration, we want all the entities
return false;
}
-
+
/** Returns the nearest entity that was hit, after the enumeration has been completed */
cEntity * GetHitEntity(void) const { return m_HitEntity; }
-
+
/** Returns the line coeff where the hit was encountered, after the enumeration has been completed */
double GetMinCoeff(void) const { return m_MinCoeff; }
-
+
/** Returns true if the callback has encountered a true hit */
bool HasHit(void) const { return (m_MinCoeff < 1); }
-
+
protected:
cProjectileEntity * m_Projectile;
const Vector3d & m_Pos;
@@ -283,7 +283,7 @@ cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator,
}
case pkFishingFloat: break;
}
-
+
LOGWARNING("%s: Unknown projectile kind: %d", __FUNCTION__, a_Kind);
return nullptr;
}
@@ -312,6 +312,35 @@ void cProjectileEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_
+void cProjectileEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
+{
+ if (a_EntityHit.IsPawn() && (GetCreatorName() != "")) // If we're hitting a mob or a player and we were created by a player
+ {
+ class cNotifyWolves : public cEntityCallback
+ {
+ public:
+ cEntity * m_EntityHit;
+
+ cNotifyWolves(cEntity * a_Entity) :
+ m_EntityHit(a_Entity)
+ {
+ }
+
+ virtual bool Item(cEntity * a_Player) override
+ {
+ static_cast<cPlayer*>(a_Player)->NotifyFriendlyWolves(m_EntityHit);
+ return true;
+ }
+ } Callback(&a_EntityHit);
+
+ m_World->DoWithEntityByID(GetCreatorUniqueID(), Callback);
+ }
+}
+
+
+
+
+
AString cProjectileEntity::GetMCAClassName(void) const
{
switch (m_ProjectileKind)
@@ -353,7 +382,7 @@ void cProjectileEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a
// Already-grounded projectiles don't move at all
return;
}
-
+
auto DtSec = std::chrono::duration_cast<std::chrono::duration<double>>(a_Dt);
const Vector3d DeltaSpeed = GetSpeed() * DtSec.count();
@@ -380,7 +409,7 @@ void cProjectileEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a
OnHitEntity(*(EntityCollisionCallback.GetHitEntity()), HitPos);
}
// TODO: Test the entities in the neighboring chunks, too
-
+
// Trace the tick's worth of movement as a line:
cProjectileTracerCallback TracerCallback(this);
if (!cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
@@ -392,7 +421,7 @@ void cProjectileEntity::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a
// Update the position:
SetPosition(NextPos);
-
+
// Add slowdown and gravity effect to the speed:
Vector3d NewSpeed(GetSpeed());
NewSpeed.y += m_Gravity * DtSec.count();
diff --git a/src/Entities/ProjectileEntity.h b/src/Entities/ProjectileEntity.h
index 7ee87f93a..b354c7cfc 100644
--- a/src/Entities/ProjectileEntity.h
+++ b/src/Entities/ProjectileEntity.h
@@ -21,7 +21,7 @@ class cProjectileEntity :
public cEntity
{
typedef cEntity super;
-
+
public:
/** The kind of the projectile. The numbers correspond to the network type ID used for spawning them in the protocol. */
enum eKind
@@ -38,26 +38,22 @@ public:
pkWitherSkull = 66,
pkFishingFloat = 90,
} ;
-
+
// tolua_end
-
+
CLASS_PROTODEF(cProjectileEntity)
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
-
+
static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const cItem * a_Item, const Vector3d * a_Speed = nullptr);
-
+
/** Called by the physics blocktracer when the entity hits a solid block, the hit position and the face hit (BLOCK_FACE_) is given */
virtual void OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFace a_HitFace);
-
+
/** Called by the physics blocktracer when the entity hits another entity */
- virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
- {
- UNUSED(a_EntityHit);
- UNUSED(a_HitPos);
- }
-
+ virtual void OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos);
+
/** Called by Chunk when the projectile is eligible for player collection */
virtual void CollectedBy(cPlayer & a_Dest);
@@ -65,7 +61,7 @@ public:
/** Returns the kind of the projectile (fast class identification) */
eKind GetProjectileKind(void) const { return m_ProjectileKind; }
-
+
/** Returns the unique ID of the entity who created this projectile
May return an ID <0
*/
@@ -75,18 +71,18 @@ public:
Will be empty for non-player creators
*/
AString GetCreatorName(void) const { return m_CreatorData.m_Name; }
-
+
/** Returns the string that is used as the entity type (class name) in MCA files */
AString GetMCAClassName(void) const;
-
+
/** Returns true if the projectile has hit the ground and is stuck there */
bool IsInGround(void) const { return m_IsInGround; }
-
+
// tolua_end
-
+
/** Sets the internal InGround flag. To be used by MCA loader only! */
void SetIsInGround(bool a_IsInGround) { m_IsInGround = a_IsInGround; }
-
+
protected:
/** A structure that stores the Entity ID and Playername of the projectile's creator
@@ -107,17 +103,17 @@ protected:
/** The type of projectile I am */
eKind m_ProjectileKind;
-
+
/** The structure for containing the entity ID and name who has created this projectile
The ID and / or name may be nullptr (e.g. for dispensers / mobs). */
CreatorData m_CreatorData;
-
+
/** True if the projectile has hit the ground and is stuck there */
bool m_IsInGround;
-
+
// cEntity overrides:
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
virtual void SpawnOn(cClientHandle & a_Client) override;
-
+
} ; // tolua_export
diff --git a/src/Entities/ThrownSnowballEntity.cpp b/src/Entities/ThrownSnowballEntity.cpp
index b28205d44..ab5429011 100644
--- a/src/Entities/ThrownSnowballEntity.cpp
+++ b/src/Entities/ThrownSnowballEntity.cpp
@@ -29,6 +29,8 @@ void cThrownSnowballEntity::OnHitSolidBlock(const Vector3d & a_HitPos, eBlockFac
void cThrownSnowballEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d & a_HitPos)
{
+ super::OnHitEntity(a_EntityHit, a_HitPos);
+
int TotalDamage = 0;
if (a_EntityHit.IsMob())
{
@@ -40,7 +42,7 @@ void cThrownSnowballEntity::OnHitEntity(cEntity & a_EntityHit, const Vector3d &
}
// TODO: If entity is Ender Crystal, destroy it
a_EntityHit.TakeDamage(dtRangedAttack, this, TotalDamage, 1);
-
+
m_DestroyTimer = 5;
}