mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-13 01:08:35 +00:00
fix(Core/Spell): Improvements to path generation for Charge mechanic (#11534)
It has its flaws but it can be improved and it's actually a lot better than what we currently have.
This commit is contained in:
committed by
GitHub
parent
ad8f8ee5a5
commit
59e45c251e
@@ -608,6 +608,19 @@ void MotionMaster::MoveCharge(float x, float y, float z, float speed, uint32 id,
|
||||
}
|
||||
}
|
||||
|
||||
void MotionMaster::MoveCharge(PathGenerator const& path, float speed /*= SPEED_CHARGE*/)
|
||||
{
|
||||
G3D::Vector3 dest = path.GetActualEndPosition();
|
||||
|
||||
MoveCharge(dest.x, dest.y, dest.z, speed, EVENT_CHARGE_PREPATH);
|
||||
|
||||
// Charge movement is not started when using EVENT_CHARGE_PREPATH
|
||||
Movement::MoveSplineInit init(_owner);
|
||||
init.MovebyPath(path.GetPath());
|
||||
init.SetVelocity(speed);
|
||||
init.Launch();
|
||||
}
|
||||
|
||||
void MotionMaster::MoveSeekAssistance(float x, float y, float z)
|
||||
{
|
||||
// Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE
|
||||
|
||||
@@ -219,6 +219,7 @@ public:
|
||||
void MoveTakeoff(uint32 id, float x, float y, float z, float speed = 0.0f); // pussywizard: added for easy calling by passing 3 floats x, y, z
|
||||
|
||||
void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, const Movement::PointsArray* path = nullptr, bool generatePath = false, float orientation = 0.0f, ObjectGuid targetGUID = ObjectGuid::Empty);
|
||||
void MoveCharge(PathGenerator const& path, float speed = SPEED_CHARGE);
|
||||
void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ);
|
||||
void MoveJumpTo(float angle, float speedXY, float speedZ);
|
||||
void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = 0)
|
||||
|
||||
@@ -117,7 +117,7 @@ bool PointMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
||||
|
||||
unit->AddUnitState(UNIT_STATE_ROAMING_MOVE);
|
||||
|
||||
if (i_recalculateSpeed && !unit->movespline->Finalized())
|
||||
if (id != EVENT_CHARGE_PREPATH && i_recalculateSpeed && !unit->movespline->Finalized())
|
||||
{
|
||||
i_recalculateSpeed = false;
|
||||
Movement::MoveSplineInit init(unit);
|
||||
|
||||
@@ -646,7 +646,6 @@ Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags,
|
||||
m_glyphIndex = 0;
|
||||
m_preCastSpell = 0;
|
||||
m_spellAura = nullptr;
|
||||
m_pathFinder = nullptr; // pussywizard
|
||||
_scriptsLoaded = false;
|
||||
|
||||
//Auto Shot & Shoot (wand)
|
||||
@@ -701,7 +700,6 @@ Spell::~Spell()
|
||||
}
|
||||
|
||||
delete m_spellValue;
|
||||
delete m_pathFinder; // pussywizard
|
||||
|
||||
CheckEffectExecuteData();
|
||||
}
|
||||
@@ -6001,40 +5999,28 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
{
|
||||
Unit* target = m_targets.GetUnitTarget();
|
||||
if (!target)
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
|
||||
Position pos;
|
||||
target->GetChargeContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ);
|
||||
// first we must check to see if the target is in LoS. A path can usually be built but LoS matters for charge spells
|
||||
if (!target->IsWithinLOSInMap(m_caster)) //Do full LoS/Path check. Don't exclude m2
|
||||
return SPELL_FAILED_LINE_OF_SIGHT;
|
||||
|
||||
if (m_caster->GetMapId() == 618) // pussywizard: 618 Ring of Valor
|
||||
pos.m_positionZ = std::max(pos.m_positionZ, 28.28f);
|
||||
float objSize = target->GetCombatReach();
|
||||
float range = m_spellInfo->GetMaxRange(true, m_caster, this) * 1.5f + objSize; // can't be overly strict
|
||||
|
||||
float maxdist = m_caster->GetMeleeRange(target);
|
||||
if (!target->IsInDist(&pos, maxdist))
|
||||
m_preGeneratedPath = std::make_unique<PathGenerator>(m_caster);
|
||||
m_preGeneratedPath->SetPathLengthLimit(range);
|
||||
|
||||
// first try with raycast, if it fails fall back to normal path
|
||||
bool result = m_preGeneratedPath->CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), false);
|
||||
if (m_preGeneratedPath->GetPathType() & PATHFIND_SHORT)
|
||||
return SPELL_FAILED_NOPATH;
|
||||
else if (!result || m_preGeneratedPath->GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE))
|
||||
return SPELL_FAILED_NOPATH;
|
||||
else if (m_preGeneratedPath->IsInvalidDestinationZ(target)) // Check position z, if not in a straight line
|
||||
return SPELL_FAILED_NOPATH;
|
||||
|
||||
if (m_caster->GetMapId() == 618) // pussywizard: 618 Ring of Valor
|
||||
{
|
||||
if (!((target->GetPositionZ() > 32.0f) ^ (m_caster->GetPositionZ() > 32.0f)))
|
||||
break;
|
||||
return SPELL_FAILED_NOPATH;
|
||||
}
|
||||
else if (m_caster->GetMapId() == 572) // pussywizard: 572 Ruins of Lordaeron
|
||||
{
|
||||
if (pos.GetPositionX() < 1275.0f || m_caster->GetPositionX() < 1275.0f) // special case (acid)
|
||||
break; // can't force path because the way is around and the path is too long
|
||||
}
|
||||
|
||||
if (m_caster->GetTransport() != target->GetTransport())
|
||||
return SPELL_FAILED_NOPATH;
|
||||
if (m_caster->GetTransport())
|
||||
break;
|
||||
|
||||
m_pathFinder = new PathGenerator(m_caster);
|
||||
m_pathFinder->CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.15f, false);
|
||||
G3D::Vector3 endPos = m_pathFinder->GetEndPosition(); // also check distance between target and the point calculated by mmaps
|
||||
if (m_pathFinder->GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE) || target->GetExactDistSq(endPos.x, endPos.y, endPos.z) > maxdist * maxdist || m_pathFinder->getPathLength() > (40.0f + (m_caster->HasAura(58097) ? 5.0f : 0.0f)))
|
||||
return SPELL_FAILED_NOPATH;
|
||||
m_preGeneratedPath->ShortenPathUntilDist(G3D::Vector3(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()), objSize); // move back
|
||||
}
|
||||
if (Player* player = m_caster->ToPlayer())
|
||||
player->SetCanTeleport(true);
|
||||
|
||||
@@ -544,8 +544,6 @@ public:
|
||||
|
||||
UsedSpellMods m_appliedMods;
|
||||
|
||||
PathGenerator* m_pathFinder; // pussywizard: for precomputing path for charge
|
||||
|
||||
int32 GetCastTime() const { return m_casttime; }
|
||||
bool IsAutoRepeat() const { return m_autoRepeat; }
|
||||
void SetAutoRepeat(bool rep) { m_autoRepeat = rep; }
|
||||
@@ -770,6 +768,7 @@ public:
|
||||
|
||||
bool m_skipCheck;
|
||||
uint8 m_auraScaleMask;
|
||||
std::unique_ptr<PathGenerator> m_preGeneratedPath;
|
||||
|
||||
// xinef:
|
||||
bool _spellTargetsSelected;
|
||||
|
||||
@@ -4870,10 +4870,12 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
|
||||
targetGUID = unitTarget->GetGUID();
|
||||
}
|
||||
|
||||
if (m_pathFinder)
|
||||
float speed = G3D::fuzzyGt(m_spellInfo->Speed, 0.0f) ? m_spellInfo->Speed : SPEED_CHARGE;
|
||||
// Spell is not using explicit target - no generated path
|
||||
if (!m_preGeneratedPath)
|
||||
{
|
||||
m_caster->GetMotionMaster()->MoveCharge(m_pathFinder->GetEndPosition().x, m_pathFinder->GetEndPosition().y, m_pathFinder->GetEndPosition().z,
|
||||
42.0f, EVENT_CHARGE, &m_pathFinder->GetPath(), false, 0.f, targetGUID);
|
||||
Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetCombatReach(), unitTarget->GetRelativeAngle(m_caster));
|
||||
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speed);
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
@@ -4882,10 +4884,7 @@ void Spell::EffectCharge(SpellEffIndex /*effIndex*/)
|
||||
}
|
||||
else
|
||||
{
|
||||
Position pos = unitTarget->GetFirstCollisionPosition(unitTarget->GetObjectSize(), unitTarget->GetRelativeAngle(m_caster));
|
||||
|
||||
m_caster->GetMotionMaster()->MoveCharge(pos.m_positionX, pos.m_positionY, pos.m_positionZ + Z_OFFSET_FIND_HEIGHT, SPEED_CHARGE, EVENT_CHARGE,
|
||||
nullptr, false, 0.f, targetGUID);
|
||||
m_caster->GetMotionMaster()->MoveCharge(*m_preGeneratedPath, speed);
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
|
||||
@@ -3282,6 +3282,11 @@ enum SummonType
|
||||
enum EventId
|
||||
{
|
||||
EVENT_CHARGE = 1003,
|
||||
|
||||
/// Special charge event which is used for charge spells that have explicit targets
|
||||
/// and had a path already generated - using it in PointMovementGenerator will not
|
||||
/// create a new spline and launch it
|
||||
EVENT_CHARGE_PREPATH = 1005,
|
||||
};
|
||||
|
||||
enum ResponseCodes
|
||||
|
||||
Reference in New Issue
Block a user