diff options
-rw-r--r-- | src/server/game/Entities/Vehicle/Vehicle.cpp | 56 | ||||
-rw-r--r-- | src/server/game/Entities/Vehicle/Vehicle.h | 18 |
2 files changed, 50 insertions, 24 deletions
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 550cc03f995..a3be443d014 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -31,7 +31,8 @@ #include "MoveSplineInit.h" #include "TemporarySummon.h" -Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) : _me(unit), _vehicleInfo(vehInfo), _usableSeatNum(0), _creatureEntry(creatureEntry) +Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) : +_me(unit), _vehicleInfo(vehInfo), _usableSeatNum(0), _creatureEntry(creatureEntry), _status(STATUS_NONE) { for (uint32 i = 0; i < MAX_VEHICLE_SEATS; ++i) { @@ -49,6 +50,8 @@ Vehicle::Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry) Vehicle::~Vehicle() { + /// @Uninstall must be called before this. + ASSERT(_status == STATUS_UNINSTALLING); for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr) ASSERT(!itr->second.Passenger); } @@ -92,6 +95,7 @@ void Vehicle::Install() } } + _status = STATUS_INSTALLED; if (GetBase()->GetTypeId() == TYPEID_UNIT) sScriptMgr->OnInstall(this); } @@ -112,6 +116,14 @@ void Vehicle::InstallAllAccessories(bool evading) void Vehicle::Uninstall() { + /// @Prevent recursive uninstall call. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.) + if (_status == STATUS_UNINSTALLING) + { + sLog->outError(LOG_FILTER_VEHICLES, "Vehicle GuidLow: %u, Entry: %u attempts to uninstall, but already has STATUS_UNINSTALLING! " + "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry()); + return; + } + _status = STATUS_UNINSTALLING; sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Uninstall Entry: %u, GuidLow: %u", _creatureEntry, _me->GetGUIDLow()); RemoveAllPassengers(); @@ -250,6 +262,14 @@ int8 Vehicle::GetNextEmptySeat(int8 seatId, bool next) const void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 type, uint32 summonTime) { + /// @Prevent adding accessories when vehicle is uninstalling. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.) + if (_status == STATUS_UNINSTALLING) + { + sLog->outError(LOG_FILTER_VEHICLES, "Vehicle GuidLow: %u, Entry: %u attempts to install accessory Entry: %u on seat %d with STATUS_UNINSTALLING! " + "Check Uninstall/PassengerBoarded script hooks for errors.", _me->GetGUIDLow(), _me->GetEntry(), entry, (int32)seatId); + return; + } + sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle: Installing accessory entry %u on vehicle entry %u (seat:%i)", entry, GetCreatureEntry(), seatId); if (Unit* passenger = GetPassenger(seatId)) { @@ -279,14 +299,6 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ return; } - // this cannot be checked instantly like this - // spellsystem is delaying everything to next update tick - //if (!accessory->IsOnVehicle(me)) - //{ - // accessory->UnSummon(); - // return; // Something went wrong in the spellsystem - //} - if (GetBase()->GetTypeId() == TYPEID_UNIT) sScriptMgr->OnInstallAccessory(this, accessory); } @@ -294,6 +306,14 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) { + /// @Prevent adding passengers when vehicle is uninstalling. (Bad script in OnUninstall/OnRemovePassenger/PassengerBoarded hook.) + if (_status == STATUS_UNINSTALLING) + { + sLog->outError(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, attempting to board vehicle GuidLow: %u, Entry: %u during uninstall! SeatId: %i", + unit->GetGUIDLow(), unit->GetEntry(), _me->GetGUIDLow(), _me->GetEntry(), (int32)seatId); + return false; + } + if (unit->GetVehicle() != this) return false; @@ -353,13 +373,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) unit->m_movementInfo.t_seat = seat->first; unit->m_movementInfo.t_guid = _me->GetGUID(); - if (_me->GetTypeId() == TYPEID_UNIT - && unit->GetTypeId() == TYPEID_PLAYER - && seat->first == 0 && seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) - { - if (!_me->SetCharmedBy(unit, CHARM_TYPE_VEHICLE)) - ASSERT(false); - } + if (_me->GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && + seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) + ASSERT(_me->SetCharmedBy(unit, CHARM_TYPE_VEHICLE)) if (_me->IsInWorld()) { @@ -415,7 +431,7 @@ void Vehicle::RemovePassenger(Unit* unit) unit->ClearUnitState(UNIT_STATE_ONVEHICLE); - if (_me->GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && seat->first == 0 && seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) + if (_me->GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && seat->second.SeatInfo->m_flags & VEHICLE_SEAT_FLAG_CAN_CONTROL) _me->RemoveCharmedBy(unit); if (_me->IsInWorld()) @@ -426,13 +442,13 @@ void Vehicle::RemovePassenger(Unit* unit) unit->m_movementInfo.t_seat = 0; } - if (_me->GetTypeId() == TYPEID_UNIT && _me->ToCreature()->IsAIEnabled) - _me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, false); - // only for flyable vehicles if (unit->IsFlying()) _me->CastSpell(unit, VEHICLE_SPELL_PARACHUTE, true); + if (_me->GetTypeId() == TYPEID_UNIT && _me->ToCreature()->IsAIEnabled) + _me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, false); + if (GetBase()->GetTypeId() == TYPEID_UNIT) sScriptMgr->OnRemovePassenger(this, unit); } diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 5ae08bd7109..ab06b4a1439 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -32,9 +32,6 @@ typedef std::set<uint64> GuidSet; class Vehicle : public TransportBase { public: - explicit Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry); - virtual ~Vehicle(); - void Install(); void Uninstall(); void Reset(bool evading = false); @@ -67,7 +64,20 @@ class Vehicle : public TransportBase VehicleSeatEntry const* GetSeatForPassenger(Unit* passenger); + protected: + friend bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry); + Vehicle(Unit* unit, VehicleEntry const* vehInfo, uint32 creatureEntry); + friend void Unit::RemoveVehicleKit(); + ~Vehicle(); + private: + enum Status + { + STATUS_NONE, + STATUS_INSTALLED, + STATUS_UNINSTALLING, + }; + SeatMap::iterator GetSeatIteratorForPassenger(Unit* passenger); void InitMovementInfoForBase(); @@ -82,7 +92,7 @@ class Vehicle : public TransportBase GuidSet vehiclePlayers; uint32 _usableSeatNum; // Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags uint32 _creatureEntry; // Can be different than me->GetBase()->GetEntry() in case of players - + Status _status; Position m_lastShootPos; }; #endif |