Core/Vehicles: Make the vehicle system more aura driven. Get rid of redundant checks and update relevant data.
Closes #805
This commit is contained in:
@@ -1250,7 +1250,7 @@ void SmartScript::ProcessAction(SmartScriptHolder &e, Unit* unit, uint32 var0, u
|
||||
{
|
||||
if (IsUnit(*itr) && (*itr)->ToUnit()->GetVehicleKit())
|
||||
{
|
||||
me->EnterVehicle((*itr)->ToUnit()->GetVehicleKit(), e.action.enterVehicle.seat);
|
||||
me->EnterVehicle((*itr)->ToUnit(), e.action.enterVehicle.seat);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2553,10 +2553,6 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell)
|
||||
// Resist
|
||||
SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool CanReflect)
|
||||
{
|
||||
// Return evade for units in evade mode
|
||||
if (pVictim->GetTypeId() == TYPEID_UNIT && pVictim->ToCreature()->IsInEvadeMode() && this != pVictim)
|
||||
return SPELL_MISS_EVADE;
|
||||
|
||||
// Check for immune
|
||||
if (pVictim->IsImmunedToSpell(spell))
|
||||
return SPELL_MISS_IMMUNE;
|
||||
@@ -2573,6 +2569,10 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool
|
||||
if (this == pVictim)
|
||||
return SPELL_MISS_NONE;
|
||||
|
||||
// Return evade for units in evade mode
|
||||
if (pVictim->GetTypeId() == TYPEID_UNIT && pVictim->ToCreature()->IsInEvadeMode())
|
||||
return SPELL_MISS_EVADE;
|
||||
|
||||
// Try victim reflect spell
|
||||
if (CanReflect)
|
||||
{
|
||||
@@ -12347,7 +12347,6 @@ void Unit::setDeathState(DeathState s)
|
||||
UnsummonAllTotems();
|
||||
RemoveAllControlled();
|
||||
RemoveAllAurasOnDeath();
|
||||
ExitVehicle();
|
||||
}
|
||||
|
||||
if (s == JUST_DIED)
|
||||
@@ -16512,14 +16511,20 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
|
||||
}
|
||||
}
|
||||
|
||||
if (this->ToCreature())
|
||||
if (this->ToCreature() && this->ToCreature()->IsAIEnabled)
|
||||
this->ToCreature()->AI()->DoAction(EVENT_SPELLCLICK);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void Unit::EnterVehicle(Vehicle *vehicle, int8 seatId, AuraApplication const * aurApp)
|
||||
void Unit::EnterVehicle(Unit *base, int8 seatId)
|
||||
{
|
||||
CastCustomSpell(VEHICLE_SPELL_RIDE_HARDCODED, SPELLVALUE_BASE_POINT0, seatId+1, base, false);
|
||||
}
|
||||
|
||||
void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* aurApp)
|
||||
{
|
||||
// Must be called only from aura handler
|
||||
if (!isAlive() || GetVehicleKit() == vehicle || vehicle->GetBase()->IsOnVehicle(this))
|
||||
return;
|
||||
|
||||
@@ -16541,6 +16546,9 @@ void Unit::EnterVehicle(Vehicle *vehicle, int8 seatId, AuraApplication const * a
|
||||
}
|
||||
}
|
||||
|
||||
if (aurApp && aurApp->GetRemoveMode())
|
||||
return;
|
||||
|
||||
if (Player* plr = ToPlayer())
|
||||
{
|
||||
if (vehicle->GetBase()->GetTypeId() == TYPEID_PLAYER && plr->isInCombat())
|
||||
@@ -16557,11 +16565,6 @@ void Unit::EnterVehicle(Vehicle *vehicle, int8 seatId, AuraApplication const * a
|
||||
bg->EventPlayerDroppedFlag(plr);
|
||||
}
|
||||
|
||||
// vehicle is applied by aura, and aura effect remove handler was called during apply handler execution
|
||||
// prevent undefined behaviour
|
||||
if (aurApp && aurApp->GetRemoveMode())
|
||||
return;
|
||||
|
||||
if (Player* thisPlr = this->ToPlayer())
|
||||
{
|
||||
WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0);
|
||||
@@ -16598,6 +16601,7 @@ void Unit::ChangeSeat(int8 seatId, bool next)
|
||||
|
||||
void Unit::ExitVehicle(Position const* exitPosition)
|
||||
{
|
||||
// This function can be called at upper level code to initialize an exit from the passenger's side.
|
||||
if (!m_vehicle)
|
||||
return;
|
||||
|
||||
@@ -16612,6 +16616,11 @@ void Unit::ExitVehicle(Position const* exitPosition)
|
||||
}
|
||||
}
|
||||
|
||||
_ExitVehicle(exitPosition);
|
||||
}
|
||||
|
||||
void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
{
|
||||
if (!m_vehicle)
|
||||
return;
|
||||
|
||||
@@ -16650,6 +16659,16 @@ void Unit::ExitVehicle(Position const* exitPosition)
|
||||
if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION))
|
||||
if (((Minion*)vehicle->GetBase())->GetOwner() == this)
|
||||
vehicle->Dismiss();
|
||||
|
||||
if (HasUnitTypeMask(UNIT_MASK_ACCESSORY))
|
||||
{
|
||||
// Vehicle just died, we die too
|
||||
if (vehicle->GetBase()->getDeathState() == JUST_DIED)
|
||||
setDeathState(JUST_DIED);
|
||||
// If for other reason we as minion are exiting the vehicle (ejected, master unmounted) - unsummon
|
||||
else
|
||||
ToTempSummon()->UnSummon();
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::BuildMovementPacket(ByteBuffer *data) const
|
||||
|
||||
@@ -2058,11 +2058,14 @@ class Unit : public WorldObject
|
||||
|
||||
bool CheckPlayerCondition(Player* pPlayer);
|
||||
bool HandleSpellClick(Unit* clicker, int8 seatId = -1);
|
||||
void EnterVehicle(Unit *base, int8 seatId = -1, AuraApplication const * aurApp = NULL) { EnterVehicle(base->GetVehicleKit(), seatId, aurApp); }
|
||||
void EnterVehicle(Vehicle *vehicle, int8 seatId = -1, AuraApplication const * aurApp = NULL);
|
||||
void EnterVehicle(Unit *base, int8 seatId = -1);
|
||||
void ExitVehicle(Position const* exitPosition = NULL);
|
||||
void ChangeSeat(int8 seatId, bool next = true);
|
||||
|
||||
// Should only be called by AuraEffect::HandleAuraControlVehicle(AuraApplication const* auraApp, uint8 mode, bool apply) const;
|
||||
void _ExitVehicle(Position const* exitPosition = NULL);
|
||||
void _EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* aurApp = NULL);
|
||||
|
||||
void BuildMovementPacket(ByteBuffer *data) const;
|
||||
|
||||
bool isMoving() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MOVING); }
|
||||
|
||||
@@ -122,7 +122,7 @@ void Vehicle::Install()
|
||||
|
||||
void Vehicle::InstallAllAccessories()
|
||||
{
|
||||
me->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE); // We might have aura's saved in the DB with now invalid casters - remove
|
||||
RemoveAllPassengers(); // We might have aura's saved in the DB with now invalid casters - remove
|
||||
|
||||
VehicleAccessoryList const* mVehicleList = sObjectMgr->GetVehicleAccessoryList(m_creatureEntry);
|
||||
if (!mVehicleList)
|
||||
@@ -134,12 +134,7 @@ void Vehicle::InstallAllAccessories()
|
||||
|
||||
void Vehicle::Uninstall()
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Uninstall %u", me->GetEntry());
|
||||
for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
|
||||
if (Unit *passenger = ObjectAccessor::GetUnit(*GetBase(), itr->second.passenger))
|
||||
if (passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY))
|
||||
passenger->ToTempSummon()->UnSummon();
|
||||
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Uninstall Entry: %u, GuidLow: %u", m_creatureEntry, me->GetGUIDLow());
|
||||
RemoveAllPassengers();
|
||||
|
||||
if (GetBase()->GetTypeId() == TYPEID_UNIT)
|
||||
@@ -148,12 +143,7 @@ void Vehicle::Uninstall()
|
||||
|
||||
void Vehicle::Die()
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Die %u", me->GetEntry());
|
||||
for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
|
||||
if (Unit *passenger = ObjectAccessor::GetUnit(*GetBase(), itr->second.passenger))
|
||||
if (passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY))
|
||||
passenger->setDeathState(JUST_DIED);
|
||||
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Die Entry: %u, GuidLow: %u", m_creatureEntry, me->GetGUIDLow());
|
||||
RemoveAllPassengers();
|
||||
|
||||
if (GetBase()->GetTypeId() == TYPEID_UNIT)
|
||||
@@ -181,31 +171,18 @@ void Vehicle::Reset()
|
||||
|
||||
void Vehicle::RemoveAllPassengers()
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::RemoveAllPassengers");
|
||||
for (SeatMap::iterator itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
|
||||
if (Unit *passenger = ObjectAccessor::GetUnit(*GetBase(), itr->second.passenger))
|
||||
{
|
||||
ASSERT(passenger->IsInWorld());
|
||||
ASSERT(passenger->IsOnVehicle(GetBase()));
|
||||
ASSERT(GetSeatForPassenger(passenger));
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::RemoveAllPassengers. Entry: %u, GuidLow: %u", m_creatureEntry, me->GetGUIDLow());
|
||||
|
||||
if (passenger->IsVehicle())
|
||||
passenger->GetVehicleKit()->RemoveAllPassengers();
|
||||
// Passengers always cast an aura with SPELL_AURA_CONTROL_VEHICLE on the vehicle
|
||||
// We just remove the aura and the unapply handler will make the target leave the vehicle.
|
||||
// We don't need to iterate over m_Seats
|
||||
me->RemoveAurasByType(SPELL_AURA_CONTROL_VEHICLE);
|
||||
|
||||
if (passenger->GetVehicle() != this)
|
||||
sLog->outCrash("Vehicle %u has invalid passenger %u. Seat: %i", me->GetEntry(), passenger->GetEntry(), itr->first);
|
||||
|
||||
passenger->ExitVehicle();
|
||||
if (itr->second.passenger)
|
||||
{
|
||||
sLog->outCrash("Vehicle %u cannot remove passenger %u. "UI64FMTD" is still on vehicle.", me->GetEntry(), passenger->GetEntry(), itr->second.passenger);
|
||||
itr->second.passenger = 0;
|
||||
}
|
||||
|
||||
// creature passengers mounted on player mounts should be despawned at dismount
|
||||
if (GetBase()->GetTypeId() == TYPEID_PLAYER && passenger->ToCreature())
|
||||
passenger->ToCreature()->DespawnOrUnsummon();
|
||||
}
|
||||
// Following the above logic, this assertion should NEVER fail.
|
||||
// Even in 'hacky' cases, there should at least be VEHICLE_SPELL_RIDE_HARDCODED on us.
|
||||
SeatMap::const_iterator itr;
|
||||
for (itr = m_Seats.begin(); itr != m_Seats.end(); ++itr)
|
||||
ASSERT(!itr->second.passenger);
|
||||
}
|
||||
|
||||
bool Vehicle::HasEmptySeat(int8 seatId) const
|
||||
@@ -264,16 +241,8 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ
|
||||
if (me->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
if (me->ToCreature()->IsInEvadeMode() && passenger->ToCreature()->IsAIEnabled)
|
||||
{
|
||||
passenger->ToCreature()->AI()->EnterEvadeMode();
|
||||
return;
|
||||
}
|
||||
else if (passenger->HasUnitTypeMask(UNIT_MASK_ACCESSORY) && passenger->ToTempSummon()->GetSummonType() == TEMPSUMMON_MANUAL_DESPAWN)
|
||||
{
|
||||
passenger->ExitVehicle();
|
||||
passenger->ToTempSummon()->DespawnOrUnsummon();
|
||||
ASSERT(!GetPassenger(seatId))
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -288,9 +257,16 @@ void Vehicle::InstallAccessory(uint32 entry, int8 seatId, bool minion, uint8 typ
|
||||
|
||||
if (!me->HandleSpellClick(accessory, seatId))
|
||||
{
|
||||
sLog->outErrorDb("Vehicle entry %u in vehicle_accessory does not have a valid record in npc_spellclick_spells! Calling default EnterVehicle()",
|
||||
sLog->outErrorDb("Vehicle entry %u in vehicle_accessory does not have a valid record in npc_spellclick_spells! Cannot join vehicle.",
|
||||
m_creatureEntry);
|
||||
accessory->EnterVehicle(this, seatId);
|
||||
accessory->AddObjectToRemoveList();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!accessory->IsOnVehicle(me))
|
||||
{
|
||||
accessory->AddObjectToRemoveList();
|
||||
return; // Something went wrong in the spellsystem
|
||||
}
|
||||
|
||||
// This is not good, we have to send update twice
|
||||
@@ -489,7 +465,7 @@ void Vehicle::RelocatePassengers(float x, float y, float z, float ang)
|
||||
|
||||
void Vehicle::Dismiss()
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss %u", me->GetEntry());
|
||||
sLog->outDebug(LOG_FILTER_VEHICLES, "Vehicle::Dismiss Entry: %u, GuidLow %u", m_creatureEntry, me->GetGUIDLow());
|
||||
Uninstall();
|
||||
me->DestroyForNearbyPlayers();
|
||||
me->CombatStop();
|
||||
|
||||
@@ -73,6 +73,7 @@ enum VehicleSeatFlagsB
|
||||
|
||||
enum VehicleSpells
|
||||
{
|
||||
VEHICLE_SPELL_RIDE_HARDCODED = 46598,
|
||||
VEHICLE_SPELL_PARACHUTE = 45472
|
||||
};
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
|
||||
{
|
||||
if (Vehicle *vehicle = vehUnit->GetVehicleKit())
|
||||
if (vehicle->HasEmptySeat(seatId))
|
||||
GetPlayer()->EnterVehicle(vehicle, seatId);
|
||||
GetPlayer()->_EnterVehicle(vehicle, seatId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -116,7 +116,7 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
|
||||
else if (Unit *vehUnit = Unit::GetUnit(*GetPlayer(), guid))
|
||||
if (Vehicle *vehicle = vehUnit->GetVehicleKit())
|
||||
if (vehicle->HasEmptySeat(seatId))
|
||||
GetPlayer()->EnterVehicle(vehicle, seatId);
|
||||
GetPlayer()->_EnterVehicle(vehicle, seatId);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -200,7 +200,6 @@ void WorldSession::HandleEjectPassenger(WorldPacket &data)
|
||||
{
|
||||
ASSERT(GetPlayer() == vehicle->GetBase());
|
||||
unit->ExitVehicle();
|
||||
unit->AddObjectToRemoveList();
|
||||
}
|
||||
else
|
||||
sLog->outError("Player %u attempted to eject creature GUID %u from non-ejectable seat.", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
|
||||
|
||||
@@ -4269,7 +4269,7 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const * aurApp, uint8
|
||||
|
||||
if (apply)
|
||||
{
|
||||
caster->EnterVehicle(target->GetVehicleKit(), m_amount - 1, aurApp);
|
||||
caster->_EnterVehicle(target->GetVehicleKit(), m_amount - 1, aurApp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4282,7 +4282,7 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const * aurApp, uint8
|
||||
|
||||
// some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them
|
||||
caster->RemoveAurasDueToSpell(GetId());
|
||||
caster->ExitVehicle();
|
||||
caster->_ExitVehicle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1166,7 +1166,7 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
|
||||
// use 99 because it is 3d search
|
||||
SearchAreaTarget(unitList, 99, PUSH_DST_CENTER, SPELL_TARGETS_ENTRY, 33114);
|
||||
float minDist = 99 * 99;
|
||||
Vehicle *target = NULL;
|
||||
Unit *target = NULL;
|
||||
for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
|
||||
{
|
||||
if (Vehicle *seat = (*itr)->GetVehicleKit())
|
||||
@@ -1178,11 +1178,11 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
|
||||
if (dist < minDist)
|
||||
{
|
||||
minDist = dist;
|
||||
target = seat;
|
||||
target = (*itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target && target->GetBase()->IsWithinDist2d(&m_targets.m_dstPos, GetSpellRadius(m_spellInfo, effIndex, false) * 2)) // now we use *2 because the location of the seat is not correct
|
||||
if (target && target->IsWithinDist2d(&m_targets.m_dstPos, GetSpellRadius(m_spellInfo, effIndex, false) * 2)) // now we use *2 because the location of the seat is not correct
|
||||
passenger->EnterVehicle(target, 0);
|
||||
else
|
||||
{
|
||||
@@ -3144,7 +3144,7 @@ void Spell::EffectSummonType(SpellEffIndex effIndex)
|
||||
}
|
||||
|
||||
// Hard coded enter vehicle spell
|
||||
m_originalCaster->CastSpell(summon, 46598, true);
|
||||
m_originalCaster->CastSpell(summon, VEHICLE_SPELL_RIDE_HARDCODED, true);
|
||||
|
||||
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||
uint32 faction = properties->Faction;
|
||||
@@ -5148,7 +5148,7 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
|
||||
oldContainer->DisappearAndDie();
|
||||
// TODO: a hack, range = 11, should after some time cast, otherwise too far
|
||||
m_caster->CastSpell(seat->GetBase(), 62496, true);
|
||||
unitTarget->EnterVehicle(seat, 1);
|
||||
unitTarget->EnterVehicle(m_caster, 1);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user