summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--source/Entities/Entity.cpp33
-rw-r--r--source/Entities/Entity.h6
-rw-r--r--source/Entities/ProjectileEntity.cpp37
-rw-r--r--source/Entities/ProjectileEntity.h2
4 files changed, 70 insertions, 8 deletions
diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp
index b936d8d73..a07811a96 100644
--- a/source/Entities/Entity.cpp
+++ b/source/Entities/Entity.cpp
@@ -253,6 +253,39 @@ void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_R
+void cEntity::SetRotationFromSpeed(void)
+{
+ const double EPS = 0.0000001;
+ if ((abs(m_Speed.x) < EPS) && (abs(m_Speed.z) < EPS))
+ {
+ // atan2() may overflow or is undefined, pick any number
+ SetRotation(0);
+ return;
+ }
+ SetRotation(atan2(m_Speed.x, m_Speed.z) * 180 / PI);
+}
+
+
+
+
+
+void cEntity::SetPitchFromSpeed(void)
+{
+ const double EPS = 0.0000001;
+ double xz = sqrt(m_Speed.x * m_Speed.x + m_Speed.z * m_Speed.z); // Speed XZ-plane component
+ if ((abs(xz) < EPS) && (abs(m_Speed.y) < EPS))
+ {
+ // atan2() may overflow or is undefined, pick any number
+ SetPitch(0);
+ return;
+ }
+ SetPitch(atan2(m_Speed.y, xz) * 180 / PI);
+}
+
+
+
+
+
void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
{
if (cRoot::Get()->GetPluginManager()->CallHookTakeDamage(*this, a_TDI))
diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h
index aa5d8fbd2..0e30f230c 100644
--- a/source/Entities/Entity.h
+++ b/source/Entities/Entity.h
@@ -205,6 +205,12 @@ public:
void SetGravity(float a_Gravity) { m_Gravity = a_Gravity; }
+ /// Sets the rotation to match the speed vector (entity goes "face-forward")
+ void SetRotationFromSpeed(void);
+
+ /// Sets the pitch to match the speed vector (entity gies "face-forward")
+ void SetPitchFromSpeed(void);
+
// tolua_end
/// Makes this entity take damage specified in the a_TDI. The TDI is sent through plugins first, then applied
diff --git a/source/Entities/ProjectileEntity.cpp b/source/Entities/ProjectileEntity.cpp
index b97f72884..81ac336f0 100644
--- a/source/Entities/ProjectileEntity.cpp
+++ b/source/Entities/ProjectileEntity.cpp
@@ -16,6 +16,13 @@
+/// Converts an angle in radians into a byte representation used by the network protocol
+#define ANGLE_TO_PROTO(X) (Byte)(X * 255 / 360)
+
+
+
+
+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cProjectileTracerCallback:
@@ -189,6 +196,8 @@ cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Ve
m_IsInGround(false)
{
SetSpeed(a_Speed);
+ SetRotationFromSpeed();
+ SetPitchFromSpeed();
}
@@ -321,12 +330,15 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
NewSpeed.y += m_Gravity / 20;
NewSpeed *= TracerCallback.GetSlowdownCoeff();
SetSpeed(NewSpeed);
+ SetRotationFromSpeed();
+ SetPitchFromSpeed();
// DEBUG:
- LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}",
+ LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}, rot {%.02f, %.02f}",
m_UniqueID,
GetPosX(), GetPosY(), GetPosZ(),
- GetSpeedX(), GetSpeedY(), GetSpeedZ()
+ GetSpeedX(), GetSpeedY(), GetSpeedZ(),
+ GetRotation(), GetPitch()
);
}
@@ -337,7 +349,8 @@ void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
void cProjectileEntity::SpawnOn(cClientHandle & a_Client)
{
// Default spawning - use the projectile kind to spawn an object:
- a_Client.SendSpawnObject(*this, m_ProjectileKind, 0, 0, 0);
+ a_Client.SendSpawnObject(*this, m_ProjectileKind, 12, ANGLE_TO_PROTO(GetRotation()), ANGLE_TO_PROTO(GetPitch()));
+ a_Client.SendEntityMetadata(*this);
}
@@ -355,8 +368,11 @@ cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a
{
SetSpeed(a_Speed);
SetMass(0.1);
- LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f}",
- m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ()
+ SetRotationFromSpeed();
+ SetPitchFromSpeed();
+ LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f} and rot {%.02f, %.02f}",
+ m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ(),
+ GetRotation(), GetPitch()
);
}
@@ -392,14 +408,21 @@ bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
-void cArrowEntity::SpawnOn(cClientHandle & a_Client)
+void cArrowEntity::OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace)
{
- a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0);
+ super::OnHitSolidBlock(a_HitPos, a_HitFace);
+
+ // Broadcast the position and speed packets before teleporting:
+ BroadcastMovementUpdate();
+
+ // Teleport the entity to the exact hit coords:
+ m_World->BroadcastTeleportEntity(*this);
}
+
void cArrowEntity::OnHitEntity(cEntity & a_EntityHit)
{
if (!a_EntityHit.IsMob() && !a_EntityHit.IsMinecart() && !a_EntityHit.IsPlayer())
diff --git a/source/Entities/ProjectileEntity.h b/source/Entities/ProjectileEntity.h
index 5863b4f10..43aecac0e 100644
--- a/source/Entities/ProjectileEntity.h
+++ b/source/Entities/ProjectileEntity.h
@@ -151,7 +151,7 @@ protected:
bool m_IsCritical;
// cProjectileEntity overrides:
- virtual void SpawnOn(cClientHandle & a_Client) override;
+ virtual void OnHitSolidBlock(const Vector3d & a_HitPos, char a_HitFace) override;
virtual void OnHitEntity(cEntity & a_EntityHit) override;
// tolua_begin