mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-21 20:56:23 +00:00
fix(Core/Pathfinding): Improve - Point movement (#3658)
This commit is contained in:
@@ -249,6 +249,7 @@ bool CreatureAI::_EnterEvadeMode()
|
||||
me->SetLootRecipient(nullptr);
|
||||
me->ResetPlayerDamageReq();
|
||||
me->SetLastDamagedTime(0);
|
||||
me->SetCannotReachTarget(false);
|
||||
|
||||
if (me->IsInEvadeMode())
|
||||
return false;
|
||||
|
||||
@@ -626,12 +626,7 @@ void SmartAI::EnterEvadeMode()
|
||||
me->RemoveEvadeAuras();
|
||||
|
||||
me->AddUnitState(UNIT_STATE_EVADE);
|
||||
me->DeleteThreatList();
|
||||
me->CombatStop(true);
|
||||
me->LoadCreaturesAddon(true);
|
||||
me->SetLootRecipient(nullptr);
|
||||
me->ResetPlayerDamageReq();
|
||||
me->SetLastDamagedTime(0);
|
||||
_EnterEvadeMode();
|
||||
|
||||
GetScript()->ProcessEventsFor(SMART_EVENT_EVADE);//must be after aura clear so we can cast spells from db
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
#include "LuaEngine.h"
|
||||
#endif
|
||||
|
||||
constexpr uint32 DEF_CANNOT_REACH = 5 * IN_MILLISECONDS; // this is when creatures are in los / no path to the target, 5s wait time then they return to spawn pos with evade
|
||||
|
||||
TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
|
||||
{
|
||||
TrainerSpellMap::const_iterator itr = spellList.find(spell_id);
|
||||
@@ -164,7 +166,7 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MovableMapObject(),
|
||||
m_transportCheckTimer(1000), lootPickPocketRestoreTime(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE),
|
||||
m_DBTableGuid(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false),
|
||||
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_moveInLineOfSightDisabled(false), m_moveInLineOfSightStrictlyDisabled(false),
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(0)
|
||||
m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), _lastDamagedTime(0), m_cannotReachTarget(false), m_cannotReachTimer(0)
|
||||
{
|
||||
m_regenTimer = CREATURE_REGEN_INTERVAL;
|
||||
m_valuesCount = UNIT_END;
|
||||
@@ -610,6 +612,16 @@ void Creature::Update(uint32 diff)
|
||||
|
||||
m_regenTimer += CREATURE_REGEN_INTERVAL;
|
||||
}
|
||||
|
||||
if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid())
|
||||
{
|
||||
m_cannotReachTimer += diff;
|
||||
if (m_cannotReachTimer >= DEF_CANNOT_REACH && IsAIEnabled)
|
||||
{
|
||||
AI()->EnterEvadeMode();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -499,6 +499,7 @@ public:
|
||||
uint8 getLevelForTarget(WorldObject const* target) const override; // overwrite Unit::getLevelForTarget for boss level support
|
||||
|
||||
bool IsInEvadeMode() const { return HasUnitState(UNIT_STATE_EVADE); }
|
||||
bool IsEvadingAttacks() const { return IsInEvadeMode() || CanNotReachTarget(); }
|
||||
|
||||
bool AIM_Initialize(CreatureAI* ai = nullptr);
|
||||
void Motion_Initialize();
|
||||
@@ -664,6 +665,9 @@ public:
|
||||
return m_charmInfo->GetCharmSpell(pos)->GetAction();
|
||||
}
|
||||
|
||||
void SetCannotReachTarget(bool cannotReach) { if (cannotReach == m_cannotReachTarget) return; m_cannotReachTarget = cannotReach; m_cannotReachTimer = 0; }
|
||||
bool CanNotReachTarget() const { return m_cannotReachTarget; }
|
||||
|
||||
void SetPosition(float x, float y, float z, float o);
|
||||
void SetPosition(const Position& pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); }
|
||||
|
||||
@@ -784,6 +788,9 @@ private:
|
||||
|
||||
time_t _lastDamagedTime; // Part of Evade mechanics
|
||||
|
||||
bool m_cannotReachTarget;
|
||||
uint32 m_cannotReachTimer;
|
||||
|
||||
Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing
|
||||
};
|
||||
|
||||
|
||||
@@ -665,7 +665,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
|
||||
|
||||
void Unit::DealDamageMods(Unit const* victim, uint32& damage, uint32* absorb)
|
||||
{
|
||||
if (!victim || !victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()))
|
||||
if (!victim || !victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
|
||||
{
|
||||
if (absorb)
|
||||
*absorb += damage;
|
||||
@@ -1237,7 +1237,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss)
|
||||
if (!victim)
|
||||
return;
|
||||
|
||||
if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()))
|
||||
if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
|
||||
return;
|
||||
|
||||
SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(damageInfo->SpellID);
|
||||
@@ -1468,7 +1468,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
||||
{
|
||||
Unit* victim = damageInfo->target;
|
||||
|
||||
if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()))
|
||||
if (!victim->IsAlive() || victim->IsInFlight() || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()))
|
||||
return;
|
||||
|
||||
// Hmmmm dont like this emotes client must by self do all animations
|
||||
@@ -2224,7 +2224,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy
|
||||
MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const
|
||||
{
|
||||
|
||||
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())
|
||||
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())
|
||||
return MELEE_HIT_EVADE;
|
||||
|
||||
int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim);
|
||||
@@ -2897,7 +2897,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool Ca
|
||||
return SPELL_MISS_NONE;
|
||||
|
||||
// Return evade for units in evade mode
|
||||
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode() && !spell->HasAura(SPELL_AURA_CONTROL_VEHICLE))
|
||||
if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks() && !spell->HasAura(SPELL_AURA_CONTROL_VEHICLE))
|
||||
return SPELL_MISS_EVADE;
|
||||
|
||||
// Try victim reflect spell
|
||||
@@ -9586,7 +9586,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (victim->ToCreature()->IsInEvadeMode())
|
||||
if (victim->ToCreature()->IsEvadingAttacks())
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
|
||||
|
||||
if (!isInLOS)
|
||||
{
|
||||
i_nextCheckTime.Reset(500);
|
||||
i_nextCheckTime.Reset(100);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
|
||||
i_y += 0.2f * sin(unit->GetOrientation());
|
||||
}
|
||||
|
||||
init.MoveTo(i_x, i_y, i_z);
|
||||
init.MoveTo(i_x, i_y, i_z, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -55,7 +55,7 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
|
||||
i_y += 0.2f * sin(unit->GetOrientation());
|
||||
}
|
||||
|
||||
init.MoveTo(i_x, i_y, i_z);
|
||||
init.MoveTo(i_x, i_y, i_z, true);
|
||||
}
|
||||
if (speed > 0.0f)
|
||||
init.SetVelocity(speed);
|
||||
@@ -101,10 +101,10 @@ bool PointMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
||||
if (m_precomputedPath.size() > 2)
|
||||
init.MovebyPath(m_precomputedPath);
|
||||
else if (m_precomputedPath.size() == 2)
|
||||
init.MoveTo(m_precomputedPath[1].x, m_precomputedPath[1].y, m_precomputedPath[1].z);
|
||||
init.MoveTo(m_precomputedPath[1].x, m_precomputedPath[1].y, m_precomputedPath[1].z, true);
|
||||
}
|
||||
else
|
||||
init.MoveTo(i_x, i_y, i_z);
|
||||
init.MoveTo(i_x, i_y, i_z, true);
|
||||
if (speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit
|
||||
init.SetVelocity(speed);
|
||||
|
||||
|
||||
@@ -39,16 +39,21 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool in
|
||||
if (owner->GetMapId() == 631 && owner->GetTransport() && owner->GetTransport()->IsMotionTransport() && i_target->GetTransport() && i_target->GetTransport()->IsMotionTransport()) // for ICC, if both on a motion transport => don't use mmaps
|
||||
sameTransport = owner->GetTypeId() == TYPEID_UNIT && i_target->isInAccessiblePlaceFor(owner->ToCreature());
|
||||
bool useMMaps = MMAP::MMapFactory::IsPathfindingEnabled(owner->FindMap()) && !sameTransport;
|
||||
bool forceDest = (owner->FindMap() && owner->FindMap()->IsDungeon() && !isPlayerPet) || // force in instances to prevent exploiting
|
||||
(owner->GetTypeId() == TYPEID_UNIT && ((owner->IsPet() && owner->HasUnitState(UNIT_STATE_FOLLOW)) || // allow pets following their master to cheat while generating paths
|
||||
((Creature*)owner)->isWorldBoss() || ((Creature*)owner)->IsDungeonBoss())) || // force for all bosses, even not in instances
|
||||
bool forceDest =
|
||||
// (owner->FindMap() && owner->FindMap()->IsDungeon() && !isPlayerPet) || // force in instances to prevent exploiting
|
||||
(owner->GetTypeId() == TYPEID_UNIT && ((owner->IsPet() && owner->HasUnitState(UNIT_STATE_FOLLOW)))) || // allow pets following their master to cheat while generating paths
|
||||
// ((Creature*)owner)->isWorldBoss() || ((Creature*)owner)->IsDungeonBoss())) || // force for all bosses, even not in instances
|
||||
(owner->GetMapId() == 572 && (owner->GetPositionX() < 1275.0f || i_target->GetPositionX() < 1275.0f)) || // pussywizard: Ruins of Lordaeron - special case (acid)
|
||||
sameTransport || // nothing to comment, can't find path on transports so allow it
|
||||
(i_target->GetTypeId() == TYPEID_PLAYER && i_target->ToPlayer()->IsGameMaster()); // for .npc follow
|
||||
(i_target->GetTypeId() == TYPEID_PLAYER && i_target->ToPlayer()->IsGameMaster()) // for .npc follow*/
|
||||
; // closes "bool forceDest", that way it is more appropriate, so we can comment out crap whenever we need to
|
||||
bool forcePoint = ((!isPlayerPet || owner->GetMapId() == 618) && (forceDest || !useMMaps)) || sameTransport;
|
||||
|
||||
if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature()) && !sameTransport && !forceDest && !forcePoint)
|
||||
{
|
||||
owner->ToCreature()->SetCannotReachTarget(true);
|
||||
return;
|
||||
}
|
||||
|
||||
lastOwnerXYZ.Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ());
|
||||
lastTargetXYZ.Relocate(i_target->GetPositionX(), i_target->GetPositionY(), i_target->GetPositionZ());
|
||||
@@ -186,6 +191,11 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool in
|
||||
float maxDist = MELEE_RANGE + owner->GetMeleeReach() + i_target->GetMeleeReach();
|
||||
if (!forceDest && (i_path->GetPathType() & PATHFIND_NOPATH || (!i_offset && !isPlayerPet && i_target->GetExactDistSq(i_path->GetActualEndPosition().x, i_path->GetActualEndPosition().y, i_path->GetActualEndPosition().z) > maxDist * maxDist)))
|
||||
{
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
owner->ToCreature()->SetCannotReachTarget(false);
|
||||
}
|
||||
|
||||
lastPathingFailMSTime = World::GetGameTimeMS();
|
||||
owner->m_targetsNotAcceptable[i_target->GetGUID()] = MMapTargetData(sWorld->GetGameTime() + DISALLOW_TIME_AFTER_FAIL, owner, i_target.getTarget());
|
||||
return;
|
||||
@@ -203,8 +213,15 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool in
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if failed to generate, just use normal MoveTo
|
||||
else
|
||||
{
|
||||
// evade first
|
||||
if (owner->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
owner->ToCreature()->SetCannotReachTarget(true);
|
||||
}
|
||||
// then use normal MoveTo - if we have to
|
||||
}
|
||||
}
|
||||
|
||||
owner->AddUnitState(UNIT_STATE_CHASE);
|
||||
|
||||
Reference in New Issue
Block a user