aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2013-03-09 23:42:54 +0100
committerShauren <shauren.trinity@gmail.com>2013-03-09 23:42:54 +0100
commitb3b66a8d028fafef1e71477325f467ef73626c8e (patch)
tree77c246a0ef43647947b01ccfd2b55794aa6a9a1a
parent4ee0a4a4460ff0a44f39a5359c6e234c9d31fc6b (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.cpp7
-rw-r--r--src/server/game/Entities/Player/Player.cpp4
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp4
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp60
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.h3
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;