summaryrefslogtreecommitdiffstats
path: root/src/Entities/Boat.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Entities/Boat.cpp')
-rw-r--r--src/Entities/Boat.cpp138
1 files changed, 70 insertions, 68 deletions
diff --git a/src/Entities/Boat.cpp b/src/Entities/Boat.cpp
index aecbd8125..66ae8a894 100644
--- a/src/Entities/Boat.cpp
+++ b/src/Entities/Boat.cpp
@@ -15,10 +15,11 @@
cBoat::cBoat(Vector3d a_Pos, eMaterial a_Material) :
- Super(etBoat, a_Pos, 1.5, 0.6),
- m_LastDamage(0), m_ForwardDirection(0),
- m_DamageTaken(0.0f), m_Material(a_Material),
- m_RightPaddleUsed(false), m_LeftPaddleUsed(false)
+ Super(etBoat, a_Pos, 1.375, 0.5625),
+ m_Material(a_Material),
+ m_LeftPaddleUsed(false),
+ m_RightPaddleUsed(false),
+ m_ShouldShakeForwards(true)
{
SetMass(20.0f);
SetGravity(-16.0f);
@@ -41,53 +42,29 @@ void cBoat::SpawnOn(cClientHandle & a_ClientHandle)
-void cBoat::BroadcastMovementUpdate(const cClientHandle * a_Exclude)
+bool cBoat::DoTakeDamage(TakeDamageInfo & TDI)
{
- // Cannot use super::BroadcastMovementUpdate here, broadcasting position when not
- // expected by the client breaks things. See https://github.com/cuberite/cuberite/pull/4488
+ if (
+ const auto Attacker = TDI.Attacker;
- // Process packet sending every two ticks
- if (GetWorld()->GetWorldAge() % 2 != 0)
+ (Attacker != nullptr) &&
+ Attacker->IsPlayer() &&
+ static_cast<cPlayer *>(Attacker)->IsGameModeCreative()
+ )
{
- return;
+ TDI.FinalDamage = GetMaxHealth(); // Instant hit for creative
+ return Super::DoTakeDamage(TDI);
}
- Vector3i Diff = (GetPosition() * 32.0).Floor() - (m_LastSentPosition * 32.0).Floor();
- if (Diff.HasNonZeroLength()) // Have we moved?
- {
- m_World->BroadcastEntityPosition(*this, a_Exclude);
- m_LastSentPosition = GetPosition();
- m_bDirtyOrientation = false;
- }
-}
-
-
-
-
-
-bool cBoat::DoTakeDamage(TakeDamageInfo & TDI)
-{
- m_LastDamage = 10;
if (!Super::DoTakeDamage(TDI))
{
return false;
}
- m_World->BroadcastEntityMetadata(*this);
+ m_World->BroadcastEntityMetadata(*this); // Tell the client to play the shaking animation
+ m_ShouldShakeForwards = !m_ShouldShakeForwards; // The next shake goes the opposite direction
- if (GetHealth() <= 0)
- {
- if (TDI.Attacker != nullptr)
- {
- if (TDI.Attacker->IsPlayer())
- {
- cItems Pickups;
- Pickups.Add(MaterialToItem(m_Material));
- m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 0, 0, 0, true);
- }
- }
- Destroy();
- }
+ SetInvulnerableTicks(2); // Make rapid attacks have more of an effect
return true;
}
@@ -101,7 +78,7 @@ void cBoat::OnRightClicked(cPlayer & a_Player)
if (m_Attachee != nullptr)
{
- if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
+ if (m_Attachee == &a_Player)
{
// This player is already sitting in, they want out.
a_Player.Detach();
@@ -126,38 +103,61 @@ void cBoat::OnRightClicked(cPlayer & a_Player)
-void cBoat::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
+void cBoat::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{
- Super::Tick(a_Dt, a_Chunk);
- if (!IsTicking())
+ if (
+ (a_Killer != nullptr) &&
+ a_Killer->IsPlayer() &&
+ !static_cast<cPlayer *>(a_Killer)->IsGameModeCreative() // No drops for creative
+ )
{
- // The base class tick destroyed us
- return;
+ a_Drops.Add(MaterialToItem(m_Material));
}
- BroadcastMovementUpdate();
+}
- SetSpeed(GetSpeed() * 0.97); // Slowly decrease the speed
- if ((POSY_TOINT < 0) || (POSY_TOINT >= cChunkDef::Height))
- {
- return;
- }
+
+
+
+void cBoat::KilledBy(TakeDamageInfo & a_TDI)
+{
+ Super::KilledBy(a_TDI);
+ Destroy();
+}
+
+
+
+
+
+void cBoat::HandlePhysics(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
+{
+ const auto Position = POS_TOINT;
+ const auto InWater = IsBlockWater(m_World->GetBlock(Position));
+ const auto DtSec = std::chrono::duration_cast<std::chrono::duration<double>>(a_Dt).count();
// A real boat floats.
// Propel to top water block and sit slightly beneath the waterline:
- if (IsBlockWater(m_World->GetBlock(POSX_TOINT, POSY_TOINT, POSZ_TOINT)) && ((GetPosY() - POSY_TOINT) < 0.6))
+ if (InWater)
{
- if (GetSpeedY() < 2)
- {
- const auto DtSec = std::chrono::duration_cast<std::chrono::duration<double>>(a_Dt).count();
- SetSpeedY((-m_Gravity + 1) * DtSec);
- }
+ // Counteract gravity and provide a small upwards force:
+ SetSpeedY((-m_Gravity + 1) * DtSec);
}
- if (GetLastDamage() > 0)
+ auto Speed = GetSpeed();
+ ApplyFriction(Speed, 0.9, DtSec); // Slowly decrease the speed
+ SetSpeed(Speed);
+
+ Super::HandlePhysics(a_Dt, a_Chunk);
+
+ const auto AbovePosition = Position.addedY(1);
+ const auto OnSurface = !IsBlockWater(m_World->GetBlock(AbovePosition));
+ if (InWater && OnSurface)
{
- SetLastDamage(GetLastDamage() - 1);
+ SetSpeedY(0);
+ SetPosY(Position.y + 0.52);
}
+
+ BroadcastMovementUpdate();
}
@@ -181,12 +181,18 @@ void cBoat::HandleSpeedFromAttachee(float a_Forward, float a_Sideways)
-void cBoat::SetLastDamage(int TimeSinceLastHit)
+float cBoat::GetDamageTaken(void) const
{
- m_LastDamage = TimeSinceLastHit;
+ return GetMaxHealth() - GetHealth();
+}
+
+
+
- // Tell the client to play the shaking animation
- m_World->BroadcastEntityMetadata(*this);
+
+bool cBoat::ShouldShakeForwards(void) const
+{
+ return m_ShouldShakeForwards;
}
@@ -300,7 +306,3 @@ cItem cBoat::MaterialToItem(eMaterial a_Material)
}
UNREACHABLE("Unsupported boat material");
}
-
-
-
-