diff options
Diffstat (limited to 'src/game/Unit.cpp')
-rw-r--r-- | src/game/Unit.cpp | 699 |
1 files changed, 399 insertions, 300 deletions
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index e08d4c2d43e..f41637b6c75 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -159,7 +159,6 @@ Unit::Unit() for (int i = 0; i < MAX_MOVE_TYPE; ++i) m_speed_rate[i] = 1.0f; - m_removedAuras = 0; m_charmInfo = NULL; m_unit_movement_flags = 0; m_reducedThreatPercent = 0; @@ -344,38 +343,32 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint32 M WorldPacket data( SMSG_MONSTER_MOVE, (41 + GetPackGUID().size()) ); data.append(GetPackGUID()); - // Point A, starting location data << GetPositionX() << GetPositionY() << GetPositionZ(); - // unknown field - unrelated to orientation - // seems to increment about 1000 for every 1.7 seconds - // for now, we'll just use mstime - data << getMSTime(); + data << uint32(getMSTime()); data << uint8(type); // unknown switch(type) { case 0: // normal packet break; - case 1: // stop packet + case 1: // stop packet (raw pos?) SendMessageToSet( &data, true ); return; - case 2: // not used currently - data << float(0); // orientation + case 2: // facing spot, not used currently + data << float(0); data << float(0); data << float(0); break; case 3: // not used currently - data << uint64(0); // probably target guid + data << uint64(0); // probably target guid (facing target?) break; case 4: // not used currently - data << float(0); // probably orientation + data << float(0); // facing angle break; } - //Movement Flags (0x0 = walk, 0x100 = run, 0x200 = fly/swim) - data << uint32((MovementFlags & MOVEMENTFLAG_LEVITATING) ? MOVEFLAG_FLY : MOVEFLAG_WALK); - - data << Time; // Time in between points + data << uint32(MovementFlags); + data << uint32(Time); // Time in between points data << uint32(1); // 1 single waypoint data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B @@ -396,16 +389,12 @@ void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end) data << GetPositionX(); data << GetPositionY(); data << GetPositionZ(); - data << getMSTime(); - data << uint8( 0 ); data << uint32(((GetUnitMovementFlags() & MOVEMENTFLAG_LEVITATING) || isInFlight())? (MOVEFLAG_FLY|MOVEFLAG_WALK) : MOVEFLAG_WALK); data << uint32( traveltime ); data << uint32( pathSize ); data.append( (char*)path.GetNodes(start), pathSize * 4 * 3 ); - - //WPAssert( data.size() == 37 + pathnodes.Size( ) * 4 * 3 ); SendMessageToSet(&data, true); } @@ -472,7 +461,10 @@ void Unit::RemoveAurasWithInterruptFlags(uint32 flag, uint32 except) ++iter; if ((aur->GetSpellProto()->AuraInterruptFlags & flag) && (!except || aur->GetId() != except)) { + uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur); + if (removedAuras+1<m_removedAuras.size()) + iter=m_interruptableAuras.begin(); } } @@ -513,14 +505,17 @@ void Unit::RemoveSpellbyDamageTaken(uint32 damage, uint32 spell) ++iter; if ((!spell || aur->GetId() != spell) && roll_chance_f(chance)) { + uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur); + if (removedAuras+1<m_removedAuras.size()) + iter=m_ccAuras.begin(); } } } uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss) { - if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) + if (!pVictim->isAlive() || pVictim->hasUnitState(UNIT_STAT_UNATTACKABLE) || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) return 0; //You don't lose health from damage taken from another player while in a sanctuary @@ -1323,7 +1318,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) if(!this || !pVictim) return; - if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) + if (!pVictim->isAlive() || pVictim->hasUnitState(UNIT_STAT_UNATTACKABLE) || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) return; SpellEntry const *spellProto = sSpellStore.LookupEntry(damageInfo->SpellID); @@ -1566,7 +1561,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) if(!this || !pVictim) return; - if (!pVictim->isAlive() || pVictim->isInFlight() || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) + if (!pVictim->isAlive() || pVictim->hasUnitState(UNIT_STAT_UNATTACKABLE) || pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) return; //You don't lose health from damage taken from another player while in a sanctuary @@ -1626,7 +1621,8 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) // If this is a creature and it attacks from behind it has a probability to daze it's victim if( (damageInfo->hitOutCome==MELEE_HIT_CRIT || damageInfo->hitOutCome==MELEE_HIT_CRUSHING || damageInfo->hitOutCome==MELEE_HIT_NORMAL || damageInfo->hitOutCome==MELEE_HIT_GLANCING) && - GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this) ) + GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this) + && (pVictim->GetTypeId() == TYPEID_PLAYER || !((Creature*)pVictim)->isWorldBoss())) { // -probability is between 0% and 40% // 20% base chance @@ -1659,7 +1655,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) // victim's damage shield std::set<AuraEffect*> alreadyDone; - uint32 removedAuras = pVictim->m_removedAuras; + uint32 removedAuras = pVictim->m_removedAuras.size(); AuraEffectList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD); for(AuraEffectList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next) { @@ -1688,9 +1684,9 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) pVictim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true); - if (pVictim->m_removedAuras > removedAuras) + if (pVictim->m_removedAuras.size() > removedAuras) { - removedAuras = pVictim->m_removedAuras; + removedAuras = pVictim->m_removedAuras.size(); next = vDamageShields.begin(); } } @@ -2083,7 +2079,10 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe ++i; if (auraeff->GetAmount()<=0) { - pVictim->RemoveAura(aura); + uint32 removedAuras = pVictim->m_removedAuras.size(); + pVictim->RemoveAura(aura, AURA_REMOVE_BY_ENEMY_SPELL); + if (removedAuras+1<pVictim->m_removedAuras.size()) + i=vSchoolAbsorb.begin(); } } } @@ -2118,7 +2117,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe (*i)->SetAmount((*i)->GetAmount()-currentAbsorb); if((*i)->GetAmount() <= 0) { - pVictim->RemoveAurasDueToSpell((*i)->GetId()); + pVictim->RemoveAura((*i)->GetParentAura(), AURA_REMOVE_BY_ENEMY_SPELL); next = vManaShield.begin(); } @@ -2426,7 +2425,10 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack if (tmp > 0 && roll < (sum += tmp)) { DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT <%d, %d)", sum-tmp, sum); - return MELEE_HIT_CRIT; + if(GetTypeId() == TYPEID_UNIT && (((Creature*)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRIT)) + DEBUG_LOG ("RollMeleeOutcomeAgainst: CRIT DISABLED)"); + else + return MELEE_HIT_CRIT; } // Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon) @@ -2832,7 +2834,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit *pVictim, SpellEntry const *spell) HitChance -= int32(((Player*)pVictim)->GetRatingBonusValue(CR_HIT_TAKEN_SPELL)*100.0f); if (HitChance < 100) HitChance = 100; - if (HitChance > 9900) HitChance = 9900; + if (HitChance > 10000) HitChance = 10000; int32 tmp = 10000 - HitChance; @@ -3183,6 +3185,67 @@ uint32 Unit::GetWeaponSkillValue (WeaponAttackType attType, Unit const* target) return value; } +void Unit::_DeleteAuras() +{ + for (AuraList::iterator i = m_removedAuras.begin(); i != m_removedAuras.end();i = m_removedAuras.begin()) + { + Aura * Aur = *i; + SpellEntry const* AurSpellInfo = Aur->GetSpellProto(); + // Statue unsummoned at aura delete + Totem* statue = NULL; + if(Aur->GetAuraDuration() && !Aur->IsPersistent() && IsChanneledSpell(Aur->GetSpellProto())) + { + Unit* caster = Aur->GetCaster(); + if(caster && caster->isAlive()) + { + // stop caster chanelling state + if(caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) + { + // same spell + if (AurSpellInfo == caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo + //prevent recurential call + && caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED) + { + if (caster==this || !IsAreaOfEffectSpell(AurSpellInfo)) + { + // remove auras only for non-aoe spells or when chanelled aura is removed + // because aoe spells don't require aura on target to continue + caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel(); + } + + if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE) + statue = ((Totem*)caster); + } + } + + // Unsummon summon as possessed creatures on spell cancel + if(caster->GetTypeId() == TYPEID_PLAYER) + { + for(int i = 0; i < 3; ++i) + { + if(AurSpellInfo->Effect[i] == SPELL_EFFECT_SUMMON) + if(SummonPropertiesEntry const *SummonProperties = sSummonPropertiesStore.LookupEntry(AurSpellInfo->EffectMiscValueB[i])) + if(SummonProperties->Category == SUMMON_CATEGORY_POSSESSED) + { + ((Player*)caster)->StopCastingCharm(); + break; + } + } + } + } + } + if(statue) + { + sLog.outDebug("Statue %d is unsummoned by aura %d delete from unit %d", statue->GetGUIDLow(), Aur->GetId(),GetGUIDLow()); + statue->UnSummon(); + } + + sLog.outDebug("Aura %d is deleted from unit %d", Aur->GetId(), GetGUIDLow()); + m_removedAuras.pop_front(); + delete (Aur); + } +} + void Unit::_UpdateSpells( uint32 time ) { if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]) @@ -3199,7 +3262,6 @@ void Unit::_UpdateSpells( uint32 time ) } // TODO: Find a better way to prevent crash when multiple auras are removed. - m_removedAuras = 0; for (AuraMap::iterator i = m_Auras.begin(); i != m_Auras.end(); ++i) i->second->SetUpdated(false); @@ -3208,20 +3270,20 @@ void Unit::_UpdateSpells( uint32 time ) Aura *aur = i->second; // prevent double update - if (aur->IsUpdated()) + if(aur->IsUpdated()) + { + ++i; continue; + } + aur->SetUpdated(true); - aur->SetInUse(true); + uint32 removedAuras = m_removedAuras.size(); aur->Update( time ); - aur->SetInUse(false); // several auras can be deleted due to update - if(m_removedAuras) - { - m_removedAuras = 0; + if(removedAuras < m_removedAuras.size()) i = m_Auras.begin(); - } else ++i; } @@ -3234,6 +3296,8 @@ void Unit::_UpdateSpells( uint32 time ) ++i; } + _DeleteAuras(); + if(!m_gameObj.empty()) { std::list<GameObject*>::iterator ite1, dnext1; @@ -3696,6 +3760,8 @@ bool Unit::AddAura(Aura *Aur) { if(foundAura->GetStackAmount() < aurSpellInfo->StackAmount) foundAura->SetStackAmount(foundAura->GetStackAmount()+1); + else + foundAura->RefreshAura(); delete Aur; return true; } @@ -3751,7 +3817,7 @@ bool Unit::AddAura(Aura *Aur) } if((Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE && !Aur->IsAuraType(SPELL_AURA_MOD_POSSESS)) //only dummy aura is breakable - || (Aur->GetSpellProto()->Mechanic==MECHANIC_KNOCKOUT && Aur->IsAuraType(SPELL_AURA_MOD_STUN))) + || ((GetAllSpellMechanicMask(Aur->GetSpellProto()) & 1<<MECHANIC_KNOCKOUT) && Aur->IsAuraType(SPELL_AURA_MOD_STUN))) { m_ccAuras.push_back(Aur); } @@ -3787,7 +3853,6 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) { next = i; ++next; - if ((*i).second->IsInUse()) continue; SpellEntry const* i_spellProto = (*i).second->GetSpellProto(); @@ -3863,12 +3928,9 @@ void Unit::RemoveAura(uint32 spellId, uint64 caster ,AuraRemoveMode removeMode) void Unit::RemoveAura(Aura * aur ,AuraRemoveMode mode) { - if (aur->IsInUse()) - { - if (!aur->GetRemoveMode()) - aur->RemoveAura(mode); + // no need to remove + if (!aur || aur->IsRemoved()) return; - } for(AuraMap::iterator iter = m_Auras.lower_bound(aur->GetId()); iter != m_Auras.upper_bound(aur->GetId());) { if (aur == iter->second) @@ -3885,7 +3947,7 @@ void Unit::RemoveAurasDueToSpell(uint32 spellId, uint64 caster ,AuraRemoveMode r { for(AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) { - if ((!caster || iter->second->GetCasterGUID()==caster) && (!iter->second->IsInUse() || !iter->second->GetRemoveMode())) + if (!caster || iter->second->GetCasterGUID()==caster) { RemoveAura(iter, removeMode); iter = m_Auras.lower_bound(spellId); @@ -3958,15 +4020,15 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit else damage[i]=NULL; } - int32 dur = 2*MINUTE*IN_MILISECONDS > aur->GetAuraDuration() ? 2*MINUTE*IN_MILISECONDS : aur->GetAuraDuration(); + int32 dur = 2*MINUTE*IN_MILISECONDS < aur->GetAuraDuration() ? 2*MINUTE*IN_MILISECONDS : aur->GetAuraDuration(); Aura * new_aur = new Aura(aur->GetSpellProto(),aur->GetEffectMask(), NULL, stealer, stealer, NULL); new_aur->SetLoadedState(aur->GetCasterGUID(), dur, dur, aur->GetAuraCharges(), aur->GetStackAmount(), &damage[0]); // Unregister _before_ adding to stealer aur->UnregisterSingleCastAura(); - // strange but intended behaviour: Stolen single target auras won't be treated as single targeted new_aur->SetIsSingleTarget(false); + stealer->AddAura(new_aur); RemoveAuraFromStack(iter, AURA_REMOVE_BY_ENEMY_SPELL); return; } @@ -3979,7 +4041,7 @@ void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId) { for (AuraMap::iterator iter = m_Auras.lower_bound(spellId); iter != m_Auras.upper_bound(spellId);) { - if ((!castItem || iter->second->GetCastItemGUID()==castItem->GetGUID()) && (!iter->second->IsInUse() || !iter->second->GetRemoveMode())) + if (!castItem || iter->second->GetCastItemGUID()==castItem->GetGUID()) { RemoveAura(iter); iter = m_Auras.upper_bound(spellId); // overwrite by more appropriate @@ -3998,7 +4060,10 @@ void Unit::RemoveAurasByType(AuraType auraType, uint64 casterGUID, Aura * except ++iter; if (aur != except && (!casterGUID || aur->GetCasterGUID()==casterGUID)) { + uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur); + if (removedAuras+1<m_removedAuras.size()) + iter=m_modAuras[auraType].begin(); } } } @@ -4012,7 +4077,10 @@ void Unit::RemoveAurasByTypeWithDispel(AuraType auraType, Spell * spell) ++iter; if (GetDispelChance(spell, aur->GetCaster(), aur->GetId())) { + uint32 removedAuras = m_removedAuras.size(); RemoveAura(aur, AURA_REMOVE_BY_ENEMY_SPELL); + if (removedAuras+1<m_removedAuras.size()) + iter=m_modAuras[auraType].begin(); } } } @@ -4032,35 +4100,25 @@ void Unit::RemoveNotOwnSingleTargetAuras() AuraList& scAuras = GetSingleCastAuras(); for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();) { - if ((*iter)->GetTarget()!=this) + Aura * aur=*iter; + ++iter; + if (aur->GetTarget()!=this) { - Aura * aur=*iter; - ++iter; + uint32 removedAuras = m_removedAuras.size(); aur->GetTarget()->RemoveAura(aur->GetId(),aur->GetCasterGUID()); + if (removedAuras+1<m_removedAuras.size()) + iter=scAuras.begin(); } - else - ++iter; } } void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) { Aura* Aur = i->second; - //aura can be during update when removing, set it to remove at next update - if (Aur->IsInUse()) - { - if (!Aur->GetRemoveMode()) - Aur->RemoveAura(mode); - i++; - return; - } - - SpellEntry const* AurSpellInfo = Aur->GetSpellProto(); // some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura // remove aura from list before to prevent deleting it before m_Auras.erase(i); - ++m_removedAuras; // internal count used by unit update Aur->UnregisterSingleCastAura(); @@ -4072,71 +4130,20 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) if((Aur->GetSpellProto()->Attributes & SPELL_ATTR_BREAKABLE_BY_DAMAGE && !Aur->IsAuraType(SPELL_AURA_MOD_POSSESS)) //only dummy aura is breakable - || (Aur->GetSpellProto()->Mechanic==MECHANIC_KNOCKOUT && Aur->IsAuraType(SPELL_AURA_MOD_STUN))) + || ((GetAllSpellMechanicMask(Aur->GetSpellProto()) & 1<<MECHANIC_KNOCKOUT) && Aur->IsAuraType(SPELL_AURA_MOD_STUN))) { m_ccAuras.remove(Aur); } - // Set remove mode if mode already not set - if (!Aur->GetRemoveMode()) - Aur->SetRemoveMode(mode); - - // Statue unsummoned at aura remove - Totem* statue = NULL; - bool channeled = false; - if(Aur->GetAuraDuration() && !Aur->IsPersistent() && IsChanneledSpell(AurSpellInfo)) - { - Unit* caster = Aur->GetCaster(); - if(caster && caster->isAlive()) - { - // stop caster chanelling state - if(caster->m_currentSpells[CURRENT_CHANNELED_SPELL]) - { - // same spell - if (AurSpellInfo == caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo - //prevent recurential call - && caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED) - { - if (caster==this || !IsAreaOfEffectSpell(AurSpellInfo)) - { - // remove auras only for non-aoe spells or when chanelled aura is removed - // because aoe spells don't require aura on target to continue - { - caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->cancel(); - caster->m_currentSpells[CURRENT_CHANNELED_SPELL]=NULL; - } - } - - if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE) - statue = ((Totem*)caster); - } - } - - // Unsummon summon as possessed creatures on spell cancel - if(caster->GetTypeId() == TYPEID_PLAYER) - { - for(int i = 0; i < 3; ++i) - { - if(AurSpellInfo->Effect[i] == SPELL_EFFECT_SUMMON) - if(SummonPropertiesEntry const *SummonProperties = sSummonPropertiesStore.LookupEntry(AurSpellInfo->EffectMiscValueB[i])) - if(SummonProperties->Category == SUMMON_CATEGORY_POSSESSED) - { - ((Player*)caster)->StopCastingCharm(); - break; - } - } - } - } - } + Aur->SetRemoveMode(mode); sLog.outDebug("Aura %u now is remove mode %d", Aur->GetId(), mode); Aur->HandleEffects(false); - Aur->_RemoveAura(); - delete Aur; + // set aura to be removed during unit::_updatespells + m_removedAuras.push_back(Aur); - if(statue) - statue->UnSummon(); + Aur->_RemoveAura(); // only way correctly remove all auras from list i = m_Auras.begin(); @@ -4233,6 +4240,21 @@ bool Unit::HasAura(uint32 spellId, uint64 caster) const return false; } +bool Unit::HasAura(Aura * aur) const +{ + // no need to find aura + if (!aur || aur->IsRemoved()) + return false; + for(AuraMap::const_iterator iter = m_Auras.lower_bound(aur->GetId()); iter != m_Auras.upper_bound(aur->GetId());) + { + if (aur == iter->second) + return true; + else + ++iter; + } + return false; +} + bool Unit::HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster) const { if (Aura * aur = GetAura(spellId, caster)) @@ -4745,10 +4767,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger case 9799: case 25988: { - // prevent damage back from weapon special attacks - if (!procSpell || procSpell->DmgClass != SPELL_DAMAGE_CLASS_MAGIC ) - return false; - // return damage % to attacker but < 50% own total health basepoints0 = triggerAmount*int32(damage)/100; if(basepoints0 > GetMaxHealth()/2) @@ -5124,7 +5142,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger for(AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) { SpellEntry const *spell = iter->second->GetSpellProto(); - if( GetAllSpellMechanicMask(spell) & 1<<(MECHANIC_STUN-1)) + if( GetAllSpellMechanicMask(spell) & 1<<(MECHANIC_STUN)) { pVictim->RemoveAura(iter); } @@ -5388,7 +5406,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger if (!target) return false; triggered_spell_id = 54181; - basepoints0 = damage * triggerAmount / 100; + basepoints0 = damage * 15 / 100; break; } switch(dummySpell->Id) @@ -5599,14 +5617,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger // Leader of the Pack case 24932: { - if (triggerAmount <= 0) + if (triggerAmount <= 0) return false; basepoints0 = triggerAmount * GetMaxHealth() / 100; target = this; triggered_spell_id = 34299; if (triggeredByAura->GetCaster() != this) break; - int32 basepoints1 = triggerAmount * 2 *GetMaxPower(POWER_MANA)/100; + int32 basepoints1 = triggerAmount * 2; CastCustomSpell(this,60889,&basepoints1,0,0,true,0,triggeredByAura); break; } @@ -5818,6 +5836,34 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger basepoints0 = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000; break; } + // Light's Beacon - Beacon of Light + if ( dummySpell->Id == 53651 ) + { + if (Unit * caster = triggeredByAura->GetCaster()) + { + // do not proc when target of beacon of light is healed + if (caster == pVictim) + return false; + if (Aura * aur = caster->GetAura(53563)) + { + if (Unit * paladin = aur->GetCaster()) + { + if (paladin != this) + return false; + basepoints0 = damage; + triggered_spell_id = 53654; + target = caster; + break; + } + else + { + pVictim->RemoveAura(triggeredByAura->GetParentAura()); + return false; + } + } + } + else return false; + } // Judgements of the Wise if (dummySpell->SpellIconID == 3017) { @@ -6595,7 +6641,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, AuraEffect* trig Item* castItem = triggeredByAura->GetParentAura()->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetParentAura()->GetCastItemGUID()) : NULL; - // Try handle uncnown trigger spells + // Try handle unknown trigger spells if (sSpellStore.LookupEntry(trigger_spell_id)==NULL) { switch (auraSpellInfo->SpellFamilyName) @@ -8000,7 +8046,7 @@ void Unit::SetGuardian(Guardian* guardian, bool apply) if(AddUInt64Value(UNIT_FIELD_SUMMON, guardian->GetGUID())) { - if(GetTypeId() == TYPEID_PLAYER) + if(GetTypeId() == TYPEID_PLAYER && !GetCharmGUID()) { if(guardian->isPet()) ((Player*)this)->PetSpellInitialize(); @@ -8035,12 +8081,17 @@ void Unit::SetGuardian(Guardian* guardian, bool apply) //Check if there is another guardian for(ControlList::iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr) { + if(GetCharmGUID() == (*itr)->GetGUID()) + continue; + assert((*itr)->GetOwnerGUID() == GetGUID()); + assert((*itr)->GetTypeId() == TYPEID_UNIT); if(AddUInt64Value(UNIT_FIELD_SUMMON, (*itr)->GetGUID())) { - if(GetTypeId() == TYPEID_PLAYER) + //show another pet bar if there is no charm bar + if(GetTypeId() == TYPEID_PLAYER && !GetCharmGUID()) { - if(guardian->isPet()) + if(((Creature*)(*itr))->isPet()) ((Player*)this)->PetSpellInitialize(); else ((Player*)this)->CharmSpellInitialize(); @@ -8665,18 +8716,28 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM if (pVictim->GetTypeId() == TYPEID_PLAYER) crit_chance -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL); } - // scripted (increase crit chance ... against ... target by x% AuraEffectList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for(AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { if (!((*i)->isAffectedOnSpell(spellProto))) continue; + int32 modChance=0; switch((*i)->GetMiscValue()) { - case 849: if (pVictim->HasAuraState(AURA_STATE_FROZEN, spellProto, this)) crit_chance+= 17.0f; break; //Shatter Rank 1 - case 910: if (pVictim->HasAuraState(AURA_STATE_FROZEN, spellProto, this)) crit_chance+= 34.0f; break; //Shatter Rank 2 - case 911: if (pVictim->HasAuraState(AURA_STATE_FROZEN, spellProto, this)) crit_chance+= 50.0f; break; //Shatter Rank 3 + // Shatter + case 911: modChance+= 16.0f; + case 910: modChance+= 17.0f; + case 849: modChance+= 17.0f; + if (!pVictim->HasAuraState(AURA_STATE_FROZEN, spellProto, this)) + break; + crit_chance+=modChance; + // Fingers of Frost + // TODO: Change this code to less hacky + if (Aura * aur = GetAura(44544)) + if (aur->DropAuraCharge()) + RemoveAura(aur); + break; case 7917: // Glyph of Shadowburn if (pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, spellProto, this)) crit_chance+=(*i)->GetAmount(); @@ -8906,6 +8967,7 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint // Check for table values SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id); float coeff; + bool scripted = false; if (bonus) { if (damagetype == DOT) @@ -8915,57 +8977,74 @@ uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint if (bonus->ap_bonus) DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack; } + else // scripted bonus + { + // Gift of the Naaru + if (spellProto->Id==59547) + { + scripted = true; + uint32 apBonus = GetTotalAttackPowerValue(BASE_ATTACK); + if (apBonus > DoneAdvertisedBenefit) + { + DoneTotal+=apBonus * stack; + coeff = 0.0f; + } + else + coeff = 1.0f; + } + } + // Default calculation if (DoneAdvertisedBenefit || TakenAdvertisedBenefit) { - if(!bonus) - { - // Damage Done from spell damage bonus - int32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - // Damage over Time spells bonus calculation - float DotFactor = 1.0f; - if(damagetype == DOT) + if(!bonus && !scripted) { - int32 DotDuration = GetSpellDuration(spellProto); - // 200% limit - if(DotDuration > 0) + // Damage Done from spell damage bonus + int32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); + // Damage over Time spells bonus calculation + float DotFactor = 1.0f; + if(damagetype == DOT) { - if(DotDuration > 30000) DotDuration = 30000; - if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; - int x = 0; - for(int j = 0; j < 3; j++) + int32 DotDuration = GetSpellDuration(spellProto); + // 200% limit + if(DotDuration > 0) { - if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) + if(DotDuration > 30000) DotDuration = 30000; + if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; + int x = 0; + for(int j = 0; j < 3; j++) { - x = j; - break; + if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) + { + x = j; + break; + } + } + int32 DotTicks = 6; + if(spellProto->EffectAmplitude[x] != 0) + DotTicks = DotDuration / spellProto->EffectAmplitude[x]; + if(DotTicks) + { + DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks; + TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks; } - } - int32 DotTicks = 6; - if(spellProto->EffectAmplitude[x] != 0) - DotTicks = DotDuration / spellProto->EffectAmplitude[x]; - if(DotTicks) - { - DoneAdvertisedBenefit = DoneAdvertisedBenefit * int32(stack) / DotTicks; - TakenAdvertisedBenefit = TakenAdvertisedBenefit * int32(stack) / DotTicks; } } - } - // Distribute Damage over multiple effects, reduce by AoE - CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for(int j = 0; j < 3; ++j) - { - if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + // Distribute Damage over multiple effects, reduce by AoE + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for(int j = 0; j < 3; ++j) { - CastingTime /= 2; - break; + if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + { + CastingTime /= 2; + break; + } } - } - coeff = (CastingTime / 3500.0f) * DotFactor; + coeff = (CastingTime / 3500.0f) * DotFactor; } float coeff2 = CalculateLevelPenalty(spellProto) * 1.88f * stack; @@ -9117,12 +9196,15 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo) return true; } - SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; - for(SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) + if (spellInfo->Mechanic) { - if(itr->type & (1<<spellInfo->Mechanic)) + SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; + for(SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) { - return true; + if(itr->type == spellInfo->Mechanic) + { + return true; + } } } @@ -9153,7 +9235,7 @@ bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) con { SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) - if(itr->type & 1<<(spellInfo->EffectMechanic[index])) + if(itr->type == spellInfo->EffectMechanic[index]) return true; } @@ -9457,21 +9539,7 @@ void Unit::Mount(uint32 mount) // unsummon pet if(GetTypeId() == TYPEID_PLAYER) - { - Pet* pet = ((Player*)this)->GetPet(); - if(pet) - { - if(pet->isControlled()) - { - ((Player*)this)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber()); - ((Player*)this)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL)); - } - - ((Player*)this)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); - } - else - ((Player*)this)->SetTemporaryUnsummonedPetNumber(0); - } + ((Player*)this)->UnsummonPetTemporaryIfAny(); } void Unit::Unmount() @@ -9487,14 +9555,8 @@ void Unit::Unmount() // 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) - if(GetTypeId() == TYPEID_PLAYER && IsInWorld() && ((Player*)this)->GetTemporaryUnsummonedPetNumber() && isAlive()) - { - Pet* NewPet = new Pet((Player*)this); - if(!NewPet->LoadPetFromDB((Player*)this, 0, ((Player*)this)->GetTemporaryUnsummonedPetNumber(), true)) - delete NewPet; - - ((Player*)this)->SetTemporaryUnsummonedPetNumber(0); - } + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny(); } void Unit::SetInCombatWith(Unit* enemy) @@ -9648,7 +9710,7 @@ bool Unit::isAttackableByAOE() const if(GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster()) return false; - return !isInFlight(); + return !hasUnitState(UNIT_STAT_UNATTACKABLE); } int32 Unit::ModifyHealth(int32 dVal) @@ -10429,7 +10491,7 @@ void Unit::ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime, Spel if(Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CASTING_TIME, castTime, spell); - if( !(spellProto->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_UNK5)) ) + if( !(spellProto->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_UNK5)) && spellProto->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && spellProto->SpellFamilyName) castTime = int32( float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); else { @@ -10575,6 +10637,16 @@ Unit* Unit::GetUnit(WorldObject& object, uint64 guid) return ObjectAccessor::GetUnit(object,guid); } +Player* Unit::GetPlayer(uint64 guid) +{ + return ObjectAccessor::FindPlayer(guid); +} + +Creature* Unit::GetCreature(WorldObject& object, uint64 guid) +{ + return ObjectAccessor::GetCreature(object, guid); +} + bool Unit::isVisibleForInState( Player const* u, bool inVisibleList ) const { return u->canSeeOrDetect(this, false, inVisibleList, false); @@ -10995,9 +11067,22 @@ uint32 Unit::GetCreatePowers( Powers power ) const return 0; } +void Unit::AddToWorld() +{ + if(!IsInWorld()) + { + WorldObject::AddToWorld(); + m_Notified = false; + m_IsInNotifyList = false; + SetToNotify(); + } +} + void Unit::RemoveFromWorld() { // cleanup + assert(GetGUID()); + if(IsInWorld()) { UnsummonAllTotems(); @@ -11015,11 +11100,12 @@ void Unit::RemoveFromWorld() void Unit::CleanupsBeforeDelete() { - assert(m_uint32Values); + assert(GetGUID()); //A unit may be in removelist and not in world, but it is still in grid //and may have some references during delete RemoveAllAuras(); + _DeleteAuras(); InterruptNonMeleeSpells(true); m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList CombatStop(); @@ -11254,34 +11340,18 @@ bool Unit::isFrozen() const struct ProcTriggeredData { - ProcTriggeredData(SpellProcEventEntry const * _spellProcEvent, AuraEffect* _triggeredByAura) - : spellProcEvent(_spellProcEvent), triggeredByAura(_triggeredByAura) - {} - SpellProcEventEntry const *spellProcEvent; - AuraEffect* triggeredByAura; -}; -struct ProcTriggerringAura -{ - ProcTriggerringAura(uint32 _spellId, uint64 _casterGUID) : spellId(_spellId), casterGUID(_casterGUID) + ProcTriggeredData(Aura* _aura) + : aura(_aura) { - triggeringAura[0]=NULL; - triggeringAura[1]=NULL; - triggeringAura[2]=NULL; - } - ProcTriggeredData * triggeringAura[3]; - uint32 spellId; - uint64 casterGUID; - ~ProcTriggerringAura() - { - for (uint8 i = 0;i<3;++i) - if (triggeringAura[i]) - delete triggeringAura[i]; + effMask = 0; + spellProcEvent = NULL; } + SpellProcEventEntry const *spellProcEvent; + Aura * aura; + uint32 effMask; }; -//typedef std::list< ProcTriggeredData > ProcTriggeredList; -typedef std::list< ProcTriggerringAura > ProcTriggeredList; -typedef std::list< uint32> RemoveSpellList; +typedef std::list< ProcTriggeredData > ProcTriggeredList; // List of auras that CAN be trigger but may not exist in spell_proc_event // in most case need for drop charges @@ -11324,6 +11394,7 @@ bool InitTriggerAuraData() isTriggerAura[SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE] = true; isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true; isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true; + isTriggerAura[SPELL_AURA_ABILITY_IGNORE_AURASTATE] = true; isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN]=true; isNonTriggerAura[SPELL_AURA_REDUCE_PUSHBACK]=true; @@ -11437,69 +11508,60 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag } } - RemoveSpellList removedSpells; ProcTriggeredList procTriggered; // Fill procTriggered list for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr) { - bool first = true; - ProcTriggeredList::iterator aurItr; + ProcTriggeredData triggerData(itr->second); + + if(!IsTriggeredAtSpellProcEvent(pTarget, triggerData.aura, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), triggerData.spellProcEvent)) + continue; + for (uint8 i=0; i<MAX_SPELL_EFFECTS;++i) { if (AuraEffect * aurEff = itr->second->GetPartAura(i)) { - SpellProcEventEntry const* spellProcEvent = NULL; - if(!IsTriggeredAtSpellProcEvent(pTarget, aurEff, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent)) + // Skip this auras + if (isNonTriggerAura[aurEff->GetAuraName()]) continue; - if (first) - { - first = false; - ProcTriggerringAura procAur(itr->second->GetId(), itr->second->GetCasterGUID()); - procTriggered.push_front(procAur); - aurItr = procTriggered.begin(); - } - aurItr->triggeringAura[i] = new ProcTriggeredData(spellProcEvent, aurEff); + // If not trigger by default and spellProcEvent==NULL - skip + if (!isTriggerAura[aurEff->GetAuraName()] && triggerData.spellProcEvent==NULL) + continue; + + triggerData.effMask |= 1<<i; } } + if (triggerData.effMask) + procTriggered.push_front(triggerData); } // Nothing found if (procTriggered.empty()) return; - Aura * parentAura = NULL; // Handle effects proceed this time for(ProcTriggeredList::iterator i = procTriggered.begin(); i != procTriggered.end(); ++i) { - // look for parent aura in auras list, it may be removed while proc even processing - parentAura = GetAura(i->spellId, i->casterGUID); - if (!parentAura) + // look for aura in auras list, it may be removed while proc event processing + if (!HasAura(i->aura)) continue; - bool inuse = parentAura->IsInUse(); - if (!inuse) - parentAura->SetInUse(true); - - bool useCharges= parentAura->GetAuraCharges()>0; + bool useCharges= i->aura->GetAuraCharges()>0; bool takeCharges = false; + SpellEntry const *spellInfo = i->aura->GetSpellProto(); + uint32 Id=i->aura->GetId(); - for (uint8 j = 0; j<MAX_SPELL_EFFECTS;++j) - { - if (!i->triggeringAura[j]) - continue; + // For players set spell cooldown if need + uint32 cooldown = 0; + if (GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown) + cooldown = i->spellProcEvent->cooldown; - // possible for stacked auras from same caster, skip then - if (parentAura->GetPartAura(j)!=i->triggeringAura[j]->triggeredByAura) + for (uint8 effIndex = 0; effIndex<MAX_SPELL_EFFECTS;++effIndex) + { + if (!(i->effMask & (1<<effIndex))) continue; - SpellProcEventEntry const *spellProcEvent = i->triggeringAura[j]->spellProcEvent; - AuraEffect *triggeredByAura =triggeredByAura = i->triggeringAura[j]->triggeredByAura; - - SpellEntry const *spellInfo = triggeredByAura->GetSpellProto(); - uint32 effIndex = triggeredByAura->GetEffIndex(); - // For players set spell cooldown if need - uint32 cooldown = 0; - if (GetTypeId() == TYPEID_PLAYER && spellProcEvent && spellProcEvent->cooldown) - cooldown = spellProcEvent->cooldown; + AuraEffect *triggeredByAura = i->aura->GetPartAura(effIndex); + assert(triggeredByAura); switch(triggeredByAura->GetAuraName()) { @@ -11611,19 +11673,11 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag } takeCharges=true; } - if (!inuse) - parentAura->SetInUse(false); - - if ( !parentAura->GetAuraDuration() && !(parentAura->IsPermanent() || (parentAura->IsPassive())) ) - RemoveAura(parentAura); - else + // Remove charge (aura can be removed by triggers) + if(useCharges && takeCharges) { - // Remove charge (aura can be removed by triggers) - if(useCharges && takeCharges) - { - if (parentAura->DropAuraCharge()) - RemoveAura(parentAura->GetId(),parentAura->GetCasterGUID()); - } + if (i->aura->DropAuraCharge()) + RemoveAura(i->aura); } } } @@ -12243,20 +12297,13 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) return pet; } -bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, AuraEffect * aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ) +bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura * aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ) { SpellEntry const* spellProto = aura->GetSpellProto (); // Get proc Event Entry spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id); - // Skip this auras - if (isNonTriggerAura[aura->GetAuraName()]) - return false; - // If not trigger by default and spellProcEvent==NULL - skip - if (!isTriggerAura[aura->GetAuraName()] && spellProcEvent==NULL) - return false; - // Get EventProcFlag uint32 EventProcFlag; if (spellProcEvent && spellProcEvent->procFlags) // if exist get custom spellProcEvent->procFlags @@ -12362,8 +12409,6 @@ bool Unit::HandleAuraRaidProcFromChargeWithValue( AuraEffect* triggeredByAura ) else radius = GetSpellMaxRangeForTarget(triggeredByAura->GetCaster() ,sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); - //Get max possible jumps for aura to get proper charges amount for target - if(Player* caster = ((Player*)triggeredByAura->GetCaster())) { caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL); @@ -12371,7 +12416,7 @@ bool Unit::HandleAuraRaidProcFromChargeWithValue( AuraEffect* triggeredByAura ) if (Unit* target= GetNextRandomRaidMemberOrPet(radius)) { CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID()); - if (Aura * aur = GetAura(spellProto->Id, caster->GetGUID())) + if (Aura * aur = target->GetAura(spellProto->Id, caster->GetGUID())) aur->SetAuraCharges(jumps); //bonus must be applied after aura cast on target @@ -12425,19 +12470,14 @@ bool Unit::HandleAuraRaidProcFromCharge( AuraEffect* triggeredByAura ) else radius = GetSpellMaxRangeForTarget(triggeredByAura->GetCaster() ,sSpellRangeStore.LookupEntry(spellProto->rangeIndex)); - //Get max possible jumps for aura to get proper charges amount for target - int32 maxJumps = spellProto->procCharges; - if(Player* caster = ((Player*)triggeredByAura->GetCaster())) { caster->ApplySpellMod(spellProto->Id, SPELLMOD_RADIUS, radius,NULL); - caster->ApplySpellMod(spellProto->Id, SPELLMOD_CHARGES, maxJumps, NULL); - if (Unit* target= GetNextRandomRaidMemberOrPet(radius)) { - CastSpell(this, spellProto, true,NULL,triggeredByAura,caster_guid); - if (Aura * aur = GetAura(spellProto->Id, caster->GetGUID())) + CastSpell(target, spellProto, true,NULL,triggeredByAura,caster_guid); + if (Aura * aur = target->GetAura(spellProto->Id, caster->GetGUID())) aur->SetAuraCharges(jumps); } } @@ -12796,7 +12836,7 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess) if(this == charmer) return; - if(isInFlight()) + if(hasUnitState(UNIT_STAT_UNATTACKABLE)) return; if(GetTypeId() == TYPEID_PLAYER && ((Player*)this)->GetTransport()) @@ -13107,6 +13147,8 @@ void Unit::GetPartyMember(std::list<Unit*> &TagUnitMap, float radius) void Unit::HandleAuraEffect(AuraEffect * aureff, bool apply) { + if (aureff->GetParentAura()->IsRemoved()) + return; if (apply) { m_modAuras[aureff->GetAuraName()].push_back(aureff); @@ -13145,7 +13187,7 @@ void Unit::AddAura(uint32 spellId, Unit* target) for(uint32 i = 0; i < 3; ++i) { - if(spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA) + if(spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || IsAreaAuraEffect(spellInfo->Effect[i])) { if(target->IsImmunedToSpellEffect(spellInfo, i)) continue; @@ -13174,6 +13216,8 @@ Aura * Unit::AddAuraEffect(uint32 spellId, uint8 effIndex, Unit* caster) if (aur) { AuraEffect *aurEffect = CreateAuraEffect(aur, effIndex, NULL, caster); + if (!aurEffect) + return aur; if (!aur->SetPartAura(aurEffect, effIndex)) delete aurEffect; } @@ -13259,6 +13303,61 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) summon->SetPhaseMask(newPhaseMask,true); } +void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ) +{ + if(GetTypeId() == TYPEID_UNIT) + { + GetMotionMaster()->MoveKnockbackFrom(x, y, speedXY, speedZ); + } + else + { + float vcos, vsin; + GetSinCos(x, y, vsin, vcos); + + WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); + data.append(GetPackGUID()); + data << uint32(0); // Sequence + data << float(vcos); // x direction + data << float(vsin); // y direction + data << float(speedXY); // Horizontal speed + data << float(-speedZ); // Z Movement speed (vertical) + + ((Player*)this)->GetSession()->SendPacket(&data); + } +} + +void Unit::JumpTo(float speedXY, float speedZ, bool forward) +{ + float angle = forward ? 0 : M_PI; + if(GetTypeId() == TYPEID_UNIT) + { + GetMotionMaster()->MoveJumpTo(angle, speedXY, speedZ); + } + else + { + float vcos = cos(angle+GetOrientation()); + float vsin = sin(angle+GetOrientation()); + + WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); + data.append(GetPackGUID()); + data << uint32(0); // Sequence + data << float(vcos); // x direction + data << float(vsin); // y direction + data << float(speedXY); // Horizontal speed + data << float(-speedZ); // Z Movement speed (vertical) + + ((Player*)this)->GetSession()->SendPacket(&data); + } +} + +void Unit::JumpTo(WorldObject *obj, float speedZ) +{ + float x, y, z; + obj->GetContactPoint(this, x, y, z); + float speedXY = GetExactDistance2d(x, y) * 10.0f / speedZ; + GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ); +} + void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ ) { if(GetTypeId() == TYPEID_PLAYER) |