diff options
author | Shauren <shauren.trinity@gmail.com> | 2013-03-09 23:42:54 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2013-03-09 23:42:54 +0100 |
commit | b3b66a8d028fafef1e71477325f467ef73626c8e (patch) | |
tree | 77c246a0ef43647947b01ccfd2b55794aa6a9a1a | |
parent | 4ee0a4a4460ff0a44f39a5359c6e234c9d31fc6b (diff) |
Core/Vehicles: Fixed a possible crash if vehicle is deleted before its passenger runs Abort on pending join event
Closes #9392
-rw-r--r-- | src/server/game/Battlefield/Zones/BattlefieldWG.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 4 | ||||
-rwxr-xr-x | src/server/game/Entities/Vehicle/Vehicle.cpp | 60 | ||||
-rw-r--r-- | src/server/game/Entities/Vehicle/Vehicle.h | 3 |
5 files changed, 35 insertions, 43 deletions
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 57f1b44e568..4f481f36716 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -397,7 +397,7 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer) for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) if (Creature* creature = GetCreature(*itr)) if (creature->IsVehicle()) - creature->GetVehicleKit()->Dismiss(); + creature->DespawnOrUnsummon(); m_vehicles[team].clear(); } @@ -767,8 +767,9 @@ void BattlefieldWG::OnPlayerLeaveWar(Player* player) // Remove all aura from WG /// @todo false we can go out of this zone on retail and keep Rank buff, remove on end of WG if (!player->GetSession()->PlayerLogout()) { - if (player->GetVehicle()) // Remove vehicle of player if he go out. - player->GetVehicle()->Dismiss(); + if (Creature* vehicle = player->GetVehicleCreatureBase()) // Remove vehicle of player if he go out. + vehicle->DespawnOrUnsummon(); + RemoveAurasFromPlayer(player); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c0d3acd8a8d..195a9118929 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -23673,14 +23673,14 @@ void Player::UpdateAreaDependentAuras(uint32 newArea) if (!HasAura(itr->second->spellId)) CastSpell(this, itr->second->spellId, true); - if (newArea == 4273 && GetVehicle() && GetPositionX() > 400) // Ulduar + if (newArea == 4273 && GetVehicleCreatureBase() && GetPositionX() > 400) // Ulduar { switch (GetVehicleBase()->GetEntry()) { case 33062: case 33109: case 33060: - GetVehicle()->Dismiss(); + GetVehicleCreatureBase()->DespawnOrUnsummon(); break; } } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0e93bd93433..9d581fcdce9 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -16945,9 +16945,9 @@ void Unit::_ExitVehicle(Position const* exitPosition) if (player) player->ResummonPetTemporaryUnSummonedIfAny(); - if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION)) + if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION) && vehicle->GetBase()->GetTypeId() == TYPEID_UNIT) if (((Minion*)vehicle->GetBase())->GetOwner() == this) - vehicle->Dismiss(); + vehicle->GetBase()->ToCreature()->DespawnOrUnsummon(); if (HasUnitTypeMask(UNIT_MASK_ACCESSORY)) { diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index bfffc84671f..0714c31b047 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -256,11 +256,17 @@ void Vehicle::RemoveAllPassengers() /// Setting to_Abort to true will cause @VehicleJoinEvent::Abort to be executed on next @Unit::UpdateEvents call /// This will properly "reset" the pending join process for the passenger. - while (!_pendingJoinEvents.empty()) { - VehicleJoinEvent* e = _pendingJoinEvents.front(); - e->to_Abort = true; - _pendingJoinEvents.pop_front(); + /// Update vehicle pointer in every pending join event - Abort may be called after vehicle is deleted + Vehicle* eventVehicle = _status != STATUS_UNINSTALLING ? this : NULL; + + while (!_pendingJoinEvents.empty()) + { + VehicleJoinEvent* e = _pendingJoinEvents.front(); + e->to_Abort = true; + e->Target = eventVehicle; + _pendingJoinEvents.pop_front(); + } } // Passengers always cast an aura with SPELL_AURA_CONTROL_VEHICLE on the vehicle @@ -381,13 +387,13 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ /// @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, DB GUID: %u, Entry: %u) attempts to install accessory (Entry: %u) on seat %i with STATUS_UNINSTALLING! " + sLog->outError(LOG_FILTER_VEHICLES, "Vehicle (GuidLow: %u, DB GUID: %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->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(), entry, (int32)seatId); return; } - sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle (GuidLow: %u, DB Guid: %u, Entry %u): installing accessory (Entry: %u) on seat: %i", + sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle (GuidLow: %u, DB Guid: %u, Entry %u): installing accessory (Entry: %u) on seat: %d", _me->GetGUIDLow(), (_me->GetTypeId() == TYPEID_UNIT ? _me->ToCreature()->GetDBTableGUIDLow() : _me->GetGUIDLow()), GetCreatureEntry(), entry, (int32)seatId); @@ -557,25 +563,6 @@ void Vehicle::RelocatePassengers() } /** - * @fn void Vehicle::Dismiss() - * - * @brief Dismiss the vehicle. Removes passengers and despawns self. Only valid for creatures. - * - * @author Machiavelli - * @date 17-2-2013 - */ - -void Vehicle::Dismiss() -{ - if (GetBase()->GetTypeId() != TYPEID_UNIT) - return; - - sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss Entry: %u, GuidLow %u, DBGuid: %u", GetCreatureEntry(), _me->GetGUIDLow(), _me->ToCreature()->GetDBTableGUIDLow()); - Uninstall(); - GetBase()->ToCreature()->DespawnOrUnsummon(); -} - -/** * @fn bool Vehicle::IsVehicleInUse() const * * @brief Returns information whether the vehicle is currently used by any unit @@ -633,10 +620,9 @@ void Vehicle::InitMovementInfoForBase() * @return null if passenger not found on vehicle, else the DBC record for the seat. */ -VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit const* passenger) +VehicleSeatEntry const* Vehicle::GetSeatForPassenger(Unit const* passenger) const { - SeatMap::iterator itr; - for (itr = Seats.begin(); itr != Seats.end(); ++itr) + for (SeatMap::const_iterator itr = Seats.begin(); itr != Seats.end(); ++itr) if (itr->second.Passenger == passenger->GetGUID()) return itr->second.SeatInfo; @@ -868,13 +854,19 @@ bool VehicleJoinEvent::Execute(uint64, uint32) void VehicleJoinEvent::Abort(uint64) { - sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %i cancelled", - Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first); + if (Target) + { + sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on vehicle GuidLow: %u, Entry: %u SeatId: %d cancelled", + Passenger->GetGUIDLow(), Passenger->GetEntry(), Target->GetBase()->GetGUIDLow(), Target->GetBase()->GetEntry(), (int32)Seat->first); - /// @SPELL_AURA_CONTROL_VEHICLE auras can be applied even when the passenger is not (yet) on the vehicle. - /// When this code is triggered it means that something went wrong in @Vehicle::AddPassenger, and we should remove - /// the aura manually. - Target->GetBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, Passenger->GetGUID()); + /// @SPELL_AURA_CONTROL_VEHICLE auras can be applied even when the passenger is not (yet) on the vehicle. + /// When this code is triggered it means that something went wrong in @Vehicle::AddPassenger, and we should remove + /// the aura manually. + Target->GetBase()->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE, Passenger->GetGUID()); + } + else + sLog->outDebug(LOG_FILTER_VEHICLES, "Passenger GuidLow: %u, Entry: %u, board on destroyed vehicle SeatId: %d cancelled", + Passenger->GetGUIDLow(), Passenger->GetEntry(), (int32)Seat->first); if (Passenger->IsInWorld() && Passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) Passenger->ToCreature()->DespawnOrUnsummon(); diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index f9bf3c21ef4..b8ed3a8f947 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -62,7 +62,6 @@ class Vehicle : public TransportBase void RemovePassenger(Unit* passenger); void RelocatePassengers(); void RemoveAllPassengers(); - void Dismiss(); bool IsVehicleInUse() const; void SetLastShootPos(Position const& pos) { _lastShootPos.Relocate(pos); } @@ -70,7 +69,7 @@ class Vehicle : public TransportBase SeatMap Seats; ///< The collection of all seats on the vehicle. Including vacant ones. - VehicleSeatEntry const* GetSeatForPassenger(Unit const* passenger); + VehicleSeatEntry const* GetSeatForPassenger(Unit const* passenger) const; protected: friend class VehicleJoinEvent; |