mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-23 18:36:31 +01:00
Core/Vehicles: Add some internal checks in vehicle code to prevent crashable behaviour caused by scripts or other areas of the core.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user