From b5c63d8fc50d9f8ff179988a9a14010de89f5d75 Mon Sep 17 00:00:00 2001 From: Tiger Wang Date: Mon, 2 Sep 2013 12:01:49 +0100 Subject: Minecart enhancements [SEE DESC] Curved rails. Better physics. Better code as improved by xoft. Stuff. --- source/Entities/Minecart.cpp | 350 +++++++++++++++++++++++++++++-------------- source/Entities/Minecart.h | 5 +- 2 files changed, 242 insertions(+), 113 deletions(-) diff --git a/source/Entities/Minecart.cpp b/source/Entities/Minecart.cpp index a148886a6..9a92df38e 100644 --- a/source/Entities/Minecart.cpp +++ b/source/Entities/Minecart.cpp @@ -20,6 +20,7 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) : { SetMass(20.f); SetMaxHealth(6); + SetHealth(6); } @@ -62,183 +63,308 @@ void cMinecart::SpawnOn(cClientHandle & a_ClientHandle) -void cMinecart::Tick(float a_Dt, cChunk & a_Chunk) +void cMinecart::HandlePhysics(float a_Dt, cChunk & a_Chunk) { + 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. */ - super::Tick(a_Dt, a_Chunk); - - BLOCKTYPE BelowType; - NIBBLETYPE BelowMeta; + // 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 - - // Get block type & meta below the cart - GetWorld()->GetBlockTypeMeta(floor(GetPosX()), floor(GetPosY() -1 ), floor(GetPosZ()), BelowType, BelowMeta); - - if ((BelowType == E_BLOCK_RAIL) || (BelowType == E_BLOCK_DETECTOR_RAIL) || (BelowType == E_BLOCK_ACTIVATOR_RAIL)) + + switch (BelowMeta) { - switch (BelowMeta) + case E_RAIL_ZM_ZP: // NORTHSOUTH { - - case E_RAIL_ZM_ZP: + 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 { - SpeedY = 0; // Don't move vertically as on ground - - // 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 { - if (SpeedZ > 0) - { - // Going SOUTH, slow down - SpeedZ = SpeedZ - 0.1; - } - else - { - // Going NORTH, slow down - SpeedZ = SpeedZ + 0.1; - } + // Going NORTH, slow down + SpeedZ = SpeedZ + 0.1; } - break; } + break; + } - case E_RAIL_XM_XP: - { - SpeedY = 0; - SetPosY(floor(GetPosY())); + case E_RAIL_XM_XP: // EASTWEST + { + SetRotation(180); + SpeedY = 0; + SpeedZ = 0; - if (SpeedX != 0) + SetPosY(floor(GetPosY())); + + if (SpeedX != 0) + { + if (SpeedX > 0) { - if (SpeedX > 0) - { - SpeedX = SpeedX - 0.1; - } - else - { - SpeedX = SpeedX + 0.1; - } + SpeedX = SpeedX - 0.1; + } + else + { + SpeedX = SpeedX + 0.1; } - break; } + break; + } + + case E_RAIL_ASCEND_ZM: // ASCEND NORTH + { + SetRotation(270); + SetPosY(floor(GetPosY()) + 0.2); // It seems it doesn't work without levitation :/ + SpeedX = 0; - case E_RAIL_ASCEND_ZM: + if (SpeedZ >= 0) { - if (SpeedZ >= 0) + // SpeedZ POSITIVE, going SOUTH + if (SpeedZ <= MAX_SPEED) // Speed limit { - // SpeedZ POSITIVE, going SOUTH - if (SpeedZ <= 8) // Speed limit of 8 SOUTH (m/s??) - { - SpeedZ = SpeedZ + 0.5; // Speed up - SpeedY = (0 - SpeedZ); // Downward movement is negative (0 minus positive numbers is negative) - } - else - { - SpeedZ = 8; // Enforce speed limit - SpeedY = (0 - SpeedZ); - } + SpeedZ = SpeedZ + 0.5; // Speed up + SpeedY = (0 - SpeedZ); // Downward movement is negative (0 minus positive numbers is negative) } else { - // SpeedZ NEGATIVE, going NORTH - SpeedZ = SpeedZ + 0.6; // Slow down - SpeedY = (0 - SpeedZ); // Upward movement is positive (0 minus negative number is positive number) + SpeedZ = MAX_SPEED; // Enforce speed limit + SpeedY = (0 - SpeedZ); } - break; } + 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_RAIL_ASCEND_ZP: // ASCEND SOUTH + { + SetRotation(270); + SetPosY(floor(GetPosY()) + 0.2); + SpeedX = 0; - case E_RAIL_ASCEND_ZP: + if (SpeedZ > 0) { - if (SpeedX > 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 POSITIVE, going SOUTH - SpeedZ = SpeedZ - 0.6; // Slow down - SpeedY = SpeedZ; // Upward movement positive + // SpeedZ NEGATIVE, going NORTH + SpeedZ = SpeedZ - 0.5; // Speed up + SpeedY = SpeedZ; // Downward movement negative } else { - if (SpeedZ >= -8) // Speed limit of 8 WEST (m/s??) - { - // SpeedZ NEGATIVE, going NORTH - SpeedZ = SpeedZ - 0.5; // Speed up - SpeedY = SpeedZ; // Downward movement negative - } - else - { - SpeedZ = 8; // Enforce speed limit - SpeedY = SpeedZ; - } + SpeedZ = MAX_SPEED_NEGATIVE; // Enforce speed limit + SpeedY = SpeedZ; } - break; } + break; + } + + case E_RAIL_ASCEND_XM: // ASCEND EAST + { + SetRotation(180); + SetPosY(floor(GetPosY()) + 0.2); + SpeedZ = 0; - case E_RAIL_ASCEND_XM: + if (SpeedX >= 0) { - if (SpeedX >= 0) + if (SpeedX <= MAX_SPEED) { - if (SpeedX <= 8) - { - SpeedX = SpeedX + 0.5; - SpeedY = (0 - SpeedX); - } - else - { - SpeedX = 8; - SpeedY = (0 - SpeedX); - } + SpeedX = SpeedX + 0.5; + SpeedY = (0 - SpeedX); } else { - SpeedX = SpeedX + 0.6; + SpeedX = MAX_SPEED; SpeedY = (0 - SpeedX); } - break; } + else + { + SpeedX = SpeedX + 0.4; + SpeedY = (0 - SpeedX); + } + break; + } + + case E_RAIL_ASCEND_XP: // ASCEND WEST + { + SetRotation(180); + SetPosY(floor(GetPosY()) + 0.2); + SpeedZ = 0; - case E_RAIL_ASCEND_XP: + if (SpeedX > 0) { - if (SpeedX > 0) + SpeedX = SpeedX - 0.4; + SpeedY = SpeedX; + } + else + { + if (SpeedX >= MAX_SPEED_NEGATIVE) { - SpeedX = SpeedX - 0.6; + SpeedX = SpeedX - 0.5; SpeedY = SpeedX; } else { - if (SpeedX >= -8) - { - SpeedX = SpeedX - 0.5; - SpeedY = SpeedX; - } - else - { - SpeedX = -8; - SpeedY = SpeedX; - } + SpeedX = MAX_SPEED_NEGATIVE; + SpeedY = SpeedX; } - break; } + break; + } + + case E_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_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_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; + } - default: + case E_RAIL_CURVED_ZP_XP: // Curved SOUTH EAST + { + SetRotation(45); + SetPosY(floor(GetPosY()) + 0.2); + + if (SpeedZ < 0) + { + SpeedX = (0 - SpeedZ); + } + else if (SpeedX < 0) { - ASSERT(!"Unhandled rail meta!"); - break; + SpeedZ = (0 - SpeedX); } + break; + } + default: + { + ASSERT(!"Unhandled rail meta!"); // Dun dun DUN! + break; } } - + // Set speed to speed variables SetSpeedX(SpeedX); SetSpeedY(SpeedY); SetSpeedZ(SpeedZ); - // Pass to physics handlers in Entity.cpp and broadcast position to client - HandlePhysics(a_Dt, a_Chunk); + + // 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 91336673d..b3386fbc9 100644 --- a/source/Entities/Minecart.h +++ b/source/Entities/Minecart.h @@ -37,7 +37,10 @@ public: // cEntity overrides: virtual bool Initialize(cWorld * a_World) override; 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; } -- cgit v1.2.3