diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 8416b5300a..0a35e19546 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -412,7 +412,7 @@ Unit* PetAI::SelectNextTarget(bool allowAutoSelect) const if (me->HasReactState(REACT_AGGRESSIVE) && allowAutoSelect) { 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; } @@ -445,7 +445,8 @@ void PetAI::HandleReturnMovement() me->GetCharmInfo()->GetStayPosition(x, y, z); ClearCharmInfoFlags(); me->GetCharmInfo()->SetIsReturning(true); - me->GetMotionMaster()->Clear(); + + me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE); me->GetMotionMaster()->MovePoint(me->GetGUID().GetCounter(), x, y, z); } } @@ -455,7 +456,7 @@ void PetAI::HandleReturnMovement() { ClearCharmInfoFlags(); me->GetCharmInfo()->SetIsReturning(true); - me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE); 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 ClearCharmInfoFlags(); 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(); @@ -494,26 +495,25 @@ void PetAI::DoAttack(Unit* target, bool chase) { ClearCharmInfoFlags(); me->GetCharmInfo()->SetIsAtStay(true); - me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->Clear(MOTION_SLOT_ACTIVE); 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 - switch (moveType) + switch (type) { case POINT_MOTION_TYPE: { // Pet is returning to where stay was clicked. data should be // 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(); me->GetCharmInfo()->SetIsAtStay(true); - me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); } break; @@ -522,7 +522,7 @@ void PetAI::MovementInform(uint32 moveType, uint32 data) { // If data is owner's GUIDLow then we've reached follow point, // 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(); me->GetCharmInfo()->SetIsFollowing(true); @@ -624,7 +624,7 @@ void PetAI::ReceiveEmote(Player* player, uint32 emote) void PetAI::OnCharmed(bool isNew) { - if (me->IsCharmed()) + if (!me->isPossessedByPlayer() && me->IsCharmed()) me->FollowTarget(me->GetCharmer()); CreatureAI::OnCharmed(isNew); diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index 2346b106ec..c7f339b528 100644 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -38,11 +38,13 @@ class TC_GAME_API PetAI : public CreatureAI void KilledUnit(Unit* /*victim*/) override; void AttackStart(Unit* target) override; // only start attacking if not attacking something else already 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 OwnerAttacked(Unit* target) override; void DamageTaken(Unit* attacker, uint32& /*damage*/) override { AttackStart(attacker); } void ReceiveEmote(Player* player, uint32 textEmote) override; + void JustEnteredCombat(Unit* who) override { EngagementStart(who); } + void JustExitedCombat() override { EngagementOver(); } void OnCharmed(bool isNew) override; // The following aren't used by the PetAI but need to be defined to override diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 256ffcf243..894d1eabe3 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -3000,14 +3000,14 @@ float Creature::GetAggroRange(Unit const* target) const 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 // pets set to aggressive. Will not return neutral or friendly targets. Unit* target = nullptr; - Trinity::NearestHostileUnitInAggroRangeCheck u_check(this, useLOS); + Trinity::NearestHostileUnitInAggroRangeCheck u_check(this, useLOS, ignoreCivilians); Trinity::UnitSearcher searcher(this, target, u_check); Cell::VisitGridObjects(this, searcher, MAX_AGGRO_RADIUS); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index f9dfb5cfa6..2f3293f6fc 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -241,7 +241,7 @@ class TC_GAME_API Creature : public Unit, public GridObject, public Ma Unit* SelectNearestTarget(float dist = 0, bool playerOnly = false) 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 CallForHelp(float fRadius); diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 7b695c557c..9016db11e4 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -1217,9 +1217,10 @@ namespace Trinity class NearestHostileUnitInAggroRangeCheck { 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) { if (!u->IsHostileTo(_me)) @@ -1234,12 +1235,19 @@ namespace Trinity if (_useLOS && !u->IsWithinLOSInMap(_me)) return false; + // pets in aggressive do not attack civilians + if (_ignoreCivilians) + if (Creature* c = u->ToCreature()) + if (c->IsCivilian()) + return false; + return true; } private: Creature const* _me; bool _useLOS; + bool _ignoreCivilians; NearestHostileUnitInAggroRangeCheck(NearestHostileUnitInAggroRangeCheck const&); }; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 017872a274..e8da74545c 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -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 // @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 - if (!m_caster->ToUnit()->GetCharmerGUID().IsCreature()) + if (!m_caster->ToUnit()->IsControlledByPlayer()) cancel(); }