aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNoName <322016+Faq@users.noreply.github.com>2020-02-28 20:03:52 +0200
committerGitHub <noreply@github.com>2020-02-28 19:03:52 +0100
commit40542f01e3fec0bff2c6e5eadbe20e58f19b0fd8 (patch)
tree49ed6cfbb454ec61babaec8e4862aec0b36578b5 /src
parent1a761aa8e7091b90a7449ac03d336693be675edd (diff)
Core/Movement: Implement MoveSplineFlag::Enter_Cycle (#24049)
by xvwyh #22448
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp22
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Movement/MotionMaster.cpp3
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.cpp45
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.cpp1
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.cpp13
-rw-r--r--src/server/game/Movement/Spline/MovementPacketBuilder.h1
7 files changed, 70 insertions, 17 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 193e4228cfc..7e3fd717190 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -42,6 +42,7 @@
#include "LootMgr.h"
#include "MotionMaster.h"
#include "MovementGenerator.h"
+#include "MovementPacketBuilder.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
#include "ObjectAccessor.h"
@@ -493,19 +494,28 @@ void Unit::UpdateSplineMovement(uint32 t_diff)
movespline->updateState(t_diff);
bool arrived = movespline->Finalized();
+ if (movespline->isCyclic())
+ {
+ m_splineSyncTimer.Update(t_diff);
+ if (m_splineSyncTimer.Passed())
+ {
+ m_splineSyncTimer.Reset(5000); // Retail value, do not change
+
+ WorldPacket data(SMSG_FLIGHT_SPLINE_SYNC, 4 + GetPackGUID().size());
+ Movement::PacketBuilder::WriteSplineSync(*movespline, data);
+ data.appendPackGUID(GetGUID());
+ SendMessageToSet(&data, true);
+ }
+ }
+
if (arrived)
DisableSpline();
- m_movesplineTimer.Update(t_diff);
- if (m_movesplineTimer.Passed() || arrived)
- UpdateSplinePosition();
+ UpdateSplinePosition();
}
void Unit::UpdateSplinePosition()
{
- static uint32 const positionUpdateDelay = 400;
-
- m_movesplineTimer.Reset(positionUpdateDelay);
Movement::Location loc = movespline->ComputePosition();
if (movespline->onTransport)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index fac7433ee89..73e5897322a 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1792,7 +1792,7 @@ class TC_GAME_API Unit : public WorldObject
uint32 m_state; // Even derived shouldn't modify
uint32 m_lastManaUse; // msecs
- TimeTrackerSmall m_movesplineTimer;
+ TimeTrackerSmall m_splineSyncTimer;
DiminishingReturn m_Diminishing[DIMINISHING_MAX];
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index fb7109499da..d266b855ed0 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -807,6 +807,9 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool
Movement::MoveSplineInit init(_owner);
+ // add the owner's current position as starting point as it gets removed after entering the cycle
+ init.Path().push_back(G3D::Vector3(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()));
+
for (uint8 i = 0; i < stepCount; angle += step, ++i)
{
G3D::Vector3 point;
diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp
index 3a03e24f0ec..991979ac83e 100644
--- a/src/server/game/Movement/Spline/MoveSpline.cpp
+++ b/src/server/game/Movement/Spline/MoveSpline.cpp
@@ -122,9 +122,8 @@ void MoveSpline::init_spline(MoveSplineInitArgs const& args)
if (args.flags.cyclic)
{
uint32 cyclic_point = 0;
- // MoveSplineFlag::Enter_Cycle support dropped
- //if (splineflags & SPLINEFLAG_ENTER_CYCLE)
- //cyclic_point = 1; // shouldn't be modified, came from client
+ if (splineflags.enter_cycle)
+ cyclic_point = 1; // shouldn't be modified, came from client
spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point, args.initialOrientation);
}
else
@@ -199,7 +198,10 @@ bool MoveSplineInitArgs::Validate(Unit* unit) const
#define CHECK(exp) \
if (!(exp))\
{\
- TC_LOG_ERROR("misc.movesplineinitargs", "MoveSplineInitArgs::Validate: expression '%s' failed for GUID: %u Entry: %u", #exp, unit->GetTypeId() == TYPEID_PLAYER ? unit->GetGUID().GetCounter() : unit->ToCreature()->GetSpawnId(), unit->GetEntry());\
+ if (unit)\
+ TC_LOG_ERROR("misc.movesplineinitargs", "MoveSplineInitArgs::Validate: expression '%s' failed for GUID: %u Entry: %u", #exp, unit->GetTypeId() == TYPEID_PLAYER ? unit->GetGUID().GetCounter() : unit->ToCreature()->GetSpawnId(), unit->GetEntry());\
+ else\
+ TC_LOG_ERROR("misc.movesplineinitargs", "MoveSplineInitArgs::Validate: expression '%s' failed for cyclic spline continuation", #exp); \
return false;\
}
CHECK(path.size() > 1);
@@ -276,6 +278,41 @@ MoveSpline::UpdateResult MoveSpline::_updateState(int32& ms_time_diff)
point_Idx = spline.first();
time_passed = time_passed % Duration();
result = Result_NextCycle;
+
+ // Remove first point from the path after one full cycle.
+ // That point was the position of the unit prior to entering the cycle and it shouldn't be repeated with continuous cycles.
+ if (splineflags.enter_cycle)
+ {
+ splineflags.enter_cycle = false;
+
+ MoveSplineInitArgs args{ (size_t)spline.getPointCount() };
+ args.path.assign(spline.getPoints().begin() + spline.first() + 1, spline.getPoints().begin() + spline.last());
+ args.facing = facing;
+ args.flags = splineflags;
+ args.path_Idx_offset = point_Idx_offset;
+ // MoveSplineFlag::Parabolic | MoveSplineFlag::Animation not supported currently
+ //args.parabolic_amplitude = ?;
+ //args.time_perc = ?;
+ args.splineId = m_Id;
+ args.initialOrientation = initialOrientation;
+ args.velocity = 1.0f; // Calculated below
+ args.HasVelocity = true;
+ args.TransformForTransport = onTransport;
+ if (args.Validate(nullptr))
+ {
+ // New cycle should preserve previous cycle's duration for some weird reason, even though
+ // the path is really different now. Blizzard is weird. Or this was just a simple oversight.
+ // Since our splines precalculate length with velocity in mind, if we want to find the desired
+ // velocity, we have to make a fake spline, calculate its duration and then compare it to the
+ // desired duration, thus finding out how much the velocity has to be increased for them to match.
+ MoveSpline tempSpline;
+ tempSpline.Initialize(args);
+ args.velocity = (float)tempSpline.Duration() / Duration();
+
+ if (args.Validate(nullptr))
+ init_spline(args);
+ }
+ }
}
else
{
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp
index 749ffc98300..bb885671479 100644
--- a/src/server/game/Movement/Spline/MoveSplineInit.cpp
+++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp
@@ -89,6 +89,7 @@ namespace Movement
// corrent first vertex
args.path[0] = real_position;
args.initialOrientation = real_position.orientation;
+ args.flags.enter_cycle = args.flags.cyclic;
move_spline.onTransport = transport;
uint32 moveFlags = unit->m_movementInfo.GetMovementFlags();
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
index e61887b931e..d5aad6c2625 100644
--- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp
@@ -68,8 +68,6 @@ namespace Movement
break;
}
- // add fake Enter_Cycle flag - needed for client-side cyclic movement (client will erase first spline vertex after first cycle done)
- splineflags.enter_cycle = move_spline.isCyclic();
data << uint32(splineflags & uint32(~MoveSplineFlag::Mask_No_Monster_Move));
if (splineflags.animation)
@@ -124,10 +122,9 @@ namespace Movement
void WriteCatmullRomCyclicPath(Spline<int32> const& spline, ByteBuffer& data)
{
- uint32 count = spline.getPointCount() - 3;
- data << uint32(count + 1);
- data << spline.getPoint(1); // fake point, client will erase it from the spline after first cycle done
- data.append<G3D::Vector3>(&spline.getPoint(1), count);
+ uint32 count = spline.getPointCount() - 4;
+ data << count;
+ data.append<Vector3>(&spline.getPoint(2), count);
}
void PacketBuilder::WriteMonsterMove(MoveSpline const& move_spline, ByteBuffer& data)
@@ -187,4 +184,8 @@ namespace Movement
data << (move_spline.isCyclic() ? G3D::Vector3::zero() : move_spline.FinalDestination());
}
}
+ void PacketBuilder::WriteSplineSync(MoveSpline const& move_spline, ByteBuffer& data)
+ {
+ data << (float)move_spline.timePassed() / move_spline.Duration();
+ }
}
diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.h b/src/server/game/Movement/Spline/MovementPacketBuilder.h
index dd608bd48b5..80adbdfb185 100644
--- a/src/server/game/Movement/Spline/MovementPacketBuilder.h
+++ b/src/server/game/Movement/Spline/MovementPacketBuilder.h
@@ -37,6 +37,7 @@ namespace Movement
static void WriteMonsterMove(MoveSpline const& mov, ByteBuffer& data);
static void WriteStopMovement(G3D::Vector3 const& loc, uint32 splineId, ByteBuffer& data);
static void WriteCreate(MoveSpline const& mov, ByteBuffer& data);
+ static void WriteSplineSync(MoveSpline const& mov, ByteBuffer& data);
};
}
#endif // TRINITYSERVER_PACKET_BUILDER_H