TrinityCore
Loading...
Searching...
No Matches
Vehicle.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "Vehicle.h"
19#include "Battleground.h"
20#include "CharmInfo.h"
21#include "Common.h"
22#include "CreatureAI.h"
23#include "DB2Stores.h"
24#include "EventProcessor.h"
25#include "Log.h"
26#include "MotionMaster.h"
27#include "MoveSplineInit.h"
28#include "ObjectAccessor.h"
29#include "ObjectMgr.h"
30#include "Player.h"
31#include "ScriptMgr.h"
32#include "SpellAuraEffects.h"
33#include "TemporarySummon.h"
34#include "Unit.h"
35#include <sstream>
36
38{
39public:
41 bool Execute(uint64, uint32) override;
42 void Abort(uint64) override;
43
46 SeatMap::iterator Seat;
47};
48
49Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) :
50UsableSeatNum(0), _me(unit), _vehicleInfo(vehInfo), _creatureEntry(creatureEntry), _status(STATUS_NONE)
51{
52 for (int8 i = 0; i < MAX_VEHICLE_SEATS; ++i)
53 {
54 if (uint32 seatId = _vehicleInfo->SeatID[i])
55 if (VehicleSeatEntry const* veSeat = sVehicleSeatStore.LookupEntry(seatId))
56 {
57 VehicleSeatAddon const* addon = sObjectMgr->GetVehicleSeatAddon(seatId);
58 Seats.insert(std::make_pair(i, VehicleSeat(veSeat, addon)));
59 if (veSeat->CanEnterOrExit())
61 }
62 }
63
64 // Set or remove correct flags based on available seats. Will overwrite db data (if wrong).
65 if (UsableSeatNum)
67 else if (!unit->m_unitData->InteractSpellID)
69
71}
72
74{
77 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
78 ASSERT(itr->second.IsEmpty());
79}
80
91{
93 if (GetBase()->GetTypeId() == TYPEID_UNIT)
94 sScriptMgr->OnInstall(this);
95}
96
98{
99 if (GetBase()->GetTypeId() == TYPEID_PLAYER || !evading)
100 RemoveAllPassengers(); // We might have aura's saved in the DB with now invalid casters - remove
101
102 VehicleAccessoryList const* accessories = sObjectMgr->GetVehicleAccessoryList(this);
103 if (!accessories)
104 return;
105
106 for (VehicleAccessoryList::const_iterator itr = accessories->begin(); itr != accessories->end(); ++itr)
107 if (!evading || itr->IsMinion) // only install minions on evade mode
108 InstallAccessory(itr->AccessoryEntry, itr->SeatId, itr->IsMinion, itr->SummonedType, itr->SummonTime, itr->RideSpellID);
109}
110
122{
124 if (_status == STATUS_UNINSTALLING && !GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
125 {
126 TC_LOG_ERROR("entities.vehicle", "Vehicle {} Entry: {} attempts to uninstall, but already has STATUS_UNINSTALLING! "
127 "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUID().ToString(), _creatureEntry);
128 return;
129 }
130
132 TC_LOG_DEBUG("entities.vehicle", "Vehicle::Uninstall Entry: {}, {}", _creatureEntry, _me->GetGUID().ToString());
134
135 if (GetBase()->GetTypeId() == TYPEID_UNIT)
136 sScriptMgr->OnUninstall(this);
137}
138
150void Vehicle::Reset(bool evading /*= false*/)
151{
152 if (GetBase()->GetTypeId() != TYPEID_UNIT)
153 return;
154
155 TC_LOG_DEBUG("entities.vehicle", "Vehicle::Reset (Entry: {}, {}, DBGuid: {})", GetCreatureEntry(), _me->GetGUID().ToString(), _me->ToCreature()->GetSpawnId());
156
158 if (GetBase()->IsAlive())
159 InstallAllAccessories(evading);
160
161 sScriptMgr->OnReset(this);
162}
163
174{
175 // This couldn't be done in DB, because some spells have MECHANIC_NONE
176
177 // Vehicles should be immune on Knockback ...
180
181 // Mechanical units & vehicles ( which are not Bosses, they have own immunities in DB ) should be also immune on healing ( exceptions in switch below )
183 {
184 // Heal & dispel ...
189
190 // ... Shield & Immunity grant spells ...
197
198 // ... Resistance, Split damage, Change stats ...
204 }
205
206 // Different immunities for vehicles goes below
207 switch (GetVehicleInfo()->ID)
208 {
209 // code below prevents a bug with movable cannons
210 case 160: // Strand of the Ancients
211 case 244: // Wintergrasp
212 case 510: // Isle of Conquest
213 case 452: // Isle of Conquest
214 case 543: // Isle of Conquest
216 // why we need to apply this? we can simple add immunities to slow mechanic in DB
218 break;
219 case 335: // Salvaged Chopper
220 case 336: // Salvaged Siege Engine
221 case 338: // Salvaged Demolisher
223 break;
224 default:
225 break;
226 }
227}
228
239{
240 TC_LOG_DEBUG("entities.vehicle", "Vehicle::RemoveAllPassengers. Entry: {}, {}", _creatureEntry, _me->GetGUID().ToString());
241
244 {
246 Vehicle* eventVehicle = _status != STATUS_UNINSTALLING ? this : nullptr;
247
248 while (!_pendingJoinEvents.empty())
249 {
251 e->ScheduleAbort();
252 e->Target = eventVehicle;
253 _pendingJoinEvents.pop_front();
254 }
255 }
256
257 // Passengers always cast an aura with SPELL_AURA_CONTROL_VEHICLE on the vehicle
258 // We just remove the aura and the unapply handler will make the target leave the vehicle.
259 // We don't need to iterate over Seats
261
262 // Aura script might cause the vehicle to be despawned in the middle of handling SPELL_AURA_CONTROL_VEHICLE removal
263 // In that case, aura effect has already been unregistered but passenger may still be found in Seats
264 for (auto const& [_, seat] : Seats)
265 if (Unit* passenger = ObjectAccessor::GetUnit(*_me, seat.Passenger.Guid))
266 passenger->_ExitVehicle();
267}
268
282bool Vehicle::HasEmptySeat(int8 seatId) const
283{
284 SeatMap::const_iterator seat = Seats.find(seatId);
285 if (seat == Seats.end())
286 return false;
287 return seat->second.IsEmpty();
288}
289
304{
305 SeatMap::const_iterator seat = Seats.find(seatId);
306 if (seat == Seats.end())
307 return nullptr;
308
309 return ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger.Guid);
310}
311
326SeatMap::const_iterator Vehicle::GetNextEmptySeat(int8 seatId, bool next) const
327{
328 SeatMap::const_iterator seat = Seats.find(seatId);
329 if (seat == Seats.end())
330 return seat;
331
332 while (!seat->second.IsEmpty() || HasPendingEventForSeat(seat->first) || (!seat->second.SeatInfo->CanEnterOrExit() && !seat->second.SeatInfo->IsUsableByOverride()))
333 {
334 if (next)
335 {
336 if (++seat == Seats.end())
337 seat = Seats.begin();
338 }
339 else
340 {
341 if (seat == Seats.begin())
342 seat = Seats.end();
343 --seat;
344 }
345
346 // Make sure we don't loop indefinetly
347 if (seat->first == seatId)
348 {
349 seat = Seats.end();
350 break;
351 }
352 }
353
354 return seat;
355}
356
371{
372 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); itr++)
373 if (!itr->second.IsEmpty() && itr->second.Passenger.Guid == passenger->GetGUID())
374 return itr->second.SeatAddon;
375
376 return nullptr;
377}
378
396void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type, uint32 summonTime, Optional<uint32> rideSpellId /*= {}*/)
397{
400 {
401 TC_LOG_ERROR("entities.vehicle", "Vehicle ({}, Entry: {}) attempts to install accessory (Entry: {}) on seat {} with STATUS_UNINSTALLING! "
402 "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUID().ToString(),
403 GetCreatureEntry(), entry, (int32)seatId);
404 return;
405 }
406
407 TC_LOG_DEBUG("entities.vehicle", "Vehicle ({}, Entry {}): installing accessory (Entry: {}) on seat: {}",
408 _me->GetGUID().ToString(), GetCreatureEntry(), entry, (int32)seatId);
409
410 TempSummon* accessory = _me->SummonCreature(entry, *_me, TempSummonType(type), Milliseconds(summonTime));
411 ASSERT(accessory);
412
413 if (minion)
414 {
416 accessory->GetThreatManager().Initialize(); // reinitialize CanHaveThreatList cached value
417 }
418
419 if (rideSpellId)
420 _me->HandleSpellClick(accessory, seatId, *rideSpellId);
421 else
422 _me->HandleSpellClick(accessory, seatId);
423
426}
427
443{
446 {
447 TC_LOG_ERROR("entities.vehicle", "Passenger {}, attempting to board vehicle {} during uninstall! SeatId: {}",
448 unit->GetGUID().ToString(), _me->GetGUID().ToString(), (int32)seatId);
449 return false;
450 }
451
452 TC_LOG_DEBUG("entities.vehicle", "Unit {} scheduling enter vehicle (entry: {}, vehicleId: {}, guid: {} on seat {}",
453 unit->GetName(), _me->GetEntry(), _vehicleInfo->ID, _me->GetGUID().ToString(), (int32)seatId);
454
455 // The seat selection code may kick other passengers off the vehicle.
456 // While the validity of the following may be arguable, it is possible that when such a passenger
457 // exits the vehicle will dismiss. That's why the actual adding the passenger to the vehicle is scheduled
458 // asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile.
459 SeatMap::iterator seat;
460 VehicleJoinEvent* e = new VehicleJoinEvent(this, unit);
461 unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0s));
462
463 if (seatId < 0) // no specific seat requirement
464 {
465 for (seat = Seats.begin(); seat != Seats.end(); ++seat)
466 if (seat->second.IsEmpty() && !HasPendingEventForSeat(seat->first) && (seat->second.SeatInfo->CanEnterOrExit() || seat->second.SeatInfo->IsUsableByOverride()))
467 break;
468
469 if (seat == Seats.end()) // no available seat
470 {
471 e->ScheduleAbort();
472 return false;
473 }
474
475 e->Seat = seat;
476 _pendingJoinEvents.push_back(e);
477 }
478 else
479 {
480 seat = Seats.find(seatId);
481 if (seat == Seats.end())
482 {
483 e->ScheduleAbort();
484 return false;
485 }
486
487 e->Seat = seat;
488 _pendingJoinEvents.push_back(e);
489 if (!seat->second.IsEmpty())
490 {
491 Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger.Guid);
492 ASSERT(passenger);
493 passenger->ExitVehicle();
494 }
495
496 ASSERT(seat->second.IsEmpty());
497 }
498
499 return true;
500}
501
514{
515 Unit* unit = passenger->ToUnit();
516 if (!unit)
517 return nullptr;
518
519 if (unit->GetVehicle() != this)
520 return nullptr;
521
522 SeatMap::iterator seat = GetSeatIteratorForPassenger(unit);
523 ASSERT(seat != Seats.end());
524
525 TC_LOG_DEBUG("entities.vehicle", "Unit {} exit vehicle entry {} id {} guid {} seat {}",
526 unit->GetName(), _me->GetEntry(), _vehicleInfo->ID, _me->GetGUID().ToString(), (int32)seat->first);
527
528 if (seat->second.SeatInfo->CanEnterOrExit() && ++UsableSeatNum)
530
531 // Enable gravity for passenger when he did not have it active before entering the vehicle
532 if (seat->second.SeatInfo->Flags & VEHICLE_SEAT_FLAG_DISABLE_GRAVITY && !seat->second.Passenger.IsGravityDisabled)
533 unit->SetDisableGravity(false);
534
535 // Remove UNIT_FLAG_UNINTERACTIBLE if passenger did not have it before entering vehicle
536 if (seat->second.SeatInfo->Flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE && !seat->second.Passenger.IsUninteractible)
537 unit->SetUninteractible(false);
538
539 seat->second.Passenger.Reset();
540
541 if (_me->GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && seat->second.SeatInfo->Flags & VEHICLE_SEAT_FLAG_CAN_CONTROL)
542 _me->RemoveCharmedBy(unit);
543
544 if (_me->IsInWorld())
545 {
546 if (!_me->GetTransport())
548 else
550 }
551
552 // only for flyable vehicles
553 if (unit->IsFlying())
554 {
555 VehicleTemplate const* vehicleTemplate = sObjectMgr->GetVehicleTemplate(this);
556 if (!vehicleTemplate || !vehicleTemplate->CustomFlags.HasFlag(VehicleCustomFlags::DontForceParachuteOnExit))
558 }
559
561 _me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, false);
562
563 if (GetBase()->GetTypeId() == TYPEID_UNIT)
564 sScriptMgr->OnRemovePassenger(this, unit);
565
566 unit->SetVehicle(nullptr);
567 return this;
568}
569
580{
581 ASSERT(_me->GetMap());
582
583 std::vector<std::pair<Unit*, Position>> seatRelocation;
584 seatRelocation.reserve(Seats.size());
585
586 // not sure that absolute position calculation is correct, it must depend on vehicle pitch angle
587 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
588 {
589 if (Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), itr->second.Passenger.Guid))
590 {
591 ASSERT(passenger->IsInWorld());
592
593 seatRelocation.emplace_back(passenger, _me->GetPositionWithOffset(passenger->m_movementInfo.transport.pos));
594 }
595 }
596
597 for (auto const& [passenger, position] : seatRelocation)
598 UpdatePassengerPosition(_me->GetMap(), passenger, position, false);
599}
600
613{
614 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
615 if (!itr->second.IsEmpty())
616 return true;
617
618 return false;
619}
620
622{
623 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
624 if (itr->second.SeatInfo->HasFlag(VEHICLE_SEAT_FLAG_CAN_CONTROL))
625 return true;
626
627 return false;
628}
629
656
671{
672 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
673 if (itr->second.Passenger.Guid == passenger->GetGUID())
674 return itr->second.SeatInfo;
675
676 return nullptr;
677}
678
692SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger)
693{
694 for (SeatMap::iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
695 if (itr->second.Passenger.Guid == passenger->GetGUID())
696 return itr;
697
698 return Seats.end();
699}
700
713{
714 uint8 ret = 0;
715 SeatMap::const_iterator itr;
716 for (itr = Seats.begin(); itr != Seats.end(); ++itr)
717 if (itr->second.IsEmpty() && !HasPendingEventForSeat(itr->first) && (itr->second.SeatInfo->CanEnterOrExit() || itr->second.SeatInfo->IsUsableByOverride()))
718 ++ret;
719
720 return ret;
721}
722
737{
738 for (PendingJoinEventContainer::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end(); ++itr)
739 {
740 if (*itr == e)
741 {
742 _pendingJoinEvents.erase(itr);
743 break;
744 }
745 }
746}
747
760{
761 for (PendingJoinEventContainer::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end();)
762 {
763 if ((*itr)->Seat->first == seatId)
764 {
765 (*itr)->ScheduleAbort();
766 _pendingJoinEvents.erase(itr++);
767 }
768 else
769 ++itr;
770 }
771}
772
785{
786 for (PendingJoinEventContainer::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end();)
787 {
788 if ((*itr)->Passenger == passenger)
789 {
790 (*itr)->ScheduleAbort();
791 _pendingJoinEvents.erase(itr++);
792 }
793 else
794 ++itr;
795 }
796}
797
814{
817
819 auto itr = std::find_if(vehicleAuras.begin(), vehicleAuras.end(), [this](AuraEffect const* aurEff) -> bool
820 {
821 return aurEff->GetCasterGUID() == Passenger->GetGUID();
822 });
823 ASSERT(itr != vehicleAuras.end());
824
825 AuraApplication const* aurApp = (*itr)->GetBase()->GetApplicationOfTarget(Target->GetBase()->GetGUID());
826 ASSERT(aurApp && !aurApp->GetRemoveMode());
827
830
831 // Passenger might've died in the meantime - abort if this is the case
832 if (!Passenger->IsAlive())
833 {
834 Abort(0);
835 return true;
836 }
837
838 //It's possible that multiple vehicle join
839 //events are executed in the same update
840 if (Passenger->GetVehicle())
842
844 Seat->second.Passenger.Guid = Passenger->GetGUID();
845 Seat->second.Passenger.IsUninteractible = Passenger->IsUninteractible();
846 Seat->second.Passenger.IsGravityDisabled = Passenger->HasUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
847 if (Seat->second.SeatInfo->CanEnterOrExit())
848 {
851 if (!Target->UsableSeatNum)
852 {
855 else
857 }
858 }
859
864
865 VehicleSeatEntry const* veSeat = Seat->second.SeatInfo;
866 VehicleSeatAddon const* veSeatAddon = Seat->second.SeatAddon;
867
868 Player* player = Passenger->ToPlayer();
869 if (player)
870 {
871 player->StopCastingCharm();
872 player->StopCastingBindSight();
876 }
877
880
881 float o = veSeatAddon ? veSeatAddon->SeatOrientationOffset : 0.f;
882 float x = veSeat->AttachmentOffset.X;
883 float y = veSeat->AttachmentOffset.Y;
884 float z = veSeat->AttachmentOffset.Z;
885
891
893 Seat->second.SeatInfo->HasFlag(VEHICLE_SEAT_FLAG_CAN_CONTROL))
894 {
895 // handles SMSG_CLIENT_CONTROL
897 {
898 // charming failed, probably aura was removed by relocation/scripts/whatever
899 Abort(0);
900 return true;
901 }
902 }
903
904 Passenger->SendClearTarget(); // SMSG_BREAK_TARGET
905 Passenger->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
906 // also adds MOVEMENTFLAG_ROOT
907
908 std::function<void(Movement::MoveSplineInit&)> initializer = [=](Movement::MoveSplineInit& init)
909 {
910 init.DisableTransportPathTransformations();
911 init.MoveTo(x, y, z, false, true);
912 init.SetFacing(o);
913 init.SetTransportEnter();
914 };
916
917 for (auto const& [guid, threatRef] : Passenger->GetThreatManager().GetThreatenedByMeList())
918 threatRef->GetOwner()->GetThreatManager().AddThreat(Target->GetBase(), 0.0f, nullptr, true, true);
919
920 if (Creature* creature = Target->GetBase()->ToCreature())
921 {
922 if (CreatureAI* ai = creature->AI())
923 ai->PassengerBoarded(Passenger, Seat->first, true);
924
925 sScriptMgr->OnAddPassenger(Target, Passenger, Seat->first);
926
927 // Actually quite a redundant hook. Could just use OnAddPassenger and check for unit typemask inside script.
929 sScriptMgr->OnInstallAccessory(Target, Passenger->ToCreature());
930 }
931
932 return true;
933}
934
947{
949 if (Target)
950 {
951 TC_LOG_DEBUG("entities.vehicle", "Passenger {}, board on vehicle {} SeatId: {} cancelled",
953
956
961 }
962 else
963 TC_LOG_DEBUG("entities.vehicle", "Passenger {}, board on uninstalled vehicle SeatId: {} cancelled",
964 Passenger->GetGUID().ToString(), (int32)Seat->first);
965
968}
969
971{
972 for (PendingJoinEventContainer::const_iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end(); ++itr)
973 {
974 if ((*itr)->Seat->first == seatId)
975 return true;
976 }
977 return false;
978}
979
981{
982 if (VehicleTemplate const* vehicleTemplate = sObjectMgr->GetVehicleTemplate(this))
983 return vehicleTemplate->DespawnDelay;
984
985 return 1ms;
986}
987
989{
990 if (VehicleTemplate const* vehicleTemplate = sObjectMgr->GetVehicleTemplate(this))
991 if (vehicleTemplate->Pitch)
992 return *vehicleTemplate->Pitch;
993
994 return std::clamp(0.0f, _vehicleInfo->PitchMin, _vehicleInfo->PitchMax);
995}
996
997std::string Vehicle::GetDebugInfo() const
998{
999 std::stringstream sstr;
1000 sstr << "Vehicle seats:\n";
1001 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); itr++)
1002 {
1003 sstr << "seat " << std::to_string(itr->first) << ": " << (itr->second.IsEmpty() ? "empty" : itr->second.Passenger.Guid.ToString()) << "\n";
1004 }
1005
1006 sstr << "Vehicle pending events:";
1007
1008 if (_pendingJoinEvents.empty())
1009 {
1010 sstr << " none";
1011 }
1012 else
1013 {
1014 sstr << "\n";
1015 for (PendingJoinEventContainer::const_iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end(); ++itr)
1016 {
1017 sstr << "seat " << std::to_string((*itr)->Seat->first) << ": " << (*itr)->Passenger->GetGUID().ToString() << "\n";
1018 }
1019 }
1020
1021 return sstr.str();
1022}
1023
@ STATUS_NONE
@ CHARM_TYPE_VEHICLE
Definition CharmInfo.h:71
DB2Storage< VehicleSeatEntry > sVehicleSeatStore("VehicleSeat.db2", &VehicleSeatLoadInfo::Instance)
#define MAX_VEHICLE_SEATS
@ VEHICLE_SEAT_FLAG_DISABLE_GRAVITY
Definition DBCEnums.h:3094
@ VEHICLE_SEAT_FLAG_CAN_CONTROL
Definition DBCEnums.h:3103
@ VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE
Definition DBCEnums.h:3112
@ VEHICLE_SEAT_FLAG_B_KEEP_PET
Definition DBCEnums.h:3135
uint8_t uint8
Definition Define.h:156
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
uint32_t uint32
Definition Define.h:154
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
#define ASSERT
Definition Errors.h:80
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
@ MOTION_PRIORITY_HIGHEST
TempSummonType
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
#define sObjectMgr
Definition ObjectMgr.h:1885
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
#define sScriptMgr
Definition ScriptMgr.h:1449
@ EVENT_VEHICLE_BOARD
@ CREATURE_TYPE_MECHANICAL
@ SPELL_EFFECT_HEAL
@ SPELL_EFFECT_DISPEL
@ SPELL_EFFECT_KNOCK_BACK_DEST
@ SPELL_EFFECT_KNOCK_BACK
@ SPELL_EFFECT_HEAL_PCT
@ MECHANIC_BANISH
@ MECHANIC_IMMUNE_SHIELD
@ MECHANIC_SHIELD
@ IMMUNITY_STATE
@ IMMUNITY_EFFECT
@ IMMUNITY_MECHANIC
@ SPELL_AURA_DAMAGE_SHIELD
@ SPELL_AURA_MOD_RESISTANCE
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_PERIODIC_HEAL
@ SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
@ SPELL_AURA_SPLIT_DAMAGE_PCT
@ SPELL_AURA_MOD_STAT
@ SPELL_AURA_SCHOOL_IMMUNITY
@ SPELL_AURA_MOUNTED
@ SPELL_AURA_MOD_DECREASE_SPEED
@ SPELL_AURA_SCHOOL_ABSORB
@ SPELL_AURA_MOD_UNATTACKABLE
@ MOVEMENTFLAG_DISABLE_GRAVITY
@ MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING
@ MOVEMENTFLAG2_NO_STRAFE
@ MOVEMENTFLAG2_FULL_SPEED_PITCHING
@ MOVEMENTFLAG2_FULL_SPEED_TURNING
@ MOVEMENTFLAG2_NO_JUMPING
@ UNIT_NPC_FLAG_SPELLCLICK
@ UNIT_NPC_FLAG_PLAYER_VEHICLE
@ UNIT_MASK_ACCESSORY
Definition Unit.h:365
@ UNIT_MASK_MINION
Definition Unit.h:357
@ CURRENT_GENERIC_SPELL
Definition Unit.h:598
@ CURRENT_AUTOREPEAT_SPELL
Definition Unit.h:600
@ UNIT_STATE_ROOT
Definition Unit.h:271
@ VEHICLE_SPELL_PARACHUTE
@ VEHICLE_FLAG_NO_JUMPING
@ VEHICLE_FLAG_NO_STRAFE
@ VEHICLE_FLAG_FULLSPEEDTURNING
@ VEHICLE_FLAG_ALLOW_PITCHING
@ VEHICLE_FLAG_FULLSPEEDPITCHING
std::vector< VehicleAccessory > VehicleAccessoryList
Aura * GetBase() const
Definition SpellAuras.h:82
AuraRemoveMode GetRemoveMode() const
Definition SpellAuras.h:96
AuraApplication const * GetApplicationOfTarget(ObjectGuid guid) const
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
bool IsInWorld() const
Definition BaseEntity.h:158
TypeID GetTypeId() const
Definition BaseEntity.h:166
void ScheduleAbort()
virtual void PassengerBoarded(Unit *, int8, bool)
== Fields =======================================
Definition CreatureAI.h:228
bool isWorldBoss() const
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
ObjectGuid::LowType GetSpawnId() const
Definition Creature.h:110
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:266
CreatureAI * AI() const
Definition Creature.h:228
constexpr bool HasFlag(T flag) const
Definition EnumFlag.h:106
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
Milliseconds CalculateTime(Milliseconds t_offset) const
void LaunchMoveSpline(std::function< void(Movement::MoveSplineInit &init)> &&initializer, uint32 id=0, MovementGeneratorPriority priority=MOTION_PRIORITY_NORMAL, MovementGeneratorType type=EFFECT_MOTION_TYPE, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
std::string ToString() const
Player * ToPlayer()
Definition Object.h:126
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
Unit * ToUnit()
Definition Object.h:116
void StopCastingBindSight() const
Definition Player.cpp:26913
void UnsummonPetTemporaryIfAny()
Definition Player.cpp:27985
void StopCastingCharm()
Definition Player.cpp:22269
void SendOnCancelExpectedVehicleRideAura() const
Definition Player.cpp:22466
auto const & GetThreatenedByMeList() const
void UpdatePassengerPosition(Map *map, WorldObject *passenger, Position const &position, bool setHomePosition)
Definition Transport.cpp:36
Trinity::unique_trackable_ptr companion class, replicating what std::weak_ptr is to std::shared_ptr.
Definition Unit.h:635
void ApplySpellImmune(uint32 spellId, SpellImmunity op, uint32 type, bool apply)
Definition Unit.cpp:8242
Vehicle * GetVehicle() const
Definition Unit.h:1784
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3955
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1342
void AddExtraUnitMovementFlag(uint32 f)
Definition Unit.h:1738
ThreatManager & GetThreatManager()
Definition Unit.h:1078
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11545
void HandleSpellClick(Unit *clicker, int8 seatId=-1)
Definition Unit.cpp:12636
void SendClearTarget()
Definition Unit.cpp:13192
std::forward_list< AuraEffect * > AuraEffectList
Definition Unit.h:652
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
bool IsAlive() const
Definition Unit.h:1185
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:998
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13361
void SetUninteractible(bool apply)
Definition Unit.cpp:8564
Trinity::unique_weak_ptr< Vehicle > GetVehicleKitWeakPtr() const
Definition Unit.h:1783
bool IsAIEnabled() const
Definition Unit.h:666
bool HasUnitMovementFlag(uint32 f) const
Definition Unit.h:1734
void SetNpcFlag(NPCFlags flags)
Definition Unit.h:997
void RemoveAurasWithInterruptFlags(InterruptFlags flag, SpellInfo const *source=nullptr)
Definition Unit.cpp:4241
void RemoveCharmedBy(Unit *charmer)
Definition Unit.cpp:11946
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1881
void SetVehicle(Vehicle *vehicle)
Definition Unit.h:1785
uint32 HasUnitTypeMask(uint32 mask) const
Definition Unit.h:747
bool SetCharmedBy(Unit *charmer, CharmType type, AuraApplication const *aurApp=nullptr)
Definition Unit.cpp:11773
bool IsFlying() const
Definition Unit.h:1807
bool IsUninteractible() const
Definition Unit.h:1052
void AddUnitTypeMask(uint32 mask)
Definition Unit.h:748
void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed=true, bool withInstant=true)
Definition Unit.cpp:3159
virtual void ExitVehicle(Position const *exitPosition=nullptr)
Definition Unit.cpp:12835
bool Execute(uint64, uint32) override
Actually adds the passenger @Passenger to vehicle @Target.
Definition Vehicle.cpp:813
SeatMap::iterator Seat
Definition Vehicle.cpp:46
Vehicle * Target
Definition Vehicle.cpp:44
void Abort(uint64) override
Aborts the event. Implies that unit @Passenger will not be boarding vehicle @Target after all.
Definition Vehicle.cpp:946
VehicleJoinEvent(Vehicle *v, Unit *u)
Definition Vehicle.cpp:40
Vehicle(Unit *unit, VehicleEntry const *vehInfo, uint32 creatureEntry)
Definition Vehicle.cpp:49
uint8 GetAvailableSeatCount() const
Gets the available seat count.
Definition Vehicle.cpp:712
Unit * GetBase() const
Definition Vehicle.h:49
Unit * GetPassenger(int8 seatId) const
Gets a passenger on specified seat.
Definition Vehicle.cpp:303
void ApplyAllImmunities()
Applies specific immunities that cannot be set in DB.
Definition Vehicle.cpp:173
Vehicle * RemovePassenger(WorldObject *passenger) override
Removes the passenger from the vehicle.
Definition Vehicle.cpp:513
void RemovePendingEvent(VehicleJoinEvent *e)
Removes @VehicleJoinEvent objects from pending join event store. This method only removes it after it...
Definition Vehicle.cpp:736
SeatMap::iterator GetSeatIteratorForPassenger(Unit *passenger)
Gets seat iterator for specified passenger.
Definition Vehicle.cpp:692
VehicleEntry const * GetVehicleInfo() const
Definition Vehicle.h:50
void Reset(bool evading=false)
Reapplies immunities and reinstalls accessories. Only has effect for creatures.
Definition Vehicle.cpp:150
void InitMovementInfoForBase()
Sets correct MovementFlags2 based on VehicleFlags from DBC.
Definition Vehicle.cpp:639
@ STATUS_INSTALLED
Definition Vehicle.h:88
@ STATUS_UNINSTALLING
Definition Vehicle.h:89
uint32 GetCreatureEntry() const
Definition Vehicle.h:51
void RemoveAllPassengers()
Removes all current and pending passengers from the vehicle.
Definition Vehicle.cpp:238
~Vehicle()
Definition Vehicle.cpp:73
bool IsVehicleInUse() const
Returns information whether the vehicle is currently used by any unit.
Definition Vehicle.cpp:612
uint32 UsableSeatNum
Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags.
Definition Vehicle.h:82
uint32 _creatureEntry
Can be different than the entry of _me in case of players.
Definition Vehicle.h:118
Status _status
Internal variable for sanity checks.
Definition Vehicle.h:119
void Uninstall()
Removes all passengers and sets status to STATUS_UNINSTALLING. No new passengers can be added to the ...
Definition Vehicle.cpp:121
void RemovePendingEventsForSeat(int8 seatId)
Removes any pending events for given seatId. Executed when a @VehicleJoinEvent::Execute is called.
Definition Vehicle.cpp:759
Unit * _me
The underlying unit with the vehicle kit. Can be player or creature.
Definition Vehicle.h:114
bool HasEmptySeat(int8 seatId) const
Checks if vehicle's seat specified by 'seatId' is empty.
Definition Vehicle.cpp:282
PendingJoinEventContainer _pendingJoinEvents
Collection of delayed join events for prospective passengers.
Definition Vehicle.h:122
Trinity::unique_weak_ptr< Vehicle > GetWeakPtr() const
Definition Vehicle.cpp:1024
VehicleSeatEntry const * GetSeatForPassenger(Unit const *passenger) const
Returns information on the seat of specified passenger, represented by the format in VehicleSeat....
Definition Vehicle.cpp:670
void Install()
Initializes power type for vehicle. Nothing more.
Definition Vehicle.cpp:90
bool IsControllableVehicle() const
Definition Vehicle.cpp:621
void RelocatePassengers()
Relocate passengers. Must be called after m_base::Relocate.
Definition Vehicle.cpp:579
bool HasPendingEventForSeat(int8 seatId) const
Definition Vehicle.cpp:970
SeatMap Seats
The collection of all seats on the vehicle. Including vacant ones.
Definition Vehicle.h:67
std::string GetDebugInfo() const
Definition Vehicle.cpp:997
SeatMap::const_iterator GetNextEmptySeat(int8 seatId, bool next) const
Gets the next empty seat based on current seat.
Definition Vehicle.cpp:326
float GetPitch()
Definition Vehicle.cpp:988
VehicleSeatAddon const * GetSeatAddonForSeatOfPassenger(Unit const *passenger) const
Gets the vehicle seat addon data for the seat of a passenger.
Definition Vehicle.cpp:370
friend class VehicleJoinEvent
Definition Vehicle.h:81
Milliseconds GetDespawnDelay()
Definition Vehicle.cpp:980
void RemovePendingEventsForPassenger(Unit *passenger)
Definition Vehicle.cpp:784
VehicleEntry const * _vehicleInfo
DBC data for vehicle.
Definition Vehicle.h:115
void InstallAllAccessories(bool evading)
Definition Vehicle.cpp:97
void InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type, uint32 summonTime, Optional< uint32 > rideSpellId={})
Installs an accessory.
Definition Vehicle.cpp:396
bool AddVehiclePassenger(Unit *unit, int8 seatId=-1)
Definition Vehicle.cpp:442
Map * GetMap() const
Definition Object.h:411
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2217
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1398
TransportBase * GetTransport() const
Definition Object.h:537
std::string const & GetName() const
Definition Object.h:342
EventProcessor m_Events
Definition Object.h:561
MovementInfo m_movementInfo
Definition Object.h:548
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
void ResetTransport()
struct MovementInfo::TransportInfo transport
Position GetPositionWithOffset(Position const &offset) const
Definition Position.cpp:61
constexpr void Relocate(float x, float y)
Definition Position.h:74
std::array< uint16, 8 > SeatID
bool HasFlag(VehicleSeatFlags flag) const
DBCPosition3D AttachmentOffset
EnumFlag< VehicleCustomFlags > CustomFlags