Core/Auras:

- Use safer order of calls in AuraEffect handlers (unit modification goes before any calls which may result in linked events execution)
 - Allow manual removal of further effects of an aura during aura removal (so Unit::RemoveAurasByType works well in such situations)
This commit is contained in:
QAston
2011-05-25 15:13:55 +02:00
parent 209b5313ff
commit ca8eb707d7
4 changed files with 144 additions and 154 deletions
+47 -31
View File
@@ -3277,6 +3277,7 @@ void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMo
ASSERT(aurApp);
ASSERT(!aurApp->GetRemoveMode());
ASSERT(aurApp->GetTarget() == this);
aurApp->SetRemoveMode(removeMode);
Aura * aura = aurApp->GetBase();
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Aura %u now is remove mode %d", aura->GetId(), removeMode);
@@ -3573,9 +3574,22 @@ void Unit::RemoveAura(uint32 spellId, uint64 caster, uint8 reqEffMask, AuraRemov
void Unit::RemoveAura(AuraApplication * aurApp, AuraRemoveMode mode)
{
ASSERT(aurApp->GetBase()->GetApplicationOfTarget(GetGUID()) == aurApp);
// we've special situation here, RemoveAura called while during aura removal
// this kind of call is needed only when aura effect removal handler
// or event triggered by it expects to remove
// not yet removed effects of an aura
if(aurApp->GetRemoveMode())
{
// remove remaining effects of an aura
for (uint8 itr = 0 ; itr < MAX_SPELL_EFFECTS; ++itr)
{
if (aurApp->HasEffect(itr))
aurApp->_HandleEffect(itr, false);
}
return;
}
// no need to remove
if (aurApp->GetRemoveMode() || aurApp->GetBase()->IsRemoved())
if (aurApp->GetBase()->GetApplicationOfTarget(GetGUID()) != aurApp || aurApp->GetBase()->IsRemoved())
return;
uint32 spellId = aurApp->GetBase()->GetId();
for (AuraApplicationMap::iterator iter = m_appliedAuras.lower_bound(spellId); iter != m_appliedAuras.upper_bound(spellId);)
@@ -3596,8 +3610,6 @@ void Unit::RemoveAura(Aura * aura, AuraRemoveMode mode)
return;
if (AuraApplication * aurApp = aura->GetApplicationOfTarget(GetGUID()))
RemoveAura(aurApp, mode);
else
ASSERT(false);
}
void Unit::RemoveAurasDueToSpell(uint32 spellId, uint64 caster, uint8 reqEffMask, AuraRemoveMode removeMode)
@@ -11909,27 +11921,14 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM, const SpellEntry * s
void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
{
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT);
if (mount)
SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, mount);
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT);
// unsummon pet
if (Player* plr = ToPlayer())
{
Pet* pet = plr->GetPet();
if (pet)
{
Battleground *bg = ToPlayer()->GetBattleground();
// don't unsummon pet in arena but SetFlag UNIT_FLAG_STUNNED to disable pet's interface
if (bg && bg->isArena())
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
else
plr->UnsummonPetTemporaryIfAny();
}
// mount as a vehicle
if (VehicleId)
{
if (CreateVehicleKit(VehicleId, creatureEntry))
@@ -11949,8 +11948,21 @@ void Unit::Mount(uint32 mount, uint32 VehicleId, uint32 creatureEntry)
GetVehicleKit()->InstallAllAccessories(false);
}
}
// unsummon pet
Pet* pet = plr->GetPet();
if (pet)
{
Battleground *bg = ToPlayer()->GetBattleground();
// don't unsummon pet in arena but SetFlag UNIT_FLAG_STUNNED to disable pet's interface
if (bg && bg->isArena())
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
else
plr->UnsummonPetTemporaryIfAny();
}
}
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNT);
}
void Unit::Unmount()
@@ -11958,8 +11970,6 @@ void Unit::Unmount()
if (!IsMounted())
return;
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_MOUNTED);
SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT);
@@ -11967,6 +11977,20 @@ void Unit::Unmount()
data.appendPackGUID(GetGUID());
SendMessageToSet(&data, true);
// unmount as a vehicle
if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit())
{
// Send other players that we are no longer a vehicle
WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, 8+4);
data.appendPackGUID(GetGUID());
data << uint32(0);
this->ToPlayer()->SendMessageToSet(&data, true);
// Remove vehicle from player
RemoveVehicleKit();
}
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_NOT_MOUNTED);
// only resummon old pet if the player is already added to a map
// this prevents adding a pet to a not created map which would otherwise cause a crash
// (it could probably happen when logging in after a previous crash)
@@ -11980,16 +12004,6 @@ void Unit::Unmount()
else
this->ToPlayer()->ResummonPetTemporaryUnSummonedIfAny();
}
if (GetTypeId() == TYPEID_PLAYER && GetVehicleKit())
{
// Send other players that we are no longer a vehicle
WorldPacket data(SMSG_PLAYER_VEHICLE_DATA, 8+4);
data.appendPackGUID(GetGUID());
data << uint32(0);
this->ToPlayer()->SendMessageToSet(&data, true);
// Remove vehicle class from player
RemoveVehicleKit();
}
}
void Unit::SetInCombatWith(Unit* enemy)
@@ -15522,7 +15536,7 @@ void Unit::SetStunned(bool apply)
{
SetUInt64Value(UNIT_FIELD_TARGET, 0);
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
CastStop();
// AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
// Creature specific
@@ -15535,6 +15549,8 @@ void Unit::SetStunned(bool apply)
data.append(GetPackGUID());
data << uint32(0);
SendMessageToSet(&data, true);
CastStop();
}
else
{