mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Movement: Implemented vertical-only knockbacks for creatures
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
#include "PathGenerator.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptSystem.h"
|
||||
#include <boost/container/static_vector.hpp>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
@@ -806,7 +807,7 @@ void MotionMaster::MoveKnockbackFrom(Position const& origin, float speedXY, floa
|
||||
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();
|
||||
@@ -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);
|
||||
init.SetParabolic(max_height, 0);
|
||||
init.SetOrientationFixed(true);
|
||||
if (speedXY >= 0.01f)
|
||||
init.SetVelocity(speedXY);
|
||||
init.SetVelocity(speedXY);
|
||||
if (effect)
|
||||
init.SetSpellEffectExtraData(*effect);
|
||||
};
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user