summaryrefslogtreecommitdiffstats
path: root/source/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'source/Entities')
-rw-r--r--source/Entities/Entity.cpp50
-rw-r--r--source/Entities/Entity.h4
-rw-r--r--source/Entities/Minecart.cpp323
-rw-r--r--source/Entities/Minecart.h5
4 files changed, 360 insertions, 22 deletions
diff --git a/source/Entities/Entity.cpp b/source/Entities/Entity.cpp
index a07811a96..1a593b3d1 100644
--- a/source/Entities/Entity.cpp
+++ b/source/Entities/Entity.cpp
@@ -536,6 +536,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
int RelBlockZ = BlockZ - (NextChunk->GetPosZ() * cChunkDef::Width);
BLOCKTYPE BlockIn = NextChunk->GetBlock( RelBlockX, BlockY, RelBlockZ );
+ BLOCKTYPE BlockBelow = NextChunk->GetBlock( RelBlockX, BlockY - 1, RelBlockZ );
if (!g_BlockIsSolid[BlockIn]) // Making sure we are not inside a solid block
{
if (m_bOnGround) // check if it's still on the ground
@@ -578,18 +579,28 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
}
else
{
- // Friction
- if (NextSpeed.SqrLength() > 0.0004f)
+ // TODO: This condition belongs to minecarts, without it, they derails too much.
+ // But it shouldn't be here for other entities. We need a complete minecart physics overhaul.
+ if (
+ (BlockBelow != E_BLOCK_RAIL) &&
+ (BlockBelow != E_BLOCK_DETECTOR_RAIL) &&
+ (BlockBelow != E_BLOCK_POWERED_RAIL) &&
+ (BlockBelow != E_BLOCK_ACTIVATOR_RAIL)
+ )
{
- NextSpeed.x *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.x) < 0.05)
+ // Friction
+ if (NextSpeed.SqrLength() > 0.0004f)
{
- NextSpeed.x = 0;
- }
- NextSpeed.z *= 0.7f / (1 + a_Dt);
- if (fabs(NextSpeed.z) < 0.05)
- {
- NextSpeed.z = 0;
+ NextSpeed.x *= 0.6666;
+ if (fabs(NextSpeed.x) < 0.05)
+ {
+ NextSpeed.x = 0;
+ }
+ NextSpeed.z *= 0.6666;
+ if (fabs(NextSpeed.z) < 0.05)
+ {
+ NextSpeed.z = 0;
+ }
}
}
}
@@ -1249,6 +1260,25 @@ void cEntity::AddSpeedZ(double a_AddSpeedZ)
+void cEntity::SteerVehicle(float a_Forward, float a_Sideways)
+{
+ if (m_AttachedTo == NULL)
+ {
+ return;
+ }
+ if ((a_Forward != 0) || (a_Sideways != 0))
+ {
+ Vector3d LookVector = GetLookVector();
+ double AddSpeedX = LookVector.x * a_Forward + LookVector.z * a_Sideways;
+ double AddSpeedZ = LookVector.z * a_Forward - LookVector.x * a_Sideways;
+ m_AttachedTo->AddSpeed(AddSpeedX, 0, AddSpeedZ);
+ }
+}
+
+
+
+
+
//////////////////////////////////////////////////////////////////////////
// Get look vector (this is NOT a rotation!)
Vector3d cEntity::GetLookVector(void) const
diff --git a/source/Entities/Entity.h b/source/Entities/Entity.h
index 0e30f230c..b063838eb 100644
--- a/source/Entities/Entity.h
+++ b/source/Entities/Entity.h
@@ -185,6 +185,8 @@ public:
void AddSpeedX (double a_AddSpeedX);
void AddSpeedY (double a_AddSpeedY);
void AddSpeedZ (double a_AddSpeedZ);
+
+ void SteerVehicle(float a_Forward, float a_Sideways);
inline int GetUniqueID(void) const { return m_UniqueID; }
inline bool IsDestroyed(void) const { return !m_IsInitialized; }
@@ -361,7 +363,7 @@ protected:
bool m_bOnGround;
float m_Gravity;
-
+
// Last Position.
double m_LastPosX, m_LastPosY, m_LastPosZ;
diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp
index 808579582..0c0b7b58a 100644
--- a/source/Entities/Minecart.cpp
+++ b/source/Entities/Minecart.cpp
@@ -2,6 +2,7 @@
// Minecart.cpp
// Implements the cMinecart class representing a minecart in the world
+// Indiana Jones!
#include "Globals.h"
#include "Minecart.h"
@@ -17,6 +18,9 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
super(etMinecart, a_X, a_Y, a_Z, 0.98, 0.7),
m_Payload(a_Payload)
{
+ SetMass(20.f);
+ SetMaxHealth(6);
+ SetHealth(6);
}
@@ -24,30 +28,329 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
{
- char Type = 0;
- switch (m_Payload) //Wiki.vg is outdated on this!!
+ char SubType = 0;
+ switch (m_Payload)
{
- case mpNone: Type = 9; break; //?
- case mpChest: Type = 10; break;
- case mpFurnace: Type = 11; break; //?
- case mpTNT: Type = 12; break; //?
- case mpHopper: Type = 13; break; //?
+ case mpNone: SubType = 0; break;
+ case mpChest: SubType = 1; break;
+ case mpFurnace: SubType = 2; break;
+ case mpTNT: SubType = 3; break;
+ case mpHopper: SubType = 5; break;
default:
{
ASSERT(!"Unknown payload, cannot spawn on client");
return;
}
}
- a_ClientHandle.SendSpawnVehicle(*this, Type);
+ a_ClientHandle.SendSpawnVehicle(*this, 10, SubType); // 10 = Minecarts, SubType = What type of Minecart
}
-void cMinecart::Tick(float a_Dt, cChunk & a_Chunk)
+void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk)
{
- // TODO: the physics
+ if ((GetPosY() > 0) && (GetPosY() < cChunkDef::Height))
+ {
+ BLOCKTYPE BelowType = GetWorld()->GetBlock(floor(GetPosX()), floor(GetPosY() -1 ), floor(GetPosZ()));
+
+ if (
+ (BelowType == E_BLOCK_RAIL) ||
+ (BelowType == E_BLOCK_POWERED_RAIL) ||
+ (BelowType == E_BLOCK_DETECTOR_RAIL) ||
+ (BelowType == E_BLOCK_ACTIVATOR_RAIL)
+ )
+ {
+ HandleRailPhysics(a_Dt, a_Chunk);
+ }
+ else
+ {
+ super::HandlePhysics(a_Dt, a_Chunk);
+ BroadcastMovementUpdate();
+ }
+ }
+ else
+ {
+ super::HandlePhysics(a_Dt, a_Chunk);
+ BroadcastMovementUpdate();
+ }
+}
+
+
+
+
+
+static const double MAX_SPEED = 8;
+static const double MAX_SPEED_NEGATIVE = (0 - MAX_SPEED);
+void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk)
+{
+
+ super::HandlePhysics(a_Dt, a_Chunk); // Main physics handling
+
+ /*
+ NOTE: Please bear in mind that taking away from negatives make them even more negative,
+ adding to negatives make them positive, etc.
+ */
+
+ // Get block meta below the cart
+ NIBBLETYPE BelowMeta = GetWorld()->GetBlockMeta(floor(GetPosX()), floor(GetPosY() -1 ), floor(GetPosZ()));
+ double SpeedX = GetSpeedX(), SpeedY = GetSpeedY(), SpeedZ = GetSpeedZ(); // Get current speed
+
+ switch (BelowMeta)
+ {
+ case E_META_RAIL_ZM_ZP: // NORTHSOUTH
+ {
+ SetRotation(270);
+ SpeedY = 0; // Don't move vertically as on ground
+ SpeedX = 0; // Correct diagonal movement from curved rails
+
+ // Set Y as current Y rounded up to bypass friction
+ SetPosY(floor(GetPosY()));
+
+ if (SpeedZ != 0) // Don't do anything if cart is stationary
+ {
+ if (SpeedZ > 0)
+ {
+ // Going SOUTH, slow down
+ SpeedZ = SpeedZ - 0.1;
+ }
+ else
+ {
+ // Going NORTH, slow down
+ SpeedZ = SpeedZ + 0.1;
+ }
+ }
+ break;
+ }
+
+ case E_META_RAIL_XM_XP: // EASTWEST
+ {
+ SetRotation(180);
+ SpeedY = 0;
+ SpeedZ = 0;
+
+ SetPosY(floor(GetPosY()));
+
+ if (SpeedX != 0)
+ {
+ if (SpeedX > 0)
+ {
+ SpeedX = SpeedX - 0.1;
+ }
+ else
+ {
+ SpeedX = SpeedX + 0.1;
+ }
+ }
+ break;
+ }
+
+ case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH
+ {
+ SetRotation(270);
+ SetPosY(floor(GetPosY()) + 0.2); // It seems it doesn't work without levitation :/
+ SpeedX = 0;
+
+ if (SpeedZ >= 0)
+ {
+ // SpeedZ POSITIVE, going SOUTH
+ if (SpeedZ <= MAX_SPEED) // Speed limit
+ {
+ SpeedZ = SpeedZ + 0.5; // Speed up
+ SpeedY = (0 - SpeedZ); // Downward movement is negative (0 minus positive numbers is negative)
+ }
+ else
+ {
+ SpeedZ = MAX_SPEED; // Enforce speed limit
+ SpeedY = (0 - SpeedZ);
+ }
+ }
+ else
+ {
+ // SpeedZ NEGATIVE, going NORTH
+ SpeedZ = SpeedZ + 0.4; // Slow down
+ SpeedY = (0 - SpeedZ); // Upward movement is positive (0 minus negative number is positive number)
+ }
+ break;
+ }
+
+ case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH
+ {
+ SetRotation(270);
+ SetPosY(floor(GetPosY()) + 0.2);
+ SpeedX = 0;
+
+ if (SpeedZ > 0)
+ {
+ // SpeedZ POSITIVE, going SOUTH
+ SpeedZ = SpeedZ - 0.4; // Slow down
+ SpeedY = SpeedZ; // Upward movement positive
+ }
+ else
+ {
+ if (SpeedZ >= MAX_SPEED_NEGATIVE) // Speed limit
+ {
+ // SpeedZ NEGATIVE, going NORTH
+ SpeedZ = SpeedZ - 0.5; // Speed up
+ SpeedY = SpeedZ; // Downward movement negative
+ }
+ else
+ {
+ SpeedZ = MAX_SPEED_NEGATIVE; // Enforce speed limit
+ SpeedY = SpeedZ;
+ }
+ }
+ break;
+ }
+
+ case E_META_RAIL_ASCEND_XM: // ASCEND EAST
+ {
+ SetRotation(180);
+ SetPosY(floor(GetPosY()) + 0.2);
+ SpeedZ = 0;
+
+ if (SpeedX >= 0)
+ {
+ if (SpeedX <= MAX_SPEED)
+ {
+ SpeedX = SpeedX + 0.5;
+ SpeedY = (0 - SpeedX);
+ }
+ else
+ {
+ SpeedX = MAX_SPEED;
+ SpeedY = (0 - SpeedX);
+ }
+ }
+ else
+ {
+ SpeedX = SpeedX + 0.4;
+ SpeedY = (0 - SpeedX);
+ }
+ break;
+ }
+
+ case E_META_RAIL_ASCEND_XP: // ASCEND WEST
+ {
+ SetRotation(180);
+ SetPosY(floor(GetPosY()) + 0.2);
+ SpeedZ = 0;
+
+ if (SpeedX > 0)
+ {
+ SpeedX = SpeedX - 0.4;
+ SpeedY = SpeedX;
+ }
+ else
+ {
+ if (SpeedX >= MAX_SPEED_NEGATIVE)
+ {
+ SpeedX = SpeedX - 0.5;
+ SpeedY = SpeedX;
+ }
+ else
+ {
+ SpeedX = MAX_SPEED_NEGATIVE;
+ SpeedY = SpeedX;
+ }
+ }
+ break;
+ }
+
+ case E_META_RAIL_CURVED_ZM_XM: // Ends pointing NORTH and WEST
+ {
+ SetRotation(315); // Set correct rotation server side
+ SetPosY(floor(GetPosY()) + 0.2); // Levitate dat cart
+
+ if (SpeedZ > 0) // Cart moving south
+ {
+ SpeedX = (0 - SpeedZ); // Diagonally move southwest (which will make cart hit a southwest rail)
+ }
+ else if (SpeedX > 0) // Cart moving east
+ {
+ SpeedZ = (0 - SpeedX); // Diagonally move northeast
+ }
+ break;
+ }
+
+ case E_META_RAIL_CURVED_ZM_XP: // Curved NORTH EAST
+ {
+ SetRotation(225);
+ SetPosY(floor(GetPosY()) + 0.2);
+
+ if (SpeedZ > 0)
+ {
+ SpeedX = SpeedZ;
+ }
+ else if (SpeedX < 0)
+ {
+ SpeedZ = SpeedX;
+ }
+ break;
+ }
+
+ case E_META_RAIL_CURVED_ZP_XM: // Curved SOUTH WEST
+ {
+ SetRotation(135);
+ SetPosY(floor(GetPosY()) + 0.2);
+
+ if (SpeedZ < 0)
+ {
+ SpeedX = SpeedZ;
+ }
+ else if (SpeedX > 0)
+ {
+ SpeedZ = SpeedX;
+ }
+ break;
+ }
+
+ case E_META_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST
+ {
+ SetRotation(45);
+ SetPosY(floor(GetPosY()) + 0.2);
+
+ if (SpeedZ < 0)
+ {
+ SpeedX = (0 - SpeedZ);
+ }
+ else if (SpeedX < 0)
+ {
+ SpeedZ = (0 - SpeedX);
+ }
+ break;
+ }
+
+ default:
+ {
+ ASSERT(!"Unhandled rail meta!"); // Dun dun DUN!
+ break;
+ }
+ }
+
+ // Set speed to speed variables
+ SetSpeedX(SpeedX);
+ SetSpeedY(SpeedY);
+ SetSpeedZ(SpeedZ);
+
+
+ // Broadcast position to client
+ BroadcastMovementUpdate();
+}
+
+
+
+
+
+void cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
+{
+ super::DoTakeDamage(TDI);
+
+ if (GetHealth() == 0)
+ {
+ Destroy(true);
+ }
}
diff --git a/source/Entities/Minecart.h b/source/Entities/Minecart.h
index c1a0e84a0..f98b02bb5 100644
--- a/source/Entities/Minecart.h
+++ b/source/Entities/Minecart.h
@@ -36,7 +36,10 @@ public:
// cEntity overrides:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
- virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
+ virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
+ void HandleRailPhysics(float a_Dt, cChunk & a_Chunk);
+ virtual void DoTakeDamage(TakeDamageInfo & TDI) override;
+
ePayload GetPayload(void) const { return m_Payload; }