Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Vehicle.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Battleground.h"
7#include "Common.h"
8#include "CreatureAI.h"
9#include "EventProcessor.h"
10#include "Log.h"
11#include "MoveSplineInit.h"
12#include "ObjectMgr.h"
13#include "Player.h"
14#include "ScriptMgr.h"
15#include "SpellInfo.h"
16#include "SpellMgr.h"
17#include "TemporarySummon.h"
18#include "Unit.h"
19#include "Util.h"
20#include "Vehicle.h"
21#include "WorldPacket.h"
22#include "ZoneScript.h"
23
24Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) :
25 UsableSeatNum(0), _me(unit), _vehicleInfo(vehInfo), _creatureEntry(creatureEntry), _status(STATUS_NONE)
26{
27 for (uint32 i = 0; i < MAX_VEHICLE_SEATS; ++i)
28 {
29 if (uint32 seatId = _vehicleInfo->m_seatID[i])
30 if (VehicleSeatEntry const* veSeat = sVehicleSeatStore.LookupEntry(seatId))
31 {
32 Seats.insert(std::make_pair(i, VehicleSeat(veSeat)));
33 if (veSeat->CanEnterOrExit())
35 }
36 }
37
38 // Set or remove correct flags based on available seats. Will overwrite db data (if wrong).
39 if (UsableSeatNum)
41 else
43
45}
46
48{
51 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
52 ASSERT(itr->second.IsEmpty());
53}
54
63
65{
66 if (Creature* creature = _me->ToCreature())
67 {
68 switch (_vehicleInfo->m_powerType)
69 {
70 case POWER_STEAM:
71 case POWER_HEAT:
72 case POWER_BLOOD:
73 case POWER_OOZE:
74 case POWER_WRATH:
75 _me->setPowerType(POWER_ENERGY);
76 _me->SetMaxPower(POWER_ENERGY, 100);
77 break;
78 case POWER_PYRITE:
79 _me->setPowerType(POWER_ENERGY);
80 _me->SetMaxPower(POWER_ENERGY, 50);
81 break;
82 default:
83 /*
84 for (uint32 i = 0; i < MAX_SPELL_VEHICLE; ++i)
85 {
86 if (!creature->m_spells[i])
87 continue;
88
89 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(creature->m_spells[i]);
90 if (!spellInfo)
91 continue;
92
93 if (spellInfo->PowerType == POWER_ENERGY)
94 {
95 _me->setPowerType(POWER_ENERGY);
96 _me->SetMaxPower(POWER_ENERGY, 100);
97 break;
98 }
99 }*/
100 break;
101 }
102 }
103
105 if (GetBase()->GetTypeId() == TypeID::TYPEID_UNIT)
106 sScriptMgr->OnInstall(this);
107}
108
110{
111 if (GetBase()->GetTypeId() == TypeID::TYPEID_PLAYER || !evading)
112 RemoveAllPassengers(); // We might have aura's saved in the DB with now invalid casters - remove
113
114 VehicleAccessoryList const* accessories = sObjectMgr->GetVehicleAccessoryList(this);
115 if (!accessories)
116 return;
117
118 for (VehicleAccessoryList::const_iterator itr = accessories->begin(); itr != accessories->end(); ++itr)
119 if (!evading || itr->IsMinion) // only install minions on evade mode
120 InstallAccessory(itr->AccessoryEntry, itr->SeatId, itr->IsMinion, TempSummonType(itr->SummonedType), itr->SummonTime);
121}
122
132
134{
136 if (_status == STATUS_UNINSTALLING && !GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
137 {
138 SF_LOG_ERROR("entities.vehicle", "Vehicle GuidLow: %u, Entry: %u attempts to uninstall, but already has STATUS_UNINSTALLING! "
139 "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry());
140 return;
141 }
142
144 SF_LOG_DEBUG("entities.vehicle", "Vehicle::Uninstall Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow());
146
147 if (GetBase()->GetTypeId() == TypeID::TYPEID_UNIT)
148 sScriptMgr->OnUninstall(this);
149}
150
161
162void Vehicle::Reset(bool evading /*= false*/)
163{
164 if (GetBase()->GetTypeId() != TypeID::TYPEID_UNIT)
165 return;
166
167 SF_LOG_DEBUG("entities.vehicle", "Vehicle::Reset (Entry: %u, GuidLow: %u, DBGuid: %u)", GetCreatureEntry(), _me->GetGUIDLow(), _me->ToCreature()->GetDBTableGUIDLow());
168
170 InstallAllAccessories(evading);
171
172 sScriptMgr->OnReset(this);
173}
174
183
185{
186 // This couldn't be done in DB, because some spells have MECHANIC_NONE
187
188 // Vehicles should be immune on Knockback ...
189 _me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true);
190 _me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK_DEST, true);
191
192 // Mechanical units & vehicles ( which are not Bosses, they have own immunities in DB ) should be also immune on healing ( exceptions in switch below )
193 if (_me->ToCreature() && _me->ToCreature()->GetCreatureTemplate()->type == CREATURE_TYPE_MECHANICAL && !_me->ToCreature()->isWorldBoss())
194 {
195 // Heal & dispel ...
196 _me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_HEAL, true);
197 _me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_HEAL_PCT, true);
198 _me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_DISPEL, true);
199 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_PERIODIC_HEAL, true);
200
201 // ... Shield & Immunity grant spells ...
202 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_SCHOOL_IMMUNITY, true);
203 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_UNATTACKABLE, true);
204 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_SCHOOL_ABSORB, true);
205 _me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_SHIELD, true);
206 _me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_IMMUNE_SHIELD, true);
207
208 // ... Resistance, Split damage, Change stats ...
209 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_DAMAGE_SHIELD, true);
210 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_SPLIT_DAMAGE_PCT, true);
211 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_RESISTANCE, true);
212 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_STAT, true);
213 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, true);
214 }
215
216 // Different immunities for vehicles goes below
217 switch (GetVehicleInfo()->m_ID)
218 {
219 // code below prevents a bug with movable cannons
220 case 160: // Strand of the Ancients
221 case 244: // Wintergrasp
222 case 510: // Isle of Conquest
223 _me->SetControlled(true, UNIT_STATE_ROOT);
224 // why we need to apply this? we can simple add immunities to slow mechanic in DB
225 _me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_DECREASE_SPEED, true);
226 break;
227 default:
228 break;
229 }
230}
231
240
242{
243 SF_LOG_DEBUG("entities.vehicle", "Vehicle::RemoveAllPassengers. Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow());
244
247 {
249 Vehicle* eventVehicle = _status != STATUS_UNINSTALLING ? this : NULL;
250
251 while (!_pendingJoinEvents.empty())
252 {
254 e->to_Abort = true;
255 e->Target = eventVehicle;
256 _pendingJoinEvents.pop_front();
257 }
258 }
259
260 // Passengers always cast an aura with SPELL_AURA_CONTROL_VEHICLE on the vehicle
261 // We just remove the aura and the unapply handler will make the target leave the vehicle.
262 // We don't need to iterate over Seats
263 _me->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE);
264
265 // Following the above logic, this assertion should NEVER fail.
266 // Even in 'hacky' cases, there should at least be VEHICLE_SPELL_RIDE_HARDCODED on us.
267 // SeatMap::const_iterator itr;
268 // for (itr = Seats.begin(); itr != Seats.end(); ++itr)
269 // ASSERT(!itr->second.passenger);
270}
271
284
285bool Vehicle::HasEmptySeat(int8 seatId) const
286{
287 SeatMap::const_iterator seat = Seats.find(seatId);
288 if (seat == Seats.end())
289 return false;
290 return seat->second.IsEmpty();
291}
292
305
307{
308 SeatMap::const_iterator seat = Seats.find(seatId);
309 if (seat == Seats.end())
310 return NULL;
311
312 return ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger.Guid);
313}
314
328
329SeatMap::const_iterator Vehicle::GetNextEmptySeat(int8 seatId, bool next) const
330{
331 SeatMap::const_iterator seat = Seats.find(seatId);
332 if (seat == Seats.end())
333 return seat;
334
335 while (!seat->second.IsEmpty() || (!seat->second.SeatInfo->CanEnterOrExit() && !seat->second.SeatInfo->IsUsableByOverride()))
336 {
337 if (next)
338 {
339 if (++seat == Seats.end())
340 seat = Seats.begin();
341 }
342 else
343 {
344 if (seat == Seats.begin())
345 seat = Seats.end();
346 --seat;
347 }
348
349 // Make sure we don't loop indefinetly
350 if (seat->first == seatId)
351 return Seats.end();
352 }
353
354 return seat;
355}
356
373
374void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, TempSummonType type, uint32 summonTime)
375{
378 {
379 SF_LOG_ERROR("entities.vehicle", "Vehicle (GuidLow: %u, DB GUID: %u, Entry: %u) attempts to install accessory (Entry: %u) on seat %d with STATUS_UNINSTALLING! "
380 "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(),
381 (_me->GetTypeId() == TypeID::TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(), entry, (int32)seatId);
382 return;
383 }
384
385 SF_LOG_DEBUG("entities.vehicle", "Vehicle (GuidLow: %u, DB Guid: %u, Entry %u): installing accessory (Entry: %u) on seat: %d",
386 _me->GetGUIDLow(), (_me->GetTypeId() == TypeID::TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(),
387 entry, (int32)seatId);
388
389 TempSummon* accessory = _me->SummonCreature(entry, *_me, type, summonTime);
390 ASSERT(accessory);
391
392 if (minion)
394
395 (void)_me->HandleSpellClick(accessory, seatId);
396
399}
400
414
415bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
416{
419 {
420 SF_LOG_ERROR("entities.vehicle", "Passenger GuidLow: %u, Entry: %u, attempting to board vehicle GuidLow: %u, Entry: %u during uninstall! SeatId: %d",
421 unit->GetGUIDLow(), unit->GetEntry(), _me->GetGUIDLow(), _me->GetEntry(), (int32)seatId);
422 return false;
423 }
424
425 SF_LOG_DEBUG("entities.vehicle", "Unit %s scheduling enter vehicle (entry: %u, vehicleId: %u, guid: %u (dbguid: %u) on seat %d",
426 unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(),
427 (_me->GetTypeId() == TypeID::TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : 0), (int32)seatId);
428
429 // The seat selection code may kick other passengers off the vehicle.
430 // While the validity of the following may be arguable, it is possible that when such a passenger
431 // exits the vehicle will dismiss. That's why the actual adding the passenger to the vehicle is scheduled
432 // asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile.
433 SeatMap::iterator seat;
434 VehicleJoinEvent* e = new VehicleJoinEvent(this, unit);
435 unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0));
436
437 if (seatId < 0) // no specific seat requirement
438 {
439 for (seat = Seats.begin(); seat != Seats.end(); ++seat)
440 if (seat->second.IsEmpty() && (seat->second.SeatInfo->CanEnterOrExit() || seat->second.SeatInfo->IsUsableByOverride()))
441 break;
442
443 if (seat == Seats.end()) // no available seat
444 {
445 e->to_Abort = true;
446 return false;
447 }
448
449 e->Seat = seat;
450 _pendingJoinEvents.push_back(e);
451 }
452 else
453 {
454 seat = Seats.find(seatId);
455 if (seat == Seats.end())
456 {
457 e->to_Abort = true;
458 return false;
459 }
460
461 e->Seat = seat;
462 _pendingJoinEvents.push_back(e);
463 if (!seat->second.IsEmpty())
464 {
465 Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger.Guid);
466 ASSERT(passenger);
467 passenger->ExitVehicle();
468 }
469
470 ASSERT(seat->second.IsEmpty());
471 }
472
473 return true;
474}
475
486
488{
489 if (unit->GetVehicle() != this)
490 return NULL;
491
492 SeatMap::iterator seat = GetSeatIteratorForPassenger(unit);
493 ASSERT(seat != Seats.end());
494
495 SF_LOG_DEBUG("entities.vehicle", "Unit %s exit vehicle entry %u id %u dbguid %u seat %d",
496 unit->GetName().c_str(), _me->GetEntry(), _vehicleInfo->m_ID, _me->GetGUIDLow(), (int32)seat->first);
497
498 if (seat->second.SeatInfo->CanEnterOrExit() && ++UsableSeatNum)
500
501 // Remove UNIT_FLAG_NOT_SELECTABLE if passenger did not have it before entering vehicle
502 if (seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE && !seat->second.Passenger.IsUnselectable)
504
505 seat->second.Passenger.Reset();
506
507 if (_me->GetTypeId() == TypeID::TYPEID_UNIT && unit->GetTypeId() == TypeID::TYPEID_PLAYER && seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL)
508 _me->RemoveCharmedBy(unit);
509
510 if (_me->IsInWorld())
512
513 // only for flyable vehicles
514 if (unit->IsFlying())
515 _me->CastSpell(unit, VEHICLE_SPELL_PARACHUTE, true);
516
517 if (_me->GetTypeId() == TypeID::TYPEID_UNIT && _me->ToCreature()->IsAIEnabled)
518 _me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, false);
519
520 if (GetBase()->GetTypeId() == TypeID::TYPEID_UNIT)
521 sScriptMgr->OnRemovePassenger(this, unit);
522
523 unit->SetVehicle(NULL);
524 return this;
525}
526
535
537{
538 ASSERT(_me->GetMap());
539
540 // not sure that absolute position calculation is correct, it must depend on vehicle pitch angle
541 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
542 {
543 if (Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), itr->second.Passenger.Guid))
544 {
545 ASSERT(passenger->IsInWorld());
546
547 float px, py, pz, po;
548 passenger->m_movementInfo.transport.pos.GetPosition(px, py, pz, po);
549 CalculatePassengerPosition(px, py, pz, &po);
550
551 passenger->UpdatePosition(px, py, pz, po);
552 }
553 }
554}
555
566
568{
569 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
570 if (!itr->second.IsEmpty())
571 return true;
572
573 return false;
574}
575
584
586{
587 uint32 vehicleFlags = GetVehicleInfo()->m_flags;
588
589 if (vehicleFlags & VEHICLE_FLAG_NO_STRAFE)
590 _me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_NO_STRAFE);
591 if (vehicleFlags & VEHICLE_FLAG_NO_JUMPING)
592 _me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_NO_JUMPING);
593 if (vehicleFlags & VEHICLE_FLAG_FULLSPEEDTURNING)
594 _me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_FULL_SPEED_TURNING);
595 if (vehicleFlags & VEHICLE_FLAG_ALLOW_PITCHING)
596 _me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING);
597 if (vehicleFlags & VEHICLE_FLAG_FULLSPEEDPITCHING)
598 _me->AddExtraUnitMovementFlag(MOVEMENTFLAG2_FULL_SPEED_PITCHING);
599}
600
613
615{
616 for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr)
617 if (itr->second.Passenger.Guid == passenger->GetGUID())
618 return itr->second.SeatInfo;
619
620 return NULL;
621}
622
635
636SeatMap::iterator Vehicle::GetSeatIteratorForPassenger(Unit* passenger)
637{
638 SeatMap::iterator itr;
639 for (itr = Seats.begin(); itr != Seats.end(); ++itr)
640 if (itr->second.Passenger.Guid == passenger->GetGUID())
641 return itr;
642
643 return Seats.end();
644}
645
656
658{
659 uint8 ret = 0;
660 SeatMap::const_iterator itr;
661 for (itr = Seats.begin(); itr != Seats.end(); ++itr)
662 if (itr->second.IsEmpty() && (itr->second.SeatInfo->CanEnterOrExit() || itr->second.SeatInfo->IsUsableByOverride()))
663 ++ret;
664
665 return ret;
666}
667
680
682{
683 for (PendingJoinEventContainer::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end(); ++itr)
684 {
685 if (*itr == e)
686 {
687 _pendingJoinEvents.erase(itr);
688 break;
689 }
690 }
691}
692
703
705{
706 for (PendingJoinEventContainer::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end();)
707 {
708 if ((*itr)->Seat->first == seatId)
709 {
710 (*itr)->to_Abort = true;
711 _pendingJoinEvents.erase(itr++);
712 }
713 else
714 ++itr;
715 }
716}
717
728
730{
731 for (PendingJoinEventContainer::iterator itr = _pendingJoinEvents.begin(); itr != _pendingJoinEvents.end();)
732 {
733 if ((*itr)->Passenger == passenger)
734 {
735 (*itr)->to_Abort = true;
736 _pendingJoinEvents.erase(itr++);
737 }
738 else
739 ++itr;
740 }
741}
742
744{
745 if (Target)
746 Target->RemovePendingEvent(this);
747}
748
763
765{
766 ASSERT(Passenger->IsInWorld());
767 ASSERT(Target && Target->GetBase()->IsInWorld());
768 ASSERT(Target->GetBase()->HasAuraTypeWithCaster(SPELL_AURA_CONTROL_VEHICLE, Passenger->GetGUID()));
769
770 Target->RemovePendingEventsForSeat(Seat->first);
771 Target->RemovePendingEventsForPassenger(Passenger);
772
773 Passenger->SetVehicle(Target);
774 Seat->second.Passenger.Guid = Passenger->GetGUID();
775 Seat->second.Passenger.IsUnselectable = Passenger->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
776 if (Seat->second.SeatInfo->CanEnterOrExit())
777 {
778 ASSERT(Target->UsableSeatNum);
779 --(Target->UsableSeatNum);
780 if (!Target->UsableSeatNum)
781 {
782 if (Target->GetBase()->GetTypeId() == TypeID::TYPEID_PLAYER)
784 else
786 }
787 }
788
789 Passenger->InterruptNonMeleeSpells(false);
790 Passenger->RemoveAurasByType(SPELL_AURA_MOUNTED);
791
792 Player* player = Passenger->ToPlayer();
793 if (player)
794 {
795 // drop flag
796 if (Battleground* bg = player->GetBattleground())
797 bg->EventPlayerDroppedFlag(player);
798
799 player->StopCastingCharm();
800 player->StopCastingBindSight();
803 }
804
805 if (Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE)
807
808 VehicleSeatEntry const* veSeat = Seat->second.SeatInfo;
809 Passenger->m_movementInfo.transport.pos.Relocate(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ);
810 Passenger->m_movementInfo.transport.time = 0;
811 Passenger->m_movementInfo.transport.seat = Seat->first;
812 Passenger->m_movementInfo.transport.guid = Target->GetBase()->GetGUID();
813
814 if (Target->GetBase()->GetTypeId() == TypeID::TYPEID_UNIT && Passenger->GetTypeId() == TypeID::TYPEID_PLAYER &&
815 Seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL)
816 ASSERT(Target->GetBase()->SetCharmedBy(Passenger, CHARM_TYPE_VEHICLE)); // SMSG_CLIENT_CONTROL
817
818 Passenger->SendClearTarget(); // SMSG_BREAK_TARGET
819 Passenger->SetDisableGravity(true); // SMSG_MOVE_GRAVITY_DISABLE
820 Passenger->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
821 // also adds MOVEMENTFLAG_ROOT
822
825 init.MoveTo(veSeat->m_attachmentOffsetX, veSeat->m_attachmentOffsetY, veSeat->m_attachmentOffsetZ, false, true);
826 init.SetFacing(0.0f);
827 init.SetTransportEnter();
828 init.Launch();
829
830 if (Creature* creature = Target->GetBase()->ToCreature())
831 {
832 if (creature->IsAIEnabled)
833 creature->AI()->PassengerBoarded(Passenger, Seat->first, true);
834
835 sScriptMgr->OnAddPassenger(Target, Passenger, Seat->first);
836
837 // Actually quite a redundant hook. Could just use OnAddPassenger and check for unit typemask inside script.
838 if (Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY))
839 sScriptMgr->OnInstallAccessory(Target, Passenger->ToCreature());
840 }
841
842 return true;
843}
844
855
857{
859 if (Target)
860 {
861 SF_LOG_DEBUG("entities.vehicle", "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %d cancelled",
862 Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first);
863
867 Target->GetBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, Passenger->GetGUID());
868 }
869 else
870 SF_LOG_DEBUG("entities.vehicle", "Passenger GuidLow: %u, Entry: %u, board on uninstalled vehicle SeatId: %d cancelled",
871 Passenger->GetGUIDLow(), Passenger->GetEntry(), (int32)Seat->first);
872
873 if (Passenger->IsInWorld() && Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY))
874 Passenger->ToCreature()->DespawnOrUnsummon();
875}
@ VEHICLE_SEAT_FLAG_CAN_CONTROL
Definition DBCEnums.h:529
@ VEHICLE_SEAT_FLAG_PASSENGER_NOT_SELECTABLE
Definition DBCEnums.h:538
DBCStorage< VehicleSeatEntry > sVehicleSeatStore(VehicleSeatEntryfmt)
#define MAX_VEHICLE_SEATS
std::int32_t int32
Definition Define.h:73
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
std::uint64_t uint64
Definition Define.h:76
#define ASSERT
Definition Errors.h:29
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
TempSummonType
Definition Object.h:67
#define sObjectMgr
Definition ObjectMgr.h:1617
#define sScriptMgr
Definition ScriptMgr.h:764
@ POWER_ENERGY
@ SPELL_EFFECT_HEAL
@ SPELL_EFFECT_DISPEL
@ SPELL_EFFECT_KNOCK_BACK_DEST
@ SPELL_EFFECT_KNOCK_BACK
@ SPELL_EFFECT_HEAL_PCT
@ CREATURE_TYPE_MECHANICAL
@ IMMUNITY_STATE
@ IMMUNITY_EFFECT
@ IMMUNITY_MECHANIC
@ MECHANIC_IMMUNE_SHIELD
@ MECHANIC_SHIELD
@ 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
@ UNIT_NPC_FLAG_SPELLCLICK
Definition Unit.h:711
@ UNIT_NPC_FLAG_PLAYER_VEHICLE
Definition Unit.h:712
@ UNIT_MASK_ACCESSORY
Definition Unit.h:814
@ UNIT_MASK_MINION
Definition Unit.h:806
@ CHARM_TYPE_VEHICLE
Definition Unit.h:1219
@ MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING
Definition Unit.h:788
@ MOVEMENTFLAG2_NO_STRAFE
Definition Unit.h:784
@ MOVEMENTFLAG2_FULL_SPEED_PITCHING
Definition Unit.h:787
@ MOVEMENTFLAG2_FULL_SPEED_TURNING
Definition Unit.h:786
@ MOVEMENTFLAG2_NO_JUMPING
Definition Unit.h:785
@ UNIT_STATE_ROOT
Definition Unit.h:522
@ UNIT_FLAG_NOT_SELECTABLE
Definition Unit.h:650
@ UNIT_FIELD_NPC_FLAGS
@ UNIT_FIELD_FLAGS
@ POWER_STEAM
@ POWER_BLOOD
@ POWER_PYRITE
@ POWER_HEAT
@ POWER_WRATH
@ POWER_OOZE
@ 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
void AddEvent(BasicEvent *Event, uint64 e_time, bool set_addtime=true)
uint64 CalculateTime(uint64 t_offset) const
void SetFacing(float angle)
void MoveTo(const Vector3 &destination, bool generatePath=true, bool forceDestination=false)
static Unit * GetUnit(WorldObject const &, uint64 guid)
uint64 GetGUID() const
Definition Object.h:119
uint32 GetGUIDLow() const
Definition Object.h:120
TypeID GetTypeId() const
Definition Object.h:131
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:1280
uint32 GetEntry() const
Definition Object.h:125
void SendOnCancelExpectedVehicleRideAura()
Definition Player.cpp:15878
void UnsummonPetTemporaryIfAny()
Definition Player.cpp:21113
void StopCastingCharm()
Definition Player.cpp:15768
Battleground * GetBattleground() const
Definition Player.cpp:19212
void StopCastingBindSight()
Definition Player.cpp:20262
Definition Unit.h:1367
Vehicle * GetVehicle() const
Definition Unit.h:2743
EventProcessor m_Events
Definition Unit.h:2396
void SetVehicle(Vehicle *vehicle)
Definition Unit.h:2747
bool IsFlying() const
Definition Unit.h:2780
void AddUnitTypeMask(uint32 mask)
Definition Unit.h:1499
void ExitVehicle(Position const *exitPosition=NULL)
Definition Unit.cpp:8306
Vehicle(Unit *unit, VehicleEntry const *vehInfo, uint32 creatureEntry)
Definition Vehicle.cpp:24
uint8 GetAvailableSeatCount() const
Gets the available seat count.
Definition Vehicle.cpp:657
Unit * GetBase() const
May be called from scripts.
Definition Vehicle.h:38
Unit * GetPassenger(int8 seatId) const
Gets a passenger on specified seat.
Definition Vehicle.cpp:306
void ApplyAllImmunities()
Applies specific immunities that cannot be set in DB.
Definition Vehicle.cpp:184
void RemovePendingEvent(VehicleJoinEvent *e)
Removes @VehicleJoinEvent objects from pending join event store. This method only removes it after it...
Definition Vehicle.cpp:681
SeatMap::iterator GetSeatIteratorForPassenger(Unit *passenger)
Gets seat iterator for specified passenger.
Definition Vehicle.cpp:636
VehicleEntry const * GetVehicleInfo() const
Definition Vehicle.h:39
void Reset(bool evading=false)
Reapplies immunities and reinstalls accessories. Only has effect for creatures.
Definition Vehicle.cpp:162
Vehicle * RemovePassenger(Unit *passenger)
Removes the passenger from the vehicle.
Definition Vehicle.cpp:487
void InitMovementInfoForBase()
Sets correct MovementFlags2 based on VehicleFlags from DBC.
Definition Vehicle.cpp:585
bool AddPassenger(Unit *passenger, int8 seatId=-1)
Attempts to add a passenger to the vehicle on 'seatId'.
Definition Vehicle.cpp:415
void CalculatePassengerPosition(float &x, float &y, float &z, float *o) const
This method transforms supplied transport offsets into global coordinates.
Definition Vehicle.h:78
@ STATUS_INSTALLED
Definition Vehicle.h:70
@ STATUS_UNINSTALLING
Definition Vehicle.h:71
@ STATUS_NONE
Definition Vehicle.h:69
uint32 GetCreatureEntry() const
Definition Vehicle.h:40
void RemoveAllPassengers()
Removes all current and pending passengers from the vehicle.
Definition Vehicle.cpp:241
void InstallAccessory(uint32 entry, int8 seatId, bool minion, TempSummonType type, uint32 summonTime)
Installs an accessory.
Definition Vehicle.cpp:374
~Vehicle()
Definition Vehicle.cpp:47
bool IsVehicleInUse() const
Returns information whether the vehicle is currently used by any unit.
Definition Vehicle.cpp:567
uint32 UsableSeatNum
Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags.
Definition Vehicle.h:64
uint32 _creatureEntry
Can be different than the entry of _me in case of players.
Definition Vehicle.h:101
Status _status
Internal variable for sanity checks.
Definition Vehicle.h:102
void Uninstall()
Removes all passengers and sets status to STATUS_UNINSTALLING. No new passengers can be added to the ...
Definition Vehicle.cpp:133
void RemovePendingEventsForSeat(int8 seatId)
Removes any pending events for given seatId. Executed when a @VehicleJoinEventExecute is called.
Definition Vehicle.cpp:704
Unit * _me
The underlying unit with the vehicle kit. Can be player or creature.
Definition Vehicle.h:97
bool HasEmptySeat(int8 seatId) const
Checks if vehicle's seat specified by 'seatId' is empty.
Definition Vehicle.cpp:285
PendingJoinEventContainer _pendingJoinEvents
Collection of delayed join events for prospective passengers.
Definition Vehicle.h:106
VehicleSeatEntry const * GetSeatForPassenger(Unit const *passenger) const
Returns information on the seat of specified passenger, represented by the format in VehicleSeat....
Definition Vehicle.cpp:614
void Install()
Initializes power type for vehicle. Nothing more.
Definition Vehicle.cpp:64
void RelocatePassengers()
Relocate passengers. Must be called after m_base::Relocate.
Definition Vehicle.cpp:536
SeatMap Seats
The collection of all seats on the vehicle. Including vacant ones.
Definition Vehicle.h:56
SeatMap::const_iterator GetNextEmptySeat(int8 seatId, bool next) const
Gets the next empty seat based on current seat.
Definition Vehicle.cpp:329
friend class VehicleJoinEvent
Definition Vehicle.h:63
void RemovePendingEventsForPassenger(Unit *passenger)
Definition Vehicle.cpp:729
VehicleEntry const * _vehicleInfo
DBC data for vehicle.
Definition Vehicle.h:98
void InstallAllAccessories(bool evading)
Definition Vehicle.cpp:109
bool Execute(uint64, uint32)
Actually adds the passenger @Passenger to vehicle @Target.
Definition Vehicle.cpp:764
SeatMap::iterator Seat
Definition Vehicle.h:120
Unit * Passenger
Definition Vehicle.h:119
Vehicle * Target
Definition Vehicle.h:118
void Abort(uint64)
Aborts the event. Implies that unit @Passenger will not be boarding vehicle @Target after all.
Definition Vehicle.cpp:856
std::string const & GetName() const
Definition Object.h:664
MovementInfo m_movementInfo
Definition Object.h:807
void ResetTransport()
Definition Object.h:518
uint32 m_flags
float m_attachmentOffsetX
float m_attachmentOffsetY
float m_attachmentOffsetZ