diff --git a/doc/EventAI.txt b/doc/EventAI.txt index a617408689b..c5d2b70fff0 100644 --- a/doc/EventAI.txt +++ b/doc/EventAI.txt @@ -558,6 +558,38 @@ Expires when main aggro target is not reachable by ChaseMovementGenerator - exam Parameter 1: SpellID Expires when spellId is successfully cast by spell lists +----------------------- +38 = EVENT_T_BOARD_VEHICLE +----------------------- +Parameter 1: Board - 0 if creature is exiting a vehicle, 1 if entering a vehicle, 2 both +Parameter 2: Seat Id (-1 if triggering on any seat) +Expires when a vehicle is entered or exited based on param 1 + +----------------------- +39 = EVENT_T_PASSENGER_BOARDED +----------------------- +Parameter 1: Board - 0 if creature(vehicle) is being exited, 1 if creature(vehicle) is being entered , 2 both +Parameter 2: Seat Id (-1 if triggering on any seat) +Expires when the creature(vehicle) is entered or exited based on param 1 + +----------------------- +40 = EVENT_T_VEHICLE_RETURN +----------------------- +Parameter 1: Seat Id (-1 if triggering on any seat) +Expires when the passenger in this seat returns to the vehicle + +----------------------- +41 = EVENT_T_PASSENGER_SPAWN +----------------------- +Parameter 1: Seat Id (-1 if triggering on any seat) +Expires when the vehicle spawns a passenger in this seat + +----------------------- +42 = EVENT_T_PASSENGER_CONTROL_END +----------------------- +Parameter 1: Seat Id (-1 if triggering on any seat) +Expires when the passenger switches from a seat that has control to a non-controlling seat + (Name ==> School ==> School Bitmask Values) ------------------------------------------- SPELL_SCHOOL_NORMAL = 0 ==> 1 diff --git a/src/game/AI/BaseAI/UnitAI.h b/src/game/AI/BaseAI/UnitAI.h index 804d93c61d0..efb9cbac8dd 100644 --- a/src/game/AI/BaseAI/UnitAI.h +++ b/src/game/AI/BaseAI/UnitAI.h @@ -570,7 +570,10 @@ class UnitAI : public CombatActions // Vehicle Hooks virtual void OnPassengerRide(Unit* passenger, bool boarded, uint8 seat) {} + virtual void OnPassengerSpawn(uint8 seat) {} virtual void OnVehicleRide(Unit* vehicle, bool boarded, uint8 seat) {} + virtual void OnVehicleReturn(uint8 seat) {} + virtual void OnPassengerControlEnd(uint8 seat) {} protected: virtual std::string GetAIName() { return "UnitAI"; } diff --git a/src/game/AI/EventAI/CreatureEventAI.cpp b/src/game/AI/EventAI/CreatureEventAI.cpp index f1752b97e60..d00e8463afd 100644 --- a/src/game/AI/EventAI/CreatureEventAI.cpp +++ b/src/game/AI/EventAI/CreatureEventAI.cpp @@ -582,6 +582,9 @@ bool CreatureEventAI::CheckEvent(CreatureEventAIHolder& holder, Unit* actionInvo if (!m_creature->GetVictim() || !IsCombatMovement() || m_creature->GetMotionMaster()->GetCurrent()->IsReachable()) return false; break; + case EVENT_T_BOARD_VEHICLE: + case EVENT_T_PASSENGER_BOARDED: + break; default: sLog.outErrorEventAI("Creature %u using Event %u has invalid Event Type(%u), missing from ProcessEvent() Switch.", m_creature->GetEntry(), holder.event.event_id, holder.event.event_type); return false; @@ -1622,6 +1625,58 @@ void CreatureEventAI::OnSpellCast(SpellEntry const* spellInfo, Unit* target) ProcessEvents(target); } +void CreatureEventAI::OnVehicleRide(Unit* vehicle, bool boarded, uint8 seat) +{ + IncreaseDepthIfNecessary(); + for (auto& i : m_CreatureEventAIList) + if (i.event.event_type == EVENT_T_BOARD_VEHICLE) + if (i.event.boardVehicle.board == boarded || i.event.boardVehicle.board == 2) + if (i.event.boardVehicle.seat == seat || i.event.boardVehicle.seat == -1) + CheckAndReadyEventForExecution(i, vehicle); + ProcessEvents(vehicle); +} + +void CreatureEventAI::OnPassengerRide(Unit* passenger, bool boarded, uint8 seat) +{ + IncreaseDepthIfNecessary(); + for (auto& i : m_CreatureEventAIList) + if (i.event.event_type == EVENT_T_PASSENGER_BOARDED) + if (i.event.passengerBoard.board == boarded || i.event.passengerBoard.board == 2) + if (i.event.passengerBoard.seat == seat || i.event.passengerBoard.seat == -1) + CheckAndReadyEventForExecution(i, passenger); + ProcessEvents(passenger); +} + +void CreatureEventAI::OnVehicleReturn(uint8 seat) +{ + IncreaseDepthIfNecessary(); + for (auto& i : m_CreatureEventAIList) + if (i.event.event_type == EVENT_T_VEHICLE_RETURN) + if (i.event.vehicleReturn.seat == seat || i.event.vehicleReturn.seat == -1) + CheckAndReadyEventForExecution(i); + ProcessEvents(); +} + +void CreatureEventAI::OnPassengerSpawn(uint8 seat) +{ + IncreaseDepthIfNecessary(); + for (auto& i : m_CreatureEventAIList) + if (i.event.event_type == EVENT_T_VEHICLE_RETURN) + if (i.event.passengerSpawn.seat == seat || i.event.passengerSpawn.seat == -1) + CheckAndReadyEventForExecution(i); + ProcessEvents(); +} + +void CreatureEventAI::OnPassengerControlEnd(uint8 seat) +{ + IncreaseDepthIfNecessary(); + for (auto& i : m_CreatureEventAIList) + if (i.event.event_type == EVENT_T_VEHICLE_RETURN) + if (i.event.passengerControlEnd.seat == seat || i.event.passengerControlEnd.seat == -1) + CheckAndReadyEventForExecution(i); + ProcessEvents(); +} + void CreatureEventAI::EnterCombat(Unit* enemy) { CreatureAI::EnterCombat(enemy); diff --git a/src/game/AI/EventAI/CreatureEventAI.h b/src/game/AI/EventAI/CreatureEventAI.h index 6555a9f4c0f..82bd93b61d5 100644 --- a/src/game/AI/EventAI/CreatureEventAI.h +++ b/src/game/AI/EventAI/CreatureEventAI.h @@ -77,6 +77,11 @@ enum EventAI_Type EVENT_T_DEATH_PREVENTED = 35, // EVENT_T_TARGET_NOT_REACHABLE = 36, // EVENT_T_SPELL_CAST = 37, // SpellId + EVENT_T_BOARD_VEHICLE = 38, // Boarding, SeatID + EVENT_T_PASSENGER_BOARDED = 39, // Boarding, SeatID + EVENT_T_VEHICLE_RETURN = 40, // SeatID + EVENT_T_PASSENGER_SPAWN = 41, // SeatID + EVENT_T_PASSENGER_CONTROL_END = 42, // SeatID EVENT_T_END, }; @@ -794,6 +799,33 @@ struct CreatureEventAI_Event { uint32 spellId; } spellCast; + // EVENT_T_BOARD_VEHICLE = 38 + struct + { + uint32 board; + uint32 seat; + } boardVehicle; + // EVENT_T_PASSENGER_BOARDED = 39 + struct + { + uint32 board; + uint32 seat; + } passengerBoard; + // EVENT_T_VEHICLE_RETURN = 40 + struct + { + uint32 seat; + } vehicleReturn; + // EVENT_T_PASSENGER_SPAWN = 41 + struct + { + uint32 seat; + } passengerSpawn; + // EVENT_T_PASSENGER_CONTROL_END = 42 + struct + { + uint32 seat; + } passengerControlEnd; // RAW struct { @@ -885,6 +917,11 @@ class CreatureEventAI : public CreatureAI void ReceiveAIEvent(AIEventType eventType, Unit* sender, Unit* invoker, uint32 miscValue) override; void CorpseRemoved(uint32& respawnDelay) override; void OnSpellCast(SpellEntry const* spellInfo, Unit* target) override; + void OnVehicleRide(Unit* vehicle, bool boarded, uint8 seat) override; + void OnPassengerRide(Unit* passenger, bool boarded, uint8 seat) override; + void OnVehicleReturn(uint8 seat) override; + void OnPassengerSpawn(uint8 seat) override; + void OnPassengerControlEnd(uint8 seat) override; // bool IsControllable() const override { return true; } static int Permissible(const Creature* creature); diff --git a/src/game/Entities/Vehicle.cpp b/src/game/Entities/Vehicle.cpp index 9c2e3e827ad..bac0067fd0d 100644 --- a/src/game/Entities/Vehicle.cpp +++ b/src/game/Entities/Vehicle.cpp @@ -41,6 +41,7 @@ #include "AI/BaseAI/CreatureAI.h" #include "Globals/ObjectMgr.h" #include "Models/M2Stores.h" +#include "Server/DBCEnums.h" #include "Server/DBCStores.h" #include "Server/SQLStorages.h" #include "Movement/MoveSplineInit.h" @@ -392,9 +393,9 @@ void VehicleInfo::SwitchSeat(Unit* passenger, uint8 seat) PassengerMap::const_iterator itr = m_passengers.find(passenger); MANGOS_ASSERT(itr != m_passengers.end()); - + uint8 oldSeat = itr->second->GetTransportSeat(); // We are already boarded to this seat - if (itr->second->GetTransportSeat() == seat) + if (oldSeat == seat) return; // Check if it's a valid seat @@ -439,6 +440,8 @@ void VehicleInfo::SwitchSeat(Unit* passenger, uint8 seat) // It seems that Seat switching is sent without SplineFlag BoardVehicle init.Launch(); + bool hadControl = seatEntry->m_flags & SEAT_FLAG_CAN_CONTROL; + // Get seatEntry of new seat seatEntry = GetSeatEntry(seat); MANGOS_ASSERT(seatEntry); @@ -449,7 +452,11 @@ void VehicleInfo::SwitchSeat(Unit* passenger, uint8 seat) if (Unit* owner = dynamic_cast(m_owner)) { if (owner->AI()) + { owner->AI()->OnPassengerRide(passenger, true, seat); + if (hadControl && !(seatEntry->m_flags & SEAT_FLAG_CAN_CONTROL)) + owner->AI()->OnPassengerControlEnd(oldSeat); + } if (passenger->AI()) passenger->AI()->OnVehicleRide(owner, true, seat); } @@ -669,6 +676,8 @@ void VehicleInfo::RespawnAccessories(int32 seatIndex) Position pos = m_owner->GetPosition(); pos.o *= 2; SummonPassenger(itr->passengerEntry, pos, itr->seatId); + if (UnitAI* ownerAI = static_cast(m_owner)->AI()) + ownerAI->OnPassengerSpawn(itr->seatId); } } @@ -704,6 +713,8 @@ void VehicleInfo::RecallAccessories(float distance, int32 seatIndex) int32 basepoint0 = seat; creature->CastCustomSpell(static_cast(m_owner), SPELL_RIDE_VEHICLE_HARDCODED, &basepoint0, nullptr, nullptr, TRIGGERED_OLD_TRIGGERED); itr = m_unboardedAccessories.erase(itr); + if (UnitAI* ownerAI = static_cast(m_owner)->AI()) + ownerAI->OnVehicleReturn(seat); } else ++itr; }