diff options
Diffstat (limited to 'src/Entities/Minecart.cpp')
-rw-r--r-- | src/Entities/Minecart.cpp | 220 |
1 files changed, 169 insertions, 51 deletions
diff --git a/src/Entities/Minecart.cpp b/src/Entities/Minecart.cpp index d4eadc5d5..f45e7bb69 100644 --- a/src/Entities/Minecart.cpp +++ b/src/Entities/Minecart.cpp @@ -7,12 +7,12 @@ #include "Globals.h" #include "Minecart.h" -#include "../World.h" #include "../ClientHandle.h" #include "../Chunk.h" #include "Player.h" #include "../BoundingBox.h" +#define NO_SPEED 0.0 #define MAX_SPEED 8 #define MAX_SPEED_NEGATIVE -MAX_SPEED @@ -220,7 +220,7 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) return; - if (GetSpeedZ() != 0) // Don't do anything if cart is stationary + if (GetSpeedZ() != NO_SPEED) // Don't do anything if cart is stationary { if (GetSpeedZ() > 0) { @@ -239,13 +239,13 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) { SetYaw(180); SetPosY(floor(GetPosY()) + 0.55); - SetSpeedY(0); - SetSpeedZ(0); + SetSpeedY(NO_SPEED); + SetSpeedZ(NO_SPEED); bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) return; - if (GetSpeedX() != 0) + if (GetSpeedX() != NO_SPEED) { if (GetSpeedX() > 0) { @@ -305,9 +305,9 @@ void cMinecart::HandleRailPhysics(NIBBLETYPE a_RailMeta, float a_Dt) case E_META_RAIL_ASCEND_XM: // ASCEND EAST { SetYaw(180); - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); - if (GetSpeedX() >= 0) + if (GetSpeedX() >= NO_SPEED) { if (GetSpeedX() <= MAX_SPEED) { @@ -424,9 +424,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) return; - if (GetSpeedZ() != 0) + if (GetSpeedZ() != NO_SPEED) { - if (GetSpeedZ() > 0) + if (GetSpeedZ() > NO_SPEED) { AddSpeedZ(AccelDecelSpeed); } @@ -441,15 +441,15 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) { SetYaw(180); SetPosY(floor(GetPosY()) + 0.55); - SetSpeedY(0); - SetSpeedZ(0); + SetSpeedY(NO_SPEED); + SetSpeedZ(NO_SPEED); bool BlckCol = TestBlockCollision(a_RailMeta), EntCol = TestEntityCollision(a_RailMeta); if (EntCol || BlckCol) return; - if (GetSpeedX() != 0) + if (GetSpeedX() != NO_SPEED) { - if (GetSpeedX() > 0) + if (GetSpeedX() > NO_SPEED) { AddSpeedX(AccelDecelSpeed); } @@ -463,9 +463,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_XM: // ASCEND EAST { SetYaw(180); - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); - if (GetSpeedX() >= 0) + if (GetSpeedX() >= NO_SPEED) { if (GetSpeedX() <= MAX_SPEED) { @@ -483,9 +483,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_XP: // ASCEND WEST { SetYaw(180); - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); - if (GetSpeedX() > 0) + if (GetSpeedX() > NO_SPEED) { AddSpeedX(AccelDecelSpeed); SetSpeedY(GetSpeedX()); @@ -503,9 +503,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_ZM: // ASCEND NORTH { SetYaw(270); - SetSpeedX(0); + SetSpeedX(NO_SPEED); - if (GetSpeedZ() >= 0) + if (GetSpeedZ() >= NO_SPEED) { if (GetSpeedZ() <= MAX_SPEED) { @@ -523,9 +523,9 @@ void cMinecart::HandlePoweredRailPhysics(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_ZP: // ASCEND SOUTH { SetYaw(270); - SetSpeedX(0); + SetSpeedX(NO_SPEED); - if (GetSpeedZ() > 0) + if (GetSpeedZ() > NO_SPEED) { AddSpeedZ(AccelDecelSpeed); SetSpeedY(GetSpeedZ()); @@ -576,7 +576,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_XP: case E_META_RAIL_XM_XP: { - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); break; } @@ -584,7 +584,7 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) case E_META_RAIL_ASCEND_ZP: case E_META_RAIL_ZM_ZP: { - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); break; } @@ -593,12 +593,12 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) { if (GetPosZ() > floor(GetPosZ()) + 0.5) { - if (GetSpeedZ() > 0) + if (GetSpeedZ() > NO_SPEED) { SetSpeedX(-GetSpeedZ() * 0.7); } - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() > floor(GetPosX()) + 0.5) @@ -608,82 +608,82 @@ void cMinecart::SnapToRail(NIBBLETYPE a_RailMeta) SetSpeedZ(-GetSpeedX() * 0.7); } - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } - SetSpeedY(0); + SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZM_XP: { if (GetPosZ() > floor(GetPosZ()) + 0.5) { - if (GetSpeedZ() > 0) + if (GetSpeedZ() > NO_SPEED) { SetSpeedX(GetSpeedZ() * 0.7); } - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() < floor(GetPosX()) + 0.5) { - if (GetSpeedX() < 0) + if (GetSpeedX() < NO_SPEED) { SetSpeedZ(GetSpeedX() * 0.7); } - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } - SetSpeedY(0); + SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZP_XM: { if (GetPosZ() < floor(GetPosZ()) + 0.5) { - if (GetSpeedZ() < 0) + if (GetSpeedZ() < NO_SPEED) { SetSpeedX(GetSpeedZ() * 0.7); } - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() > floor(GetPosX()) + 0.5) { - if (GetSpeedX() > 0) + if (GetSpeedX() > NO_SPEED) { SetSpeedZ(GetSpeedX() * 0.7); } - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } - SetSpeedY(0); + SetSpeedY(NO_SPEED); break; } case E_META_RAIL_CURVED_ZP_XP: { if (GetPosZ() < floor(GetPosZ()) + 0.5) { - if (GetSpeedZ() < 0) + if (GetSpeedZ() < NO_SPEED) { SetSpeedX(-GetSpeedZ() * 0.7); } - SetSpeedZ(0); + SetSpeedZ(NO_SPEED); SetPosZ(floor(GetPosZ()) + 0.5); } else if (GetPosX() < floor(GetPosX()) + 0.5) { - if (GetSpeedX() < 0) + if (GetSpeedX() < NO_SPEED) { SetSpeedZ(-GetSpeedX() * 0.7); } - SetSpeedX(0); + SetSpeedX(NO_SPEED); SetPosX(floor(GetPosX()) + 0.5); } SetSpeedY(0); @@ -871,11 +871,101 @@ bool cMinecart::TestEntityCollision(NIBBLETYPE a_RailMeta) return true; } case E_META_RAIL_CURVED_ZM_XM: + case E_META_RAIL_CURVED_ZP_XP: + { + Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ()); + + // Prevent division by small numbers + if (std::abs(Distance.z) < 0.001) + { + Distance.z = 0.001; + } + + /* Check to which side the minecart is to be pushed. + Let's consider a z-x-coordinate system where the minecart is the center (0/0). + The minecart moves along the line x = -z, the perpendicular line to this is x = z. + In order to decide to which side the minecart is to be pushed, it must be checked on what side of the perpendicular line the pushing entity is located. */ + if ( + ((Distance.z > 0) && ((Distance.x / Distance.z) >= 1)) || + ((Distance.z < 0) && ((Distance.x / Distance.z) <= 1)) + ) + { + // Moving -X +Z + if ((-GetSpeedX() * 0.4 / sqrt(2.0)) < 0.01) + { + // ~ SpeedX >= 0 Immobile or not moving in the "right" direction. Give it a bump! + AddSpeedX(-4 / sqrt(2.0)); + AddSpeedZ(4 / sqrt(2.0)); + } + else + { + // ~ SpeedX < 0 Moving in the "right" direction. Only accelerate it a bit. + SetSpeedX(GetSpeedX() * 0.4 / sqrt(2.0)); + SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2.0)); + } + } + else if ((GetSpeedX() * 0.4 / sqrt(2.0)) < 0.01) + { + // Moving +X -Z + // ~ SpeedX <= 0 Immobile or not moving in the "right" direction + AddSpeedX(4 / sqrt(2.0)); + AddSpeedZ(-4 / sqrt(2.0)); + } + else + { + // ~ SpeedX > 0 Moving in the "right" direction + SetSpeedX(GetSpeedX() * 0.4 / sqrt(2.0)); + SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2.0)); + } + break; + } case E_META_RAIL_CURVED_ZM_XP: case E_META_RAIL_CURVED_ZP_XM: - case E_META_RAIL_CURVED_ZP_XP: { - // TODO - simply can't be bothered right now + Vector3d Distance = MinecartCollisionCallback.GetCollidedEntityPosition() - Vector3d(GetPosX(), 0, GetPosZ()); + + // Prevent division by small numbers + if (std::abs(Distance.z) < 0.001) + { + Distance.z = 0.001; + } + + /* Check to which side the minecart is to be pushed. + Let's consider a z-x-coordinate system where the minecart is the center (0/0). + The minecart moves along the line x = z, the perpendicular line to this is x = -z. + In order to decide to which side the minecart is to be pushed, it must be checked on what side of the perpendicular line the pushing entity is located. */ + if ( + ((Distance.z > 0) && ((Distance.x / Distance.z) <= -1)) || + ((Distance.z < 0) && ((Distance.x / Distance.z) >= -1)) + ) + { + // Moving +X +Z + if ((GetSpeedX() * 0.4) < 0.01) + { + // ~ SpeedX <= 0 Immobile or not moving in the "right" direction + AddSpeedX(4 / sqrt(2.0)); + AddSpeedZ(4 / sqrt(2.0)); + } + else + { + // ~ SpeedX > 0 Moving in the "right" direction + SetSpeedX(GetSpeedX() * 0.4 / sqrt(2.0)); + SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2.0)); + } + } + else if ((-GetSpeedX() * 0.4) < 0.01) + { + // Moving -X -Z + // ~ SpeedX >= 0 Immobile or not moving in the "right" direction + AddSpeedX(-4 / sqrt(2.0)); + AddSpeedZ(-4 / sqrt(2.0)); + } + else + { + // ~ SpeedX < 0 Moving in the "right" direction + SetSpeedX(GetSpeedX() * 0.4 / sqrt(2.0)); + SetSpeedZ(GetSpeedZ() * 0.4 / sqrt(2.0)); + } break; } default: break; @@ -982,6 +1072,8 @@ cRideableMinecart::cRideableMinecart(double a_X, double a_Y, double a_Z, const c void cRideableMinecart::OnRightClicked(cPlayer & a_Player) { + super::OnRightClicked(a_Player); + if (m_Attachee != NULL) { if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID()) @@ -1013,29 +1105,55 @@ void cRideableMinecart::OnRightClicked(cPlayer & a_Player) // cMinecartWithChest: cMinecartWithChest::cMinecartWithChest(double a_X, double a_Y, double a_Z) : - super(mpChest, a_X, a_Y, a_Z) + super(mpChest, a_X, a_Y, a_Z), + cEntityWindowOwner(this), + m_Contents(ContentsWidth, ContentsHeight) { + m_Contents.AddListener(*this); } -void cMinecartWithChest::SetSlot(size_t a_Idx, const cItem & a_Item) +void cMinecartWithChest::OnRightClicked(cPlayer & a_Player) { - ASSERT(a_Idx < ARRAYCOUNT(m_Items)); - - m_Items[a_Idx] = a_Item; + // If the window is not created, open it anew: + cWindow * Window = GetWindow(); + if (Window == NULL) + { + OpenNewWindow(); + Window = GetWindow(); + } + + // Open the window for the player: + if (Window != NULL) + { + if (a_Player.GetWindow() != Window) + { + a_Player.OpenWindow(Window); + } + } } -void cMinecartWithChest::OnRightClicked(cPlayer & a_Player) +void cMinecartWithChest::OpenNewWindow() +{ + OpenWindow(new cMinecartWithChestWindow(this)); +} + + + + + +void cMinecartWithChest::Destroyed() { - // Show the chest UI window to the player - // TODO + cItems Pickups; + m_Contents.CopyToItems(Pickups); + GetWorld()->SpawnItemPickups(Pickups, GetPosX(), GetPosY() + 1, GetPosZ(), 4); } |