diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp index 9235562f..a592870b 100644 --- a/src/server/game/AI/CoreAI/GuardAI.cpp +++ b/src/server/game/AI/CoreAI/GuardAI.cpp @@ -50,7 +50,7 @@ bool GuardAI::CanSeeAlways(WorldObject const* obj) return false; } -void GuardAI::EnterEvadeMode(EvadeReason /*why*/) +void GuardAI::EnterEvadeMode(EvadeReason why) { if (!me->IsAlive()) { @@ -66,7 +66,8 @@ void GuardAI::EnterEvadeMode(EvadeReason /*why*/) me->CombatStop(true); EngagementOver(); - me->GetMotionMaster()->MoveTargetedHome(); + if (why != EVADE_REASON_VEHICLE_EVADE) + me->GetMotionMaster()->MoveTargetedHome(); } void GuardAI::JustDied(Unit* killer) diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 8bd4a4e7..64e29c40 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -186,6 +186,12 @@ void CreatureAI::EnterEvadeMode(EvadeReason why) TC_LOG_DEBUG("scripts.ai", "CreatureAI::EnterEvadeMode: entering evade mode (why: {}) ({})", why, me->GetGUID().ToString()); + if (why == EVADE_REASON_VEHICLE_EVADE) + { + Reset(); + return; + } + if (!me->GetVehicle()) // otherwise me will be in evade mode forever { if (Unit* owner = me->GetCharmerOrOwner()) @@ -283,6 +289,15 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) me->GetSpellHistory()->ResetAllCooldowns(); EngagementOver(); + if (Vehicle* myVehicle = me->GetVehicleKit()) + for (auto const& [_, seat] : myVehicle->Seats) + { + if (!seat.Passenger.Guid.IsEmpty() && seat.Passenger.Guid.GetTypeId() == TYPEID_UNIT) + if (Creature* passenger = ObjectAccessor::GetCreature(*me, seat.Passenger.Guid)) + if (passenger->IsAIEnabled() && passenger->AI()) + passenger->AI()->EnterEvadeMode(EVADE_REASON_VEHICLE_EVADE); + } + return true; } diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index 69bc6343..0184bcde 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -96,6 +96,7 @@ class TC_GAME_API CreatureAI : public UnitAI EVADE_REASON_NO_PATH, // the creature was unable to reach its target for over 5 seconds EVADE_REASON_SEQUENCE_BREAK, // this is a boss and the pre-requisite encounters for engaging it are not defeated yet EVADE_REASON_OTHER, // anything else + EVADE_REASON_VEHICLE_EVADE }; explicit CreatureAI(Creature* creature); diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index 57440748..0e919bfa 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -93,7 +93,7 @@ void EscortAI::ReturnToLastPoint() me->GetMotionMaster()->MovePoint(POINT_LAST_POINT, me->GetHomePosition()); } -void EscortAI::EnterEvadeMode(EvadeReason /*why*/) +void EscortAI::EnterEvadeMode(EvadeReason why) { me->RemoveAllAuras(); me->CombatStop(true); @@ -101,6 +101,12 @@ void EscortAI::EnterEvadeMode(EvadeReason /*why*/) EngagementOver(); + if (why == EVADE_REASON_VEHICLE_EVADE) + { + Reset(); + return; + } + if (HasEscortState(STATE_ESCORT_ESCORTING)) { AddEscortState(STATE_ESCORT_RETURNING); diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 7ea2a11b..e07a3ee2 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -394,7 +394,7 @@ void SmartAI::MovementInform(uint32 type, uint32 id) _OOCReached = true; } -void SmartAI::EnterEvadeMode(EvadeReason /*why*/) +void SmartAI::EnterEvadeMode(EvadeReason why) { if (_evadeDisabled) { @@ -417,6 +417,9 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/) SetRun(_run); + if (why == EVADE_REASON_VEHICLE_EVADE) + return; + if (me->IsCharmed() && me->GetCharmerOrOwner()) { Unit* owner = me->GetCharmerOrOwner(); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 5a7a2eba..cf6d2089 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -12725,6 +12725,9 @@ void Unit::_ExitVehicle(Position const* exitPosition) SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT AddUnitState(UNIT_STATE_MOVE); + bool wasEvading = HasUnitState(UNIT_STATE_EVADE); + if (wasEvading) + ClearUnitState(UNIT_STATE_EVADE); if (player) player->SetFallInformation(0, GetPositionZ()); @@ -12788,6 +12791,15 @@ void Unit::_ExitVehicle(Position const* exitPosition) else ToTempSummon()->UnSummon(2000); // Approximation } + else if (wasEvading && GetTypeId() == TYPEID_UNIT) + { + Creature* toCreature = ToCreature(); + toCreature->SetSpawnHealth(); + toCreature->LoadCreaturesAddon(); + if (toCreature->IsVehicle()) + toCreature->GetVehicleKit()->Reset(true); + toCreature->AI()->JustReachedHome(); + } } void Unit::BuildMovementPacket(ByteBuffer *data) const diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index e746cc0f..7607db00 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -86,6 +86,22 @@ void Vehicle::InstallAllAccessories(bool evading) if (GetBase()->GetTypeId() == TYPEID_PLAYER || !evading) RemoveAllPassengers(); // We might have aura's saved in the DB with now invalid casters - remove + if (GetBase()->GetTypeId() == TYPEID_UNIT && evading) + for (auto const& [_, seat] : Seats) + { + if (!seat.Passenger.Guid.IsEmpty() && seat.Passenger.Guid.GetTypeId() == TYPEID_UNIT) + if (Creature* passenger = ObjectAccessor::GetCreature(*_me, seat.Passenger.Guid)) + if (passenger->IsInEvadeMode()) + { + passenger->ClearUnitState(UNIT_STATE_EVADE); + passenger->SetSpawnHealth(); + passenger->LoadCreaturesAddon(); + if (passenger->IsVehicle()) + passenger->GetVehicleKit()->Reset(true); + passenger->AI()->JustReachedHome(); + } + } + VehicleAccessoryList const* accessories = sObjectMgr->GetVehicleAccessoryList(this); if (!accessories) return;