Arrows have proper yaw and pitch when shot, and stop when they hit a block.
This commit is contained in:
parent
5c0039e7b0
commit
3f4718154b
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user