aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.cpp56
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.h18
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