diff options
author | NoName <322016+Faq@users.noreply.github.com> | 2020-02-28 20:03:52 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-28 19:03:52 +0100 |
commit | 40542f01e3fec0bff2c6e5eadbe20e58f19b0fd8 (patch) | |
tree | 49ed6cfbb454ec61babaec8e4862aec0b36578b5 | |
parent | 1a761aa8e7091b90a7449ac03d336693be675edd (diff) |
Core/Movement: Implement MoveSplineFlag::Enter_Cycle (#24049)
by xvwyh
#22448
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 2 | ||||
-rw-r--r-- | src/server/game/Movement/MotionMaster.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Movement/Spline/MoveSpline.cpp | 45 | ||||
-rw-r--r-- | src/server/game/Movement/Spline/MoveSplineInit.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Movement/Spline/MovementPacketBuilder.cpp | 13 | ||||
-rw-r--r-- | src/server/game/Movement/Spline/MovementPacketBuilder.h | 1 |
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 |