diff options
author | Shauren <shauren.trinity@gmail.com> | 2013-02-24 14:38:47 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2013-02-24 14:38:47 +0100 |
commit | 16f9a9d1b48006f3cfde709ff5328a2cb2e282e0 (patch) | |
tree | 32f92a5528e796a94321a9d313c7860a26735528 | |
parent | 5f16aad0927de35a87bcaaad76ef6808f128bce2 (diff) |
Core/Vehicles: Fixed a crash that happened if someone called ExitVehicle during seat changing
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 7 | ||||
-rwxr-xr-x | src/server/game/Entities/Vehicle/Vehicle.cpp | 18 | ||||
-rw-r--r-- | src/server/game/Entities/Vehicle/Vehicle.h | 6 |
3 files changed, 23 insertions, 8 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index fa7ef5189fb..104f47a3061 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -16605,7 +16605,12 @@ void Unit::ChangeSeat(int8 seatId, bool next) // Todo: the functions below could be consolidated and refactored to take // SeatMap::const_iterator as parameter, to save redundant map lookups. m_vehicle->RemovePassenger(this); - if (!m_vehicle->AddPassenger(this, seatId)) + + // Set m_vehicle to NULL before adding passenger as adding new passengers is handled asynchronously + // and someone may call ExitVehicle again before passenger is added to new seat + Vehicle* veh = m_vehicle; + m_vehicle = NULL; + if (!veh->AddPassenger(this, seatId)) ASSERT(false); } diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 4f41e74f4d7..f3844d96069 100755 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -436,6 +436,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) // exits the vehicle will dismiss. That's why the actual adding the passenger to the vehicle is scheduled // asynchronously, so it can be cancelled easily in case the vehicle is uninstalled meanwhile. SeatMap::iterator seat; + VehicleJoinEvent* e = new VehicleJoinEvent(this, unit); + unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0)); + if (seatId < 0) // no specific seat requirement { for (seat = Seats.begin(); seat != Seats.end(); ++seat) @@ -443,22 +446,25 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) break; if (seat == Seats.end()) // no available seat + { + e->to_Abort = true; return false; + } - VehicleJoinEvent* e = new VehicleJoinEvent(this, unit, seat); + e->Seat = seat; _pendingJoinEvents.push_back(e); - unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0)); } else { seat = Seats.find(seatId); if (seat == Seats.end()) + { + e->to_Abort = true; return false; + } - VehicleJoinEvent* e = new VehicleJoinEvent(this, unit, seat); + e->Seat = seat; _pendingJoinEvents.push_back(e); - unit->m_Events.AddEvent(e, unit->m_Events.CalculateTime(0)); - if (seat->second.Passenger) { Unit* passenger = ObjectAccessor::GetUnit(*GetBase(), seat->second.Passenger); @@ -480,7 +486,7 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) * @author Machiavelli * @date 17-2-2013 * - * @param [in,out] unit The passenger to remove.. + * @param [in,out] unit The passenger to remove. */ void Vehicle::RemovePassenger(Unit* unit) diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 38c5a39f67d..8b67b82cfa3 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -65,6 +65,9 @@ class Vehicle : public TransportBase void Dismiss(); bool IsVehicleInUse() { return Seats.begin() != Seats.end(); } + void SetLastShootPos(Position const& pos) { _lastShootPos.Relocate(pos); } + Position GetLastShootPos() { return _lastShootPos; } + SeatMap Seats; ///< The collection of all seats on the vehicle. Including vacant ones. VehicleSeatEntry const* GetSeatForPassenger(Unit* passenger); @@ -100,6 +103,7 @@ class Vehicle : public TransportBase uint32 _creatureEntry; ///< Can be different than the entry of _me in case of players Status _status; ///< Internal variable for sanity checks + Position _lastShootPos; typedef std::list<VehicleJoinEvent*> PendingJoinEventContainer; PendingJoinEventContainer _pendingJoinEvents; ///< Collection of delayed join events for prospective passengers @@ -109,7 +113,7 @@ class VehicleJoinEvent : public BasicEvent { friend class Vehicle; protected: - VehicleJoinEvent(Vehicle* v, Unit* u, SeatMap::iterator seat) : Target(v), Passenger(u), Seat(seat) {} + VehicleJoinEvent(Vehicle* v, Unit* u) : Target(v), Passenger(u), Seat(Target->Seats.end()) {} ~VehicleJoinEvent() { Target->RemovePendingEvent(this); } bool Execute(uint64, uint32); void Abort(uint64); |