Core/Pets: ported a couple changes from 3.3.5 branch that went missing and corrected a master branch spell check that was allowing non-charmed player controlled units to bypass the ai movement check exception (pets are not meant to be charmed, only controlled)

This commit is contained in:
Ovahlord committed 2023-12-17 05:17:57 +01:00
1 parent 2c38b2f4be
commit 924273363f
6 files changed
+27 -17

No files matched your search

+11 -11
View File
@@ -412,7 +412,7 @@ Unit* PetAI::SelectNextTarget(bool allowAutoSelect) const
if (me->HasReactState(REACT_AGGRESSIVE) && allowAutoSelect) if (me->HasReactState(REACT_AGGRESSIVE) && allowAutoSelect)
{ {
if (!me->GetCharmInfo()->IsReturning() || me->GetCharmInfo()->IsFollowing() || me->GetCharmInfo()->IsAtStay()) if (!me->GetCharmInfo()->IsReturning() || me->GetCharmInfo()->IsFollowing() || me->GetCharmInfo()->IsAtStay())
if (Unit* nearTarget = me->SelectNearestHostileUnitInAggroRange(true)) if (Unit* nearTarget = me->SelectNearestHostileUnitInAggroRange(true, true))
return nearTarget; return nearTarget;
} }
@@ -445,7 +445,8 @@ void PetAI::HandleReturnMovement()
me->GetCharmInfo()->GetStayPosition(x, y, z); me->GetCharmInfo()->GetStayPosition(x, y, z);
ClearCharmInfoFlags(); ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsReturning(true); me->GetCharmInfo()->SetIsReturning(true);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE);
me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z); me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z);
} }
} }
@@ -455,7 +456,7 @@ void PetAI::HandleReturnMovement()
{ {
ClearCharmInfoFlags(); ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsReturning(true); me->GetCharmInfo()->SetIsReturning(true);
me->GetMotionMaster()->Clear(); me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE);
me->FollowTarget(me->GetCharmerOrOwner()); me->FollowTarget(me->GetCharmerOrOwner());
} }
} }
@@ -481,7 +482,7 @@ void PetAI::DoAttack(Unit* target, bool chase)
bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared bool oldCmdAttack = me->GetCharmInfo()->IsCommandAttack(); // This needs to be reset after other flags are cleared
ClearCharmInfoFlags(); ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells me->GetCharmInfo()->SetIsCommandAttack(oldCmdAttack); // For passive pets commanded to attack so they will use spells
me->GetMotionMaster()->Clear(); me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE);
float chaseDistance = me->GetPetChaseDistance(); float chaseDistance = me->GetPetChaseDistance();
@@ -494,26 +495,25 @@ void PetAI::DoAttack(Unit* target, bool chase)
{ {
ClearCharmInfoFlags(); ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsAtStay(true); me->GetCharmInfo()->SetIsAtStay(true);
me->GetMotionMaster()->Clear(); me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE);
me->GetMotionMaster()->MoveIdle(); me->GetMotionMaster()->MoveIdle();
} }
} }
} }
void PetAI::MovementInform(uint32 moveType, uint32 data) void PetAI::MovementInform(uint32 type, uint32 id)
{ {
// Receives notification when pet reaches stay or follow owner // Receives notification when pet reaches stay or follow owner
switch (moveType) switch (type)
{ {
case POINT_MOTION_TYPE: case POINT_MOTION_TYPE:
{ {
// Pet is returning to where stay was clicked. data should be // Pet is returning to where stay was clicked. data should be
// pet's GUIDLow since we set that as the waypoint ID // pet's GUIDLow since we set that as the waypoint ID
if (data == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning()) if (id == me->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
{ {
ClearCharmInfoFlags(); ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsAtStay(true); me->GetCharmInfo()->SetIsAtStay(true);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveIdle(); me->GetMotionMaster()->MoveIdle();
} }
break; break;
@@ -522,7 +522,7 @@ void PetAI::MovementInform(uint32 moveType, uint32 data)
{ {
// If data is owner's GUIDLow then we've reached follow point, // If data is owner's GUIDLow then we've reached follow point,
// otherwise we're probably chasing a creature // otherwise we're probably chasing a creature
if (me->GetCharmerOrOwner() && me->GetCharmInfo() && data == me->GetCharmerOrOwner()->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning()) if (me->GetCharmerOrOwner() && me->GetCharmInfo() && id == me->GetCharmerOrOwner()->GetGUID().GetCounter() && me->GetCharmInfo()->IsReturning())
{ {
ClearCharmInfoFlags(); ClearCharmInfoFlags();
me->GetCharmInfo()->SetIsFollowing(true); me->GetCharmInfo()->SetIsFollowing(true);
@@ -624,7 +624,7 @@ void PetAI::ReceiveEmote(Player* player, uint32 emote)
void PetAI::OnCharmed(bool isNew) void PetAI::OnCharmed(bool isNew)
{ {
if (me->IsCharmed()) if (!me->isPossessedByPlayer() && me->IsCharmed())
me->FollowTarget(me->GetCharmer()); me->FollowTarget(me->GetCharmer());
CreatureAI::OnCharmed(isNew); CreatureAI::OnCharmed(isNew);
+3 -1
View File
@@ -38,11 +38,13 @@ class TC_GAME_API PetAI : public CreatureAI
void KilledUnit(Unit* /*victim*/) override; void KilledUnit(Unit* /*victim*/) override;
void AttackStart(Unit* target) override; // only start attacking if not attacking something else already void AttackStart(Unit* target) override; // only start attacking if not attacking something else already
void _AttackStart(Unit* target); // always start attacking if possible void _AttackStart(Unit* target); // always start attacking if possible
void MovementInform(uint32 moveType, uint32 data) override; void MovementInform(uint32 type, uint32 id) override;
void OwnerAttackedBy(Unit* attacker) override; void OwnerAttackedBy(Unit* attacker) override;
void OwnerAttacked(Unit* target) override; void OwnerAttacked(Unit* target) override;
void DamageTaken(Unit* attacker, uint32& /*damage*/) override { AttackStart(attacker); } void DamageTaken(Unit* attacker, uint32& /*damage*/) override { AttackStart(attacker); }
void ReceiveEmote(Player* player, uint32 textEmote) override; void ReceiveEmote(Player* player, uint32 textEmote) override;
void JustEnteredCombat(Unit* who) override { EngagementStart(who); }
void JustExitedCombat() override { EngagementOver(); }
void OnCharmed(bool isNew) override; void OnCharmed(bool isNew) override;
// The following aren't used by the PetAI but need to be defined to override // The following aren't used by the PetAI but need to be defined to override
@@ -3000,14 +3000,14 @@ float Creature::GetAggroRange(Unit const* target) const
return 0.0f; return 0.0f;
} }
Unit* Creature::SelectNearestHostileUnitInAggroRange(bool useLOS) const Unit* Creature::SelectNearestHostileUnitInAggroRange(bool useLOS, bool ignoreCivilians) const
{ {
// Selects nearest hostile target within creature's aggro range. Used primarily by // Selects nearest hostile target within creature's aggro range. Used primarily by
// pets set to aggressive. Will not return neutral or friendly targets. // pets set to aggressive. Will not return neutral or friendly targets.
Unit* target = nullptr; Unit* target = nullptr;
Trinity::NearestHostileUnitInAggroRangeCheck u_check(this, useLOS); Trinity::NearestHostileUnitInAggroRangeCheck u_check(this, useLOS, ignoreCivilians);
Trinity::UnitSearcher<Trinity::NearestHostileUnitInAggroRangeCheck> searcher(this, target, u_check); Trinity::UnitSearcher<Trinity::NearestHostileUnitInAggroRangeCheck> searcher(this, target, u_check);
Cell::VisitGridObjects(this, searcher, MAX_AGGRO_RADIUS); Cell::VisitGridObjects(this, searcher, MAX_AGGRO_RADIUS);
+1 -1
View File
@@ -241,7 +241,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
Unit* SelectNearestTarget(float dist = 0, bool playerOnly = false) const; Unit* SelectNearestTarget(float dist = 0, bool playerOnly = false) const;
Unit* SelectNearestTargetInAttackDistance(float dist = 0) const; Unit* SelectNearestTargetInAttackDistance(float dist = 0) const;
Unit* SelectNearestHostileUnitInAggroRange(bool useLOS = false) const; Unit* SelectNearestHostileUnitInAggroRange(bool useLOS = false, bool ignoreCivilians = false) const;
void DoFleeToGetAssistance(); void DoFleeToGetAssistance();
void CallForHelp(float fRadius); void CallForHelp(float fRadius);
@@ -1217,9 +1217,10 @@ namespace Trinity
class NearestHostileUnitInAggroRangeCheck class NearestHostileUnitInAggroRangeCheck
{ {
public: public:
explicit NearestHostileUnitInAggroRangeCheck(Creature const* creature, bool useLOS = false) : _me(creature), _useLOS(useLOS) explicit NearestHostileUnitInAggroRangeCheck(Creature const* creature, bool useLOS = false, bool ignoreCivilians = false) : _me(creature), _useLOS(useLOS), _ignoreCivilians(ignoreCivilians)
{ {
} }
bool operator()(Unit* u) bool operator()(Unit* u)
{ {
if (!u->IsHostileTo(_me)) if (!u->IsHostileTo(_me))
@@ -1234,12 +1235,19 @@ namespace Trinity
if (_useLOS && !u->IsWithinLOSInMap(_me)) if (_useLOS && !u->IsWithinLOSInMap(_me))
return false; return false;
// pets in aggressive do not attack civilians
if (_ignoreCivilians)
if (Creature* c = u->ToCreature())
if (c->IsCivilian())
return false;
return true; return true;
} }
private: private:
Creature const* _me; Creature const* _me;
bool _useLOS; bool _useLOS;
bool _ignoreCivilians;
NearestHostileUnitInAggroRangeCheck(NearestHostileUnitInAggroRangeCheck const&); NearestHostileUnitInAggroRangeCheck(NearestHostileUnitInAggroRangeCheck const&);
}; };
+1 -1
View File
@@ -4093,7 +4093,7 @@ void Spell::update(uint32 difftime)
// if charmed by creature, trust the AI not to cheat and allow the cast to proceed // if charmed by creature, trust the AI not to cheat and allow the cast to proceed
// @todo this is a hack, "creature" movesplines don't differentiate turning/moving right now // @todo this is a hack, "creature" movesplines don't differentiate turning/moving right now
// however, checking what type of movement the spline is for every single spline would be really expensive // however, checking what type of movement the spline is for every single spline would be really expensive
if (!m_caster->ToUnit()->GetCharmerGUID().IsCreature()) if (!m_caster->ToUnit()->IsControlledByPlayer())
cancel(); cancel();
} }