diff options
Diffstat (limited to 'src/server/game/Movement')
| -rw-r--r-- | src/server/game/Movement/MotionMaster.cpp | 59 | ||||
| -rw-r--r-- | src/server/game/Movement/MotionMaster.h | 6 | ||||
| -rw-r--r-- | src/server/game/Movement/Spline/MoveSpline.cpp | 28 |
3 files changed, 46 insertions, 47 deletions
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index 85bb2e365f3..202663cf1cc 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -29,6 +29,7 @@ #include "PathGenerator.h" #include "Player.h" #include "ScriptSystem.h" +#include <boost/container/static_vector.hpp> #include <algorithm> #include <iterator> @@ -800,17 +801,17 @@ void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_C init.Launch(); } -void MotionMaster::MoveKnockbackFrom(Position const& origin, float speedXY, float speedZ, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/) +void MotionMaster::MoveKnockbackFrom(Position const& origin, float speedXY, float speedZ, float angle /*= M_PI*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/) { // This function may make players fall below map if (_owner->GetTypeId() == TYPEID_PLAYER) return; - if (std::abs(speedXY) < 0.01f /* && std::abs(speedZ) < 0.01f */) + if (std::abs(speedXY) < 0.01f && std::abs(speedZ) < 0.01f) return; Position dest = _owner->GetPosition(); - float o = dest == origin ? 0.0f : _owner->GetRelativeAngle(origin) + float(M_PI); + float o = (dest == origin ? 0.0f : _owner->GetRelativeAngle(origin)) + angle; if (speedXY < 0) { speedXY = -speedXY; @@ -824,16 +825,29 @@ void MotionMaster::MoveKnockbackFrom(Position const& origin, float speedXY, floa float dist = 2 * moveTimeHalf * speedXY; float max_height = -Movement::computeFallElevation(moveTimeHalf, false, -speedZ); - // Use a mmap raycast to get a valid destination. - _owner->MovePositionToFirstCollision(dest, dist, o); + boost::container::static_vector<G3D::Vector3, 3> path; + path.push_back(PositionToVector3(dest)); + + if (dist > 0.01f) + { + // Use a mmap raycast to get a valid destination. + _owner->MovePositionToFirstCollision(dest, dist, o); + path.push_back(PositionToVector3(dest)); + } + else + { + // vertical knockbacks get a fake 0.5 higher additional point to avoid clientside spline length checks + // sniffs confirmed that it is always 0.5, no matter what the max height is + path.push_back(PositionToVector3(dest.GetPositionWithOffset({ 0.0f, 0.0f, 0.5f }))); + path.push_back(PositionToVector3(dest)); + } std::function<void(Movement::MoveSplineInit&)> initializer = [=, effect = (spellEffectExtraData ? Optional<Movement::SpellEffectExtraData>(*spellEffectExtraData) : Optional<Movement::SpellEffectExtraData>())](Movement::MoveSplineInit& init) { - init.MoveTo(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ(), false); + init.MovebyPath({ path.data(), path.size() }); init.SetParabolic(max_height, 0); init.SetOrientationFixed(true); - if (speedXY >= 0.01f) - init.SetVelocity(speedXY); + init.SetVelocity(speedXY); if (effect) init.SetSpellEffectExtraData(*effect); }; @@ -844,36 +858,11 @@ void MotionMaster::MoveKnockbackFrom(Position const& origin, float speedXY, floa Add(movement); } -void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ) -{ - // This function may make players fall below map - if (_owner->GetTypeId() == TYPEID_PLAYER) - return; - - float x, y, z = _owner->GetPositionZ(); - - float moveTimeHalf = speedZ / Movement::gravity; - float dist = 2 * moveTimeHalf * speedXY; - - _owner->GetNearPoint2D(nullptr, x, y, dist, _owner->GetOrientation() + angle); - _owner->UpdateAllowedPositionZ(x, y, z); - - MoveJump(x, y, z, speedXY, speedZ); -} - void MotionMaster::MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id /*= EVENT_JUMP*/, MovementFacingTarget const& facing /*= {}*/, bool orientationFixed /*= false*/, JumpArrivalCastArgs const* arrivalCast /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) { - MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ, id, facing, orientationFixed, arrivalCast, - spellEffectExtraData, std::move(scriptResult)); -} - -void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id /*= EVENT_JUMP*/, MovementFacingTarget const& facing /* = {}*/, - bool orientationFixed /*= false*/, JumpArrivalCastArgs const* arrivalCast /*= nullptr*/, Movement::SpellEffectExtraData const* spellEffectExtraData /*= nullptr*/, - Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult /*= {}*/) -{ - TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveJump: '{}', jumps to point Id: {} (X: {}, Y: {}, Z: {})", _owner->GetGUID(), id, x, y, z); + TC_LOG_DEBUG("movement.motionmaster", "MotionMaster::MoveJump: '{}', jumps to point Id: {} ({})", _owner->GetGUID(), id, pos.ToString()); if (speedXY < 0.01f) { if (scriptResult) @@ -886,7 +875,7 @@ void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float spee std::function<void(Movement::MoveSplineInit&)> initializer = [=, effect = (spellEffectExtraData ? Optional<Movement::SpellEffectExtraData>(*spellEffectExtraData) : Optional<Movement::SpellEffectExtraData>())](Movement::MoveSplineInit& init) { - init.MoveTo(x, y, z, false); + init.MoveTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), false); init.SetParabolic(max_height, 0); init.SetVelocity(speedXY); std::visit(Movement::MoveSplineInitFacingVisitor(init), facing); diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 22f6bfaf475..43ad95fd4da 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -190,14 +190,10 @@ class TC_GAME_API MotionMaster Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, bool generatePath = false, Unit const* target = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); void MoveCharge(PathGenerator const& path, float speed = SPEED_CHARGE, Unit const* target = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); - void MoveKnockbackFrom(Position const& origin, float speedXY, float speedZ, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); - void MoveJumpTo(float angle, float speedXY, float speedZ); + void MoveKnockbackFrom(Position const& origin, float speedXY, float speedZ, float angle = M_PI, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr); void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = EVENT_JUMP, MovementFacingTarget const& facing = {}, bool orientationFixed = false, JumpArrivalCastArgs const* arrivalCast = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); - void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP, MovementFacingTarget const& facing = {}, - bool orientationFixed = false, JumpArrivalCastArgs const* arrivalCast = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr, - Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); void MoveJumpWithGravity(Position const& pos, float speedXY, float gravity, uint32 id = EVENT_JUMP, MovementFacingTarget const& facing = {}, bool orientationFixed = false, JumpArrivalCastArgs const* arrivalCast = nullptr, Movement::SpellEffectExtraData const* spellEffectExtraData = nullptr, Optional<Scripting::v2::ActionResultSetter<MovementStopReason>>&& scriptResult = {}); diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp index a317b018ed6..7d76570b81d 100644 --- a/src/server/game/Movement/Spline/MoveSpline.cpp +++ b/src/server/game/Movement/Spline/MoveSpline.cpp @@ -120,9 +120,8 @@ void MoveSpline::computeFallElevation(int32 time_point, float& el) const struct FallInitializer { - FallInitializer(float _start_elevation) : start_elevation(_start_elevation) { } float start_elevation; - inline int32 operator()(Spline<int32>& s, int32 i) + inline int32 operator()(Spline<int32> const& s, int32 i) const { return Movement::computeFallTime(start_elevation - s.getPoint(i+1).z, false) * 1000.f; } @@ -132,11 +131,21 @@ enum{ minimal_duration = 1 }; +struct ParabolicInPlaceInitializer +{ + float parabolic_amplitude; + inline int32 operator()(Spline<int32> const& /*s*/, int32 /*i*/) + { + return time += Movement::computeFallTime(parabolic_amplitude, false) * 1000.f; + } + + int32 time = minimal_duration; +}; + struct CommonInitializer { - CommonInitializer(float _velocity) : velocityInv(1000.f/_velocity), time(minimal_duration) { } float velocityInv; - int32 time; + int32 time = minimal_duration; inline int32 operator()(Spline<int32>& s, int32 i) { time += (s.SegLength(i) * velocityInv); @@ -160,12 +169,17 @@ void MoveSpline::init_spline(MoveSplineInitArgs const& args) // init spline timestamps if (splineflags.Falling) { - FallInitializer init(spline.getPoint(spline.first()).z); + FallInitializer init{ .start_elevation = spline.getPoint(spline.first()).z }; + spline.initLengths(init); + } + else if (splineflags.Parabolic && args.velocity < 0.01f) + { + ParabolicInPlaceInitializer init{ .parabolic_amplitude = args.parabolic_amplitude }; spline.initLengths(init); } else { - CommonInitializer init(args.velocity); + CommonInitializer init{ .velocityInv = 1000.0f / args.velocity }; spline.initLengths(init); } @@ -254,7 +268,7 @@ bool MoveSplineInitArgs::Validate(Unit const* unit) }() CHECK(path.size() > 1, unit->GetDebugInfo()); - CHECK(velocity >= 0.01f, unit->GetDebugInfo()); + CHECK(velocity >= 0.01f || (flags.Parabolic && parabolic_amplitude != 0.0f), unit->GetDebugInfo()); CHECK(effect_start_point < std::ssize(path), unit->GetDebugInfo()); CHECK(_checkPathLengths(), unit->GetGUID().ToString()); if (spellEffectExtra) |
