Index: src/game/HostilRefManager.cpp =================================================================== --- src/game/HostilRefManager.cpp (revision 5635) +++ src/game/HostilRefManager.cpp (working copy) @@ -20,6 +20,7 @@ #include "ThreatManager.h" #include "Unit.h" #include "Database/DBCStructure.h" +#include "SpellMgr.h" HostilRefManager::~HostilRefManager() { @@ -39,7 +40,7 @@ ref = getFirst(); while(ref != NULL) { - float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, (pThreatSpell ? SpellSchools(pThreatSpell->School) : SPELL_SCHOOL_NORMAL), pThreatSpell); + float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell); if(pVictim == getOwner()) ref->addThreat(float (threat) / size); // It is faster to modify the threat durectly if possible else Index: src/game/Level3.cpp =================================================================== --- src/game/Level3.cpp (revision 5636) +++ src/game/Level3.cpp (working copy) @@ -2802,7 +2802,7 @@ if( target->isAlive() ) { - m_session->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, false); + m_session->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } return true; Index: src/game/Player.cpp =================================================================== --- src/game/Player.cpp (revision 5636) +++ src/game/Player.cpp (working copy) @@ -609,7 +609,7 @@ //m_session->SendPacket(&data); //Let other players see that you get damage SendMessageToSet(&data, true); - DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, false); + DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); if(type==DAMAGE_FALL && !isAlive()) // DealDamage not apply item durability loss at self damage { @@ -1934,7 +1934,7 @@ bool Player::IsInSameGroupWith(Player const* p) const { - return GetGroup() != NULL && + return p==this || GetGroup() != NULL && GetGroup() == p->GetGroup() && GetGroup()->SameSubGroup((Player*)this, (Player*)p); } @@ -15324,7 +15324,7 @@ return true; } -void Player::ProhibitSpellScholl(SpellSchools idSchool, uint32 unTimeMs ) +void Player::ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs ) { // last check 2.0.10 WorldPacket data(SMSG_SPELL_COOLDOWN, 8+1+m_spells.size()*8); @@ -15342,7 +15342,7 @@ ASSERT(spellInfo); continue; } - if(idSchool == SpellSchools(spellInfo->School) && GetSpellCooldownDelay(unSpellId) < unTimeMs ) + if((idSchoolMask & GetSpellSchoolMask(spellInfo)) && GetSpellCooldownDelay(unSpellId) < unTimeMs ) { data << unSpellId; data << unTimeMs; // in m.secs Index: src/game/Player.h =================================================================== --- src/game/Player.h (revision 5635) +++ src/game/Player.h (working copy) @@ -1389,7 +1389,7 @@ return itr != m_spellCooldowns.end() && itr->second.end > t ? itr->second.end - t : 0; } void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time); - void ProhibitSpellScholl(SpellSchools idSchool, uint32 unTimeMs ); + void ProhibitSpellScholl(SpellSchoolMask idSchoolMask, uint32 unTimeMs ); void RemoveSpellCooldown(uint32 spell_id) { m_spellCooldowns.erase(spell_id); } void RemoveAllSpellCooldown(); void _LoadSpellCooldowns(QueryResult *result); @@ -1432,7 +1432,7 @@ bool IsGroupVisibleFor(Player* p) const; bool IsInSameGroupWith(Player const* p) const; - bool IsInSameRaidWith(Player const* p) const { return GetGroup() != NULL && GetGroup() == p->GetGroup(); } + bool IsInSameRaidWith(Player const* p) const { return p==this || GetGroup() != NULL && GetGroup() == p->GetGroup(); } void UninviteFromGroup(); static void RemoveFromGroup(Group* group, uint64 guid); void RemoveFromGroup() { RemoveFromGroup(GetGroup(),GetGUID()); } Index: src/game/SharedDefines.h =================================================================== --- src/game/SharedDefines.h (revision 5635) +++ src/game/SharedDefines.h (working copy) @@ -148,6 +148,27 @@ #define MAX_SPELL_SCHOOL 7 +enum SpellSchoolMask +{ + SPELL_SCHOOL_MASK_NONE = 0x00, // not exist + SPELL_SCHOOL_MASK_NORMAL = (1 << SPELL_SCHOOL_NORMAL), // PHYSICAL (Armor) + SPELL_SCHOOL_MASK_HOLY = (1 << SPELL_SCHOOL_HOLY ), + SPELL_SCHOOL_MASK_FIRE = (1 << SPELL_SCHOOL_FIRE ), + SPELL_SCHOOL_MASK_NATURE = (1 << SPELL_SCHOOL_NATURE), + SPELL_SCHOOL_MASK_FROST = (1 << SPELL_SCHOOL_FROST ), + SPELL_SCHOOL_MASK_SHADOW = (1 << SPELL_SCHOOL_SHADOW), + SPELL_SCHOOL_MASK_ARCANE = (1 << SPELL_SCHOOL_ARCANE) +}; + +inline SpellSchools GetFirstSchoolInMask(SpellSchoolMask mask) +{ + for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) + if(mask & (1 << i)) + return SpellSchools(i); + + return SPELL_SCHOOL_NORMAL; +} + enum ItemQualities { ITEM_QUALITY_POOR = 0, //GREY @@ -488,24 +509,6 @@ IMMUNE_SCHOOL_MAGIC = 126 }; -inline SpellSchools immuneToSchool(ImmuneToSchool immune) -{ - switch(immune) - { - case IMMUNE_SCHOOL_PHYSICAL: return SPELL_SCHOOL_NORMAL; - case IMMUNE_SCHOOL_HOLY: return SPELL_SCHOOL_HOLY; - case IMMUNE_SCHOOL_FIRE: return SPELL_SCHOOL_FIRE; - case IMMUNE_SCHOOL_NATURE: return SPELL_SCHOOL_NATURE; - case IMMUNE_SCHOOL_FROST: return SPELL_SCHOOL_FROST; - case IMMUNE_SCHOOL_SHADOW: return SPELL_SCHOOL_SHADOW; - case IMMUNE_SCHOOL_ARCANE: return SPELL_SCHOOL_ARCANE; - case IMMUNE_SCHOOL_MAGIC: break; - } - - assert(false); - return SPELL_SCHOOL_NORMAL; -} - enum Targets { TARGET_SELF = 1, Index: src/game/Spell.cpp =================================================================== --- src/game/Spell.cpp (revision 5636) +++ src/game/Spell.cpp (working copy) @@ -281,15 +281,16 @@ else m_attackType = BASE_ATTACK; break; } - m_spellSchool = SpellSchools(info->School); // Can be override for some spell (wand shoot for example) + m_spellSchoolMask = GetSpellSchoolMask(info); // Can be override for some spell (wand shoot for example) + if(m_attackType == RANGED_ATTACK) { // wand case if((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId()==TYPEID_PLAYER) { if(Item* pItem = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED)) - m_spellSchool = SpellSchools(pItem->GetProto()->Damage->DamageType); + m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetProto()->Damage->DamageType); } } @@ -992,13 +993,13 @@ struct ChainHealingOrder : public std::binary_function { const Unit* MainTarget; - ChainHealingOrder(const Unit* Target) : MainTarget(Target) {}; + ChainHealingOrder(Unit const* Target) : MainTarget(Target) {}; // functor for operator ">" - bool operator()(const Unit* _Left, const Unit* _Right) const + bool operator()(Unit const* _Left, Unit const* _Right) const { return (ChainHealingHash(_Left) < ChainHealingHash(_Right)); } - int32 ChainHealingHash(const Unit* Target) const + int32 ChainHealingHash(Unit const* Target) const { if (Target == MainTarget) return 0; @@ -3451,7 +3452,7 @@ return SPELL_FAILED_BAD_TARGETS; Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection()); - if( !target || !target->IsInSameGroupWith((Player*)m_caster) ) + if( !target || ((Player*)m_caster)==target || !target->IsInSameGroupWith((Player*)m_caster) ) return SPELL_FAILED_BAD_TARGETS; if( target->isInCombat() ) @@ -3691,9 +3692,9 @@ prevented_reason = SPELL_FAILED_CONFUSED; else if(m_caster->hasUnitState(UNIT_STAT_FLEEING)) prevented_reason = SPELL_FAILED_FLEEING; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) && m_spellInfo->School != SPELL_SCHOOL_NORMAL) + else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) && (GetSpellSchoolMask(m_spellInfo) & SPELL_SCHOOL_MASK_NORMAL)==0) prevented_reason = SPELL_FAILED_SILENCED; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) && m_spellInfo->School == SPELL_SCHOOL_NORMAL && !m_triggeredByAuraSpell) + else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) && (GetSpellSchoolMask(m_spellInfo) & SPELL_SCHOOL_MASK_NORMAL) && !m_triggeredByAuraSpell) prevented_reason = SPELL_FAILED_PACIFIED; // Attr must make flag drop spell totally immuned from all effects @@ -3707,8 +3708,8 @@ { if(itr->second) { - if( ((1 << itr->second->GetSpellProto()->School) & school_immune) || - ((1 << itr->second->GetSpellProto()->Mechanic) & mechanic_immune) || + if( (GetSpellSchoolMask(itr->second->GetSpellProto()) & school_immune) || + ((1 << itr->second->GetSpellProto()->Mechanic) & mechanic_immune) || ((1 << itr->second->GetSpellProto()->EffectMechanic[itr->second->GetEffIndex()]) & mechanic_immune)) continue; @@ -3723,11 +3724,11 @@ case SPELL_AURA_MOD_FEAR: return SPELL_FAILED_FLEEING; case SPELL_AURA_MOD_SILENCE: - if(m_spellInfo->School != SPELL_SCHOOL_NORMAL) + if((GetSpellSchoolMask(m_spellInfo) & SPELL_SCHOOL_MASK_NORMAL)==0) return SPELL_FAILED_SILENCED; break; case SPELL_AURA_MOD_PACIFY: - if(m_spellInfo->School == SPELL_SCHOOL_NORMAL) + if(GetSpellSchoolMask(m_spellInfo) & SPELL_SCHOOL_MASK_NORMAL) return SPELL_FAILED_PACIFIED; break; } @@ -3858,8 +3859,11 @@ else manaCost += float(m_spellInfo->ManaCostPercentage)/100.0f * m_caster->GetMaxPower(powerType); } - manaCost += m_caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+m_spellInfo->School); + SpellSchools school = GetFirstSchoolInMask(GetSpellSchoolMask(m_spellInfo)); + + manaCost += m_caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+school); + // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost) if ( m_spellInfo->manaCost > 0 && m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellInfo->SpellIconID == 1834 ) { @@ -3869,7 +3873,7 @@ if(Player* modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, manaCost, this); - manaCost*= (1.0f+m_caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+m_spellInfo->School)); + manaCost*= (1.0f+m_caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+school)); if (manaCost < 0) manaCost = 0; Index: src/game/Spell.h =================================================================== --- src/game/Spell.h (revision 5635) +++ src/game/Spell.h (working copy) @@ -407,7 +407,7 @@ Spell** m_triggeringContainer; // pointer to container with spell that has triggered us //Spell data - SpellSchools m_spellSchool; // Spell school (can be owerrided for some spells (wand shoot for example) + SpellSchoolMask m_spellSchoolMask; // Spell school (can be overwrite for some spells (wand shoot for example) WeaponAttackType m_attackType; // For weapon based attack bool m_canReflect; // can reflect this spell? bool m_autoRepeat; Index: src/game/SpellAuras.cpp =================================================================== --- src/game/SpellAuras.cpp (revision 5635) +++ src/game/SpellAuras.cpp (working copy) @@ -2815,12 +2815,6 @@ if(!caster || !caster->isAlive()) return; - if(m_modifier.m_miscvalue < SPELL_SCHOOL_NORMAL || m_modifier.m_miscvalue >= (1<second->GetSpellProto(); - if( ( (1 << spell->School) & school_mask) //Check for school mask + if((GetSpellSchoolMask(spell) & school_mask)//Check for school mask && !( spell->Attributes & 0x20000000) //Spells unaffected by invulnerability && !iter->second->IsPositive() //Don't remove positive spells - && spell->Id != GetId()) //Don't remove self + && spell->Id != GetId() ) //Don't remove self { m_target->RemoveAurasDueToSpell(spell->Id); if(Auras.empty()) @@ -3314,12 +3308,6 @@ void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real) { - if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_RESISTANCE_EXCLUS not valid"); - return; - } - bool positive = m_modifier.m_miscvalue2 == 0; for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) @@ -3335,12 +3323,6 @@ void Aura::HandleAuraModResistance(bool apply, bool Real) { - if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_RESISTANCE not valid"); - return; - } - bool positive = m_modifier.m_miscvalue2 == 0; for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) @@ -3356,12 +3338,6 @@ void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real) { - if(m_modifier.m_miscvalue < IMMUNE_SCHOOL_PHYSICAL || m_modifier.m_miscvalue > 127) - { - sLog.outError("WARNING: Misc Value for SPELL_AURA_MOD_BASE_RESISTANCE_PCT not valid"); - return; - } - // only players have base stats if(m_target->GetTypeId() != TYPEID_PLAYER) { @@ -3592,7 +3568,7 @@ if(m_target->GetTypeId() != TYPEID_PLAYER) return; - if(m_modifier.m_miscvalue != (1<DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, GetSpellProto(), false); + m_target->DealDamage(m_target, m_target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, GetSpellProto(), false); } void Aura::CleanupTriggeredSpells() Index: src/game/SpellEffects.cpp =================================================================== --- src/game/SpellEffects.cpp (revision 5635) +++ src/game/SpellEffects.cpp (working copy) @@ -255,7 +255,7 @@ } uint32 health = unitTarget->GetHealth(); - m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, false); + m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } void Spell::EffectEnvirinmentalDMG(uint32 i) @@ -268,9 +268,9 @@ // currently each eanemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i]; - m_caster->CalcAbsorbResist(m_caster,SpellSchools(m_spellInfo->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); - m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, SpellSchools(m_spellInfo->School), absorb, resist, false, 0, false); + m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false); if(m_caster->GetTypeId() == TYPEID_PLAYER) ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage); } @@ -937,7 +937,8 @@ uint32 classspell = itr->first; SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); - if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && spellInfo->School == SPELL_SCHOOL_FROST && + if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && + (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) && spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 ) { ((Player*)m_caster)->RemoveSpellCooldown(classspell); @@ -993,8 +994,8 @@ if(int32(m_caster->GetHealth()) > dmg) { - m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, dmg, SpellSchools(m_spellInfo->School), 0, 0, false, 0, false); - m_caster->DealDamage(m_caster,dmg,NULL,DIRECT_DAMAGE,SpellSchools(m_spellInfo->School),m_spellInfo,false); + m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, dmg, GetSpellSchoolMask(m_spellInfo), 0, 0, false, 0, false); + m_caster->DealDamage(m_caster,dmg,NULL,DIRECT_DAMAGE,GetSpellSchoolMask(m_spellInfo),m_spellInfo,false); int32 mana = dmg; @@ -1477,7 +1478,7 @@ if( // ignore positive and passive auras !iter->second->IsPositive() && !iter->second->IsPassive() && // ignore physical auras - iter->second->GetSpellProto()->School != SPELL_SCHOOL_NORMAL && + (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 && // ignore immunity persistent spells !( iter->second->GetSpellProto()->AttributesEx & 0x10000 ) ) { @@ -3526,8 +3527,8 @@ // Seal of Command - receive benefit from Spell Damage and Healing if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL) { - bonus += int32(0.20f*m_caster->SpellBaseDamageBonus((int32)(1<School))); - bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim((int32)(1<School), unitTarget)); + bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo))); + bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget)); } break; } @@ -3557,15 +3558,15 @@ // prevent negative damage uint32 eff_damage = uint32(bonus > 0 ? bonus : 0); - m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchool, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell); + m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell); if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK) // not send ranged miss/etc - m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchool, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg); + m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg); if(hitInfo & HITINFO_CRITICALHIT) criticalhit = true; - m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchool, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit); + m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit); if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg)) { @@ -3578,7 +3579,7 @@ } // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation - m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, true); + m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true); // Hemorrhage if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000)) @@ -3659,7 +3660,7 @@ // check if we can interrupt spell if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTURRUPT ) { - unitTarget->ProhibitSpellScholl(SpellSchools(unitTarget->m_currentSpells[i]->m_spellInfo->School), GetSpellDuration(m_spellInfo)); + unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo)); unitTarget->InterruptSpell(i,false); } } Index: src/game/SpellMgr.cpp =================================================================== --- src/game/SpellMgr.cpp (revision 5635) +++ src/game/SpellMgr.cpp (working copy) @@ -218,7 +218,7 @@ } // only hunter aspects have this (but not all aspects in hunter family) - if( spellInfo->activeIconID == 122 && spellInfo->School == SPELL_SCHOOL_NATURE && + if( spellInfo->activeIconID == 122 && (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NATURE) && (spellInfo->Attributes & 0x50000) != 0 && (spellInfo->Attributes & 0x9000010) == 0) { return SPELL_ASPECT; @@ -861,7 +861,7 @@ // Additional checks in case spell cast/hit/crit is the event // Check (if set) school, category, skill line, spell talent mask - if(spellProcEvent->schoolMask && (!procSpell || !procSpell->School || ((1<School) & spellProcEvent->schoolMask) == 0)) + if(spellProcEvent->schoolMask && (!procSpell || (GetSpellSchoolMask(procSpell) & spellProcEvent->schoolMask) == 0)) return false; if(spellProcEvent->category && (!procSpell || procSpell->Category != spellProcEvent->category)) return false; Index: src/game/SpellMgr.h =================================================================== --- src/game/SpellMgr.h (revision 5635) +++ src/game/SpellMgr.h (working copy) @@ -324,6 +324,12 @@ return (spellInfo->AttributesEx & 0x44); } +inline +SpellSchoolMask GetSpellSchoolMask(SpellEntry const* spellInfo) +{ + return SpellSchoolMask(1 << spellInfo->School); // in 2.4.* this will replaced by simple field access +} + // Spell affects related declarations (accessed using SpellMgr functions) struct SpellAffection { Index: src/game/StatSystem.cpp =================================================================== --- src/game/StatSystem.cpp (revision 5635) +++ src/game/StatSystem.cpp (working copy) @@ -146,7 +146,7 @@ //add dynamic flat mods AuraList const& mResbyIntellect = GetAurasByType(SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT); for(AuraList::const_iterator i = mResbyIntellect.begin();i != mResbyIntellect.end(); ++i) - if((*i)->GetModifier()->m_miscvalue & (1<GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) value += int32(GetStat(STAT_INTELLECT) * (*i)->GetModifier()->m_amount / 100.0f); value *= GetModifierValue(unitMod, TOTAL_PCT); Index: src/game/ThreatManager.cpp =================================================================== --- src/game/ThreatManager.cpp (revision 5635) +++ src/game/ThreatManager.cpp (working copy) @@ -31,7 +31,7 @@ //============================================================== // The pHatingUnit is not used yet -float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, SpellSchools pSchool, SpellEntry const *pThreatSpell) +float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) { if(pThreatSpell) { @@ -39,7 +39,7 @@ modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, pThreat); } - float threat = pHatedUnit->ApplyTotalThreatModifier(pThreat, pSchool); + float threat = pHatedUnit->ApplyTotalThreatModifier(pThreat, schoolMask); return threat; } @@ -325,7 +325,7 @@ //============================================================ -void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchools pSchool, SpellEntry const *pThreatSpell) +void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) { //function deals with adding threat and adding players and pets into ThreatList //mobs, NPCs, guards have ThreatList and HateOfflineList @@ -340,7 +340,7 @@ assert(getOwner()->GetTypeId()== TYPEID_UNIT); - float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, pSchool, pThreatSpell); + float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, schoolMask, pThreatSpell); HostilReference* ref = iThreatContainer.addThreat(pVictim, threat); // Ref is not in the online refs, search the offline refs next Index: src/game/ThreatManager.h =================================================================== --- src/game/ThreatManager.h (revision 5635) +++ src/game/ThreatManager.h (working copy) @@ -39,7 +39,7 @@ class ThreatCalcHelper { public: - static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, SpellSchools school = SPELL_SCHOOL_NORMAL, SpellEntry const *threatSpell = NULL); + static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); }; //============================================================== @@ -180,7 +180,7 @@ void clearReferences(); - void addThreat(Unit* pVictim, float threat, SpellSchools school = SPELL_SCHOOL_NORMAL, SpellEntry const *threatSpell = NULL); + void addThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); void modifyThreatPercent(Unit *pVictim, int32 pPercent); float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false); Index: src/game/Unit.cpp =================================================================== --- src/game/Unit.cpp (revision 5635) +++ src/game/Unit.cpp (working copy) @@ -422,7 +422,7 @@ RemoveSpellsCausingAura(auraType); } -void Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchools damageSchool, SpellEntry const *spellProto, bool durabilityLoss) +void 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()) return; @@ -463,7 +463,7 @@ if(!damage) { // Rage from physical damage received . - if(cleanDamage && cleanDamage->damage && damageSchool==SPELL_SCHOOL_NORMAL && pVictim->GetTypeId() == TYPEID_PLAYER && (pVictim->getPowerType() == POWER_RAGE)) + if(cleanDamage && cleanDamage->damage && (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) && pVictim->GetTypeId() == TYPEID_PLAYER && (pVictim->getPowerType() == POWER_RAGE)) ((Player*)pVictim)->RewardRage(cleanDamage->damage, 0, false); return; @@ -790,7 +790,7 @@ { if(spellProto && IsDamageToThreatSpell(spellProto)) damage *= 2; - pVictim->AddThreat(this, damage, damageSchool, spellProto); + pVictim->AddThreat(this, damage, damageSchoolMask, spellProto); } else // victim is a player { @@ -963,299 +963,288 @@ void Unit::DealDamageBySchool(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit, bool isTriggeredSpell) { + SpellSchoolMask schoolMask = GetSpellSchoolMask(spellInfo); // TODO this in only generic way, check for exceptions - DEBUG_LOG("DealDamageBySchool (BEFORE) SCHOOL %u >> DMG:%u", spellInfo->School, *damage); + DEBUG_LOG("DealDamageBySchool (BEFORE) SCHOOL %u (mask: %u) >> DMG:%u", GetFirstSchoolInMask(schoolMask), schoolMask, *damage); - // Per-school calc - switch (spellInfo->School) + // Physical damage school + if(schoolMask & SPELL_SCHOOL_MASK_NORMAL) { - // Physical damage school - case SPELL_SCHOOL_NORMAL: - { - // Calculate physical outcome - MeleeHitOutcome outcome = RollPhysicalOutcomeAgainst(pVictim, BASE_ATTACK, spellInfo); + // Calculate physical outcome + MeleeHitOutcome outcome = RollPhysicalOutcomeAgainst(pVictim, BASE_ATTACK, spellInfo); - //Used to store the Hit Outcome - cleanDamage->hitOutCome = outcome; + //Used to store the Hit Outcome + cleanDamage->hitOutCome = outcome; - // Return miss/evade first (sends miss message) - switch(outcome) + // Return miss/evade first (sends miss message) + switch(outcome) + { + case MELEE_HIT_EVADE: { - case MELEE_HIT_EVADE: - { - SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, SpellSchools(spellInfo->School), 0, 0,0,VICTIMSTATE_EVADES,0); - *damage = 0; - return; - } - case MELEE_HIT_MISS: - { - SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, SpellSchools(spellInfo->School), 0, 0,0,VICTIMSTATE_NORMAL,0); - *damage = 0; + SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, GetSpellSchoolMask(spellInfo), 0, 0,0,VICTIMSTATE_EVADES,0); + *damage = 0; + return; + } + case MELEE_HIT_MISS: + { + SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, GetSpellSchoolMask(spellInfo), 0, 0,0,VICTIMSTATE_NORMAL,0); + *damage = 0; - if(GetTypeId()== TYPEID_PLAYER) - ((Player*)this)->UpdateWeaponSkill(BASE_ATTACK); + if(GetTypeId()== TYPEID_PLAYER) + ((Player*)this)->UpdateWeaponSkill(BASE_ATTACK); - CastMeleeProcDamageAndSpell(pVictim,0,BASE_ATTACK,MELEE_HIT_MISS,spellInfo,isTriggeredSpell); - return; - } + CastMeleeProcDamageAndSpell(pVictim,0,BASE_ATTACK,MELEE_HIT_MISS,spellInfo,isTriggeredSpell); + return; } + } - // Hitinfo, Victimstate - uint32 hitInfo = HITINFO_NORMALSWING; - VictimState victimState = VICTIMSTATE_NORMAL; + // Hitinfo, Victimstate + uint32 hitInfo = HITINFO_NORMALSWING; + VictimState victimState = VICTIMSTATE_NORMAL; - //Calculate armor mitigation - uint32 damageAfterArmor; - damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage); - cleanDamage->damage += *damage - damageAfterArmor; - *damage = damageAfterArmor; + //Calculate armor mitigation + uint32 damageAfterArmor; + damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage); + cleanDamage->damage += *damage - damageAfterArmor; + *damage = damageAfterArmor; - uint32 blocked_amount = 0; + uint32 blocked_amount = 0; - // Classify outcome - switch (outcome) + // Classify outcome + switch (outcome) + { + case MELEE_HIT_BLOCK_CRIT: + case MELEE_HIT_CRIT: { - case MELEE_HIT_BLOCK_CRIT: - case MELEE_HIT_CRIT: + uint32 bonusDmg = *damage; + + // Apply crit_damage bonus + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, bonusDmg); + + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS); + for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) + if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) + bonusDmg = uint32(bonusDmg * ((*i)->GetModifier()->m_amount+100.0f)/100.0f); + + *damage += bonusDmg; + + // Resilience - reduce crit damage + if (pVictim->GetTypeId()==TYPEID_PLAYER) { - uint32 bonusDmg = *damage; + uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage); + cleanDamage->damage += resilienceReduction; + *damage -= resilienceReduction; + } - // Apply crit_damage bonus - if(Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, bonusDmg); + *crit = true; + hitInfo |= HITINFO_CRITICALHIT; - uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); - AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS); - for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) - if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - bonusDmg = uint32(bonusDmg * ((*i)->GetModifier()->m_amount+100.0f)/100.0f); + ModifyAuraState(AURA_STATE_CRIT, true); + StartReactiveTimer( REACTIVE_CRIT ); - *damage += bonusDmg; + if(getClass()==CLASS_HUNTER) + { + ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true); + StartReactiveTimer( REACTIVE_HUNTER_CRIT ); + } - // Resilience - reduce crit damage - if (pVictim->GetTypeId()==TYPEID_PLAYER) + if ( outcome == MELEE_HIT_BLOCK_CRIT ) + { + blocked_amount = uint32(pVictim->GetShieldBlockValue()); + if (blocked_amount >= *damage) { - uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage); - cleanDamage->damage += resilienceReduction; - *damage -= resilienceReduction; + hitInfo |= HITINFO_SWINGNOHITSOUND; + victimState = VICTIMSTATE_BLOCKS; + cleanDamage->damage += *damage; // To Help Calculate Rage + *damage = 0; } + else + { + // To Help Calculate Rage + cleanDamage->damage += blocked_amount; + *damage = *damage - blocked_amount; + } - *crit = true; - hitInfo |= HITINFO_CRITICALHIT; + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + } + break; + } + case MELEE_HIT_PARRY: + { + cleanDamage->damage += *damage; // To Help Calculate Rage + *damage = 0; + victimState = VICTIMSTATE_PARRY; - ModifyAuraState(AURA_STATE_CRIT, true); - StartReactiveTimer( REACTIVE_CRIT ); + // Counter-attack ( explained in Unit::DoAttackDamage() ) + { + // Get attack timers + float offtime = float(pVictim->getAttackTimer(OFF_ATTACK)); + float basetime = float(pVictim->getAttackTimer(BASE_ATTACK)); - if(getClass()==CLASS_HUNTER) + // Reduce attack time + if (pVictim->haveOffhandWeapon() && offtime < basetime) { - ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true); - StartReactiveTimer( REACTIVE_HUNTER_CRIT ); - } - - if ( outcome == MELEE_HIT_BLOCK_CRIT ) - { - blocked_amount = uint32(pVictim->GetShieldBlockValue()); - if (blocked_amount >= *damage) + float percent20 = pVictim->GetAttackTime(OFF_ATTACK) * 0.20; + float percent60 = 3 * percent20; + if(offtime > percent20 && offtime <= percent60) { - hitInfo |= HITINFO_SWINGNOHITSOUND; - victimState = VICTIMSTATE_BLOCKS; - cleanDamage->damage += *damage; // To Help Calculate Rage - *damage = 0; + pVictim->setAttackTimer(OFF_ATTACK, uint32(percent20)); } - else + else if(offtime > percent60) { - // To Help Calculate Rage - cleanDamage->damage += blocked_amount; - *damage = *damage - blocked_amount; + offtime -= 2 * percent20; + pVictim->setAttackTimer(OFF_ATTACK, uint32(offtime)); } - - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); } - break; - } - case MELEE_HIT_PARRY: - { - cleanDamage->damage += *damage; // To Help Calculate Rage - *damage = 0; - victimState = VICTIMSTATE_PARRY; - - // Counter-attack ( explained in Unit::DoAttackDamage() ) + else { - // Get attack timers - float offtime = float(pVictim->getAttackTimer(OFF_ATTACK)); - float basetime = float(pVictim->getAttackTimer(BASE_ATTACK)); - - // Reduce attack time - if (pVictim->haveOffhandWeapon() && offtime < basetime) + float percent20 = pVictim->GetAttackTime(BASE_ATTACK) * 0.20; + float percent60 = 3 * percent20; + if(basetime > percent20 && basetime <= percent60) { - float percent20 = pVictim->GetAttackTime(OFF_ATTACK) * 0.20; - float percent60 = 3 * percent20; - if(offtime > percent20 && offtime <= percent60) - { - pVictim->setAttackTimer(OFF_ATTACK, uint32(percent20)); - } - else if(offtime > percent60) - { - offtime -= 2 * percent20; - pVictim->setAttackTimer(OFF_ATTACK, uint32(offtime)); - } + pVictim->setAttackTimer(BASE_ATTACK, uint32(percent20)); } - else + else if(basetime > percent60) { - float percent20 = pVictim->GetAttackTime(BASE_ATTACK) * 0.20; - float percent60 = 3 * percent20; - if(basetime > percent20 && basetime <= percent60) - { - pVictim->setAttackTimer(BASE_ATTACK, uint32(percent20)); - } - else if(basetime > percent60) - { - basetime -= 2 * percent20; - pVictim->setAttackTimer(BASE_ATTACK, uint32(basetime)); - } + basetime -= 2 * percent20; + pVictim->setAttackTimer(BASE_ATTACK, uint32(basetime)); } } + } - // Update victim defense ? - if(pVictim->GetTypeId() == TYPEID_PLAYER) - ((Player*)pVictim)->UpdateDefense(); + // Update victim defense ? + if(pVictim->GetTypeId() == TYPEID_PLAYER) + ((Player*)pVictim)->UpdateDefense(); - // Set parry flags - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); + // Set parry flags + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); - // Mongoose bite - set only Counterattack here - if (pVictim->getClass() == CLASS_HUNTER) - { - pVictim->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true); - pVictim->StartReactiveTimer( REACTIVE_HUNTER_PARRY ); - } - else - { - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - } - break; + // Mongoose bite - set only Counterattack here + if (pVictim->getClass() == CLASS_HUNTER) + { + pVictim->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true); + pVictim->StartReactiveTimer( REACTIVE_HUNTER_PARRY ); } - case MELEE_HIT_DODGE: + else { - if(pVictim->GetTypeId() == TYPEID_PLAYER) - ((Player*)pVictim)->UpdateDefense(); + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); + } + break; + } + case MELEE_HIT_DODGE: + { + if(pVictim->GetTypeId() == TYPEID_PLAYER) + ((Player*)pVictim)->UpdateDefense(); - cleanDamage->damage += *damage; // To Help Calculate Rage - *damage = 0; - hitInfo |= HITINFO_SWINGNOHITSOUND; - victimState = VICTIMSTATE_DODGE; + cleanDamage->damage += *damage; // To Help Calculate Rage + *damage = 0; + hitInfo |= HITINFO_SWINGNOHITSOUND; + victimState = VICTIMSTATE_DODGE; - // Set dodge flags - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); + // Set dodge flags + pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); - // Overpower - if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR) - { - ((Player*)this)->AddComboPoints(pVictim, 1); - StartReactiveTimer( REACTIVE_OVERPOWER ); - } - - // Riposte - if (pVictim->getClass() != CLASS_ROGUE) - { - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - } - break; - } - case MELEE_HIT_BLOCK: + // Overpower + if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR) { - blocked_amount = uint32(pVictim->GetShieldBlockValue()); - if (blocked_amount >= *damage) - { - hitInfo |= HITINFO_SWINGNOHITSOUND; - victimState = VICTIMSTATE_BLOCKS; - cleanDamage->damage += *damage; // To Help Calculate Rage - *damage = 0; - } - else - { - // To Help Calculate Rage - cleanDamage->damage += blocked_amount; - *damage = *damage - blocked_amount; - } + ((Player*)this)->AddComboPoints(pVictim, 1); + StartReactiveTimer( REACTIVE_OVERPOWER ); + } + // Riposte + if (pVictim->getClass() != CLASS_ROGUE) + { pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - - break; - } - case MELEE_HIT_EVADE: // already processed early - case MELEE_HIT_MISS: // already processed early - case MELEE_HIT_GLANCING: - case MELEE_HIT_CRUSHING: - case MELEE_HIT_NORMAL: - break; + break; } + case MELEE_HIT_BLOCK: + { + blocked_amount = uint32(pVictim->GetShieldBlockValue()); + if (blocked_amount >= *damage) + { + hitInfo |= HITINFO_SWINGNOHITSOUND; + victimState = VICTIMSTATE_BLOCKS; + cleanDamage->damage += *damage; // To Help Calculate Rage + *damage = 0; + } + else + { + // To Help Calculate Rage + cleanDamage->damage += blocked_amount; + *damage = *damage - blocked_amount; + } - // Not correct, but this is what is used elsewhere to send misses and resists - if ( hitInfo & (HITINFO_ABSORB|HITINFO_RESIST|HITINFO_MISS) ) - SendAttackStateUpdate(hitInfo & (HITINFO_ABSORB|HITINFO_RESIST|HITINFO_MISS), pVictim, 1, SpellSchools(spellInfo->School), *damage, 0,0,victimState,blocked_amount); + pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); + pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - // do all damage=0 cases here - if(damage <= 0) - CastMeleeProcDamageAndSpell(pVictim,0,BASE_ATTACK,outcome,spellInfo,isTriggeredSpell); + break; + } + case MELEE_HIT_EVADE: // already processed early + case MELEE_HIT_MISS: // already processed early + case MELEE_HIT_GLANCING: + case MELEE_HIT_CRUSHING: + case MELEE_HIT_NORMAL: break; } - // Other schools - case SPELL_SCHOOL_HOLY: - case SPELL_SCHOOL_FIRE: - case SPELL_SCHOOL_NATURE: - case SPELL_SCHOOL_FROST: - case SPELL_SCHOOL_SHADOW: - case SPELL_SCHOOL_ARCANE: - // Calculate damage bonus - *damage = SpellDamageBonus(pVictim, spellInfo, *damage, SPELL_DIRECT_DAMAGE); + // Not correct, but this is what is used elsewhere to send misses and resists + if ( hitInfo & (HITINFO_ABSORB|HITINFO_RESIST|HITINFO_MISS) ) + SendAttackStateUpdate(hitInfo & (HITINFO_ABSORB|HITINFO_RESIST|HITINFO_MISS), pVictim, 1, GetSpellSchoolMask(spellInfo), *damage, 0,0,victimState,blocked_amount); - // Calculate critical bonus - if(spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE) + // do all damage=0 cases here + if(damage <= 0) + CastMeleeProcDamageAndSpell(pVictim,0,BASE_ATTACK,outcome,spellInfo,isTriggeredSpell); + } + // Other schools + else + { + // Calculate damage bonus + *damage = SpellDamageBonus(pVictim, spellInfo, *damage, SPELL_DIRECT_DAMAGE); + + // Calculate critical bonus + if(spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE) + { + // Calculate physical outcome + if(RollPhysicalOutcomeAgainst(pVictim, BASE_ATTACK, spellInfo) == MELEE_HIT_CRIT) { - // Calculate physical outcome - if(RollPhysicalOutcomeAgainst(pVictim, BASE_ATTACK, spellInfo) == MELEE_HIT_CRIT) + *crit = true; + *damage *= 2; + // Resilience - reduce crit damage by + if (pVictim->GetTypeId()==TYPEID_PLAYER) { - *crit = true; - *damage *= 2; - // Resilience - reduce crit damage by - if (pVictim->GetTypeId()==TYPEID_PLAYER) - { - uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage); - cleanDamage->damage += resilienceReduction; - *damage -= resilienceReduction; - } + uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage); + cleanDamage->damage += resilienceReduction; + *damage -= resilienceReduction; } } - else - *crit = SpellCriticalBonus(spellInfo, damage, pVictim); + } + else + *crit = SpellCriticalBonus(spellInfo, damage, pVictim); - if(*crit) - cleanDamage->hitOutCome = MELEE_HIT_CRIT; + if(*crit) + cleanDamage->hitOutCome = MELEE_HIT_CRIT; - // spell proc all magic damage==0 case in this function - if(*damage == 0) - { - // Procflags - uint32 procAttacker = PROC_FLAG_HIT_SPELL; - uint32 procVictim = (PROC_FLAG_STRUCK_SPELL|PROC_FLAG_TAKE_DAMAGE); + // spell proc all magic damage==0 case in this function + if(*damage == 0) + { + // Procflags + uint32 procAttacker = PROC_FLAG_HIT_SPELL; + uint32 procVictim = (PROC_FLAG_STRUCK_SPELL|PROC_FLAG_TAKE_DAMAGE); - ProcDamageAndSpell(pVictim, procAttacker, procVictim, 0, spellInfo, isTriggeredSpell); - } - - break; + ProcDamageAndSpell(pVictim, procAttacker, procVictim, 0, spellInfo, isTriggeredSpell); + } } // TODO this in only generic way, check for exceptions - DEBUG_LOG("DealDamageBySchool (AFTER) SCHOOL %u >> DMG:%u", spellInfo->School, *damage); + DEBUG_LOG("DealDamageBySchool (AFTER) SCHOOL %u (mask: %u) >> DMG:%u", GetFirstSchoolInMask(schoolMask), schoolMask, *damage); } uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell, bool useSpellDamage) @@ -1282,7 +1271,7 @@ uint32 absorb = 0; uint32 resist = 0; - CalcAbsorbResist(pVictim,SpellSchools(spellInfo->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + CalcAbsorbResist(pVictim,GetSpellSchoolMask(spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); // Only send absorbed message if we actually absorbed some damage if(damage > 0) @@ -1290,13 +1279,13 @@ // Handle absorb & resists if(damage <= absorb + resist && absorb) { - SendAttackStateUpdate(HITINFO_ABSORB|HITINFO_SWINGNOHITSOUND, pVictim, 1, SpellSchools(spellInfo->School),damage, absorb,resist,VICTIMSTATE_NORMAL,0); + SendAttackStateUpdate(HITINFO_ABSORB|HITINFO_SWINGNOHITSOUND, pVictim, 1, GetSpellSchoolMask(spellInfo),damage, absorb,resist,VICTIMSTATE_NORMAL,0); return 0; } else if(damage <= resist) // If we didn't fully absorb check if we fully resisted { ProcDamageAndSpell(pVictim, PROC_FLAG_TARGET_RESISTS, PROC_FLAG_RESIST_SPELL, 0, spellInfo,isTriggeredSpell); - SendAttackStateUpdate(HITINFO_RESIST|HITINFO_SWINGNOHITSOUND, pVictim, 1, SpellSchools(spellInfo->School), damage, absorb,resist,VICTIMSTATE_NORMAL,0); + SendAttackStateUpdate(HITINFO_RESIST|HITINFO_SWINGNOHITSOUND, pVictim, 1, GetSpellSchoolMask(spellInfo), damage, absorb,resist,VICTIMSTATE_NORMAL,0); return 0; } } @@ -1304,10 +1293,10 @@ // Send damage log sLog.outDetail("SpellNonMeleeDamageLog: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u,absorb is %u,resist is %u", GetGUIDLow(), GetTypeId(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damage, spellID, absorb,resist); - SendSpellNonMeleeDamageLog(pVictim, spellID, damage, SpellSchools(spellInfo->School), absorb, resist, false, 0, crit); + SendSpellNonMeleeDamageLog(pVictim, spellID, damage, GetSpellSchoolMask(spellInfo), absorb, resist, false, 0, crit); // Deal damage done - DealDamage(pVictim, (damage-absorb-resist), &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchools(spellInfo->School), spellInfo, true); + DealDamage(pVictim, (damage-absorb-resist), &cleanDamage, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellInfo), spellInfo, true); // Procflags uint32 procAttacker = PROC_FLAG_HIT_SPELL; @@ -1365,7 +1354,7 @@ pdamage = amount; //Calculate armor mitigation if it is a physical spell - if (spellProto->School == SPELL_SCHOOL_NORMAL) + if (GetSpellSchoolMask(spellProto) & SPELL_SCHOOL_MASK_NORMAL) { uint32 pdamageReductedArmor = CalcArmorReducedDamage(pVictim, pdamage); cleanDamage.damage += pdamage - pdamageReductedArmor; @@ -1382,7 +1371,7 @@ if (pVictim->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)pVictim)->GetDotDamageReduction(pdamage); - CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), DOT, pdamage, &absorb, &resist); + CalcAbsorbResist(pVictim, GetSpellSchoolMask(spellProto), DOT, pdamage, &absorb, &resist); sLog.outDetail("PeriodicAuraLog: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", GetGUIDLow(), GetTypeId(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), pdamage, spellProto->Id,absorb); @@ -1394,12 +1383,12 @@ data << uint32(1); data << uint32(mod->m_auraname); data << (uint32)pdamage; - data << (uint32)spellProto->School; + data << (uint32)spellProto->School; // will be mask in 2.4.x data << (uint32)absorb; data << (uint32)resist; SendMessageToSet(&data,true); - DealDamage(pVictim, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, SpellSchools(spellProto->School), spellProto, true); + DealDamage(pVictim, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, true); ProcDamageAndSpell(pVictim, PROC_FLAG_HIT_SPELL, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), spellProto); break; } @@ -1416,7 +1405,7 @@ uint32 pdamage = mod->m_amount > 0 ? mod->m_amount : 0; //Calculate armor mitigation if it is a physical spell - if (spellProto->School == SPELL_SCHOOL_NORMAL) + if (GetSpellSchoolMask(spellProto) & SPELL_SCHOOL_MASK_NORMAL) { uint32 pdamageReductedArmor = CalcArmorReducedDamage(pVictim, pdamage); cleanDamage.damage += pdamage - pdamageReductedArmor; @@ -1477,7 +1466,7 @@ if (pVictim->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)pVictim)->GetDotDamageReduction(pdamage); - CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), DOT, pdamage, &absorb, &resist); + CalcAbsorbResist(pVictim, GetSpellSchoolMask(spellProto), DOT, pdamage, &absorb, &resist); if(pVictim->GetHealth() < pdamage) pdamage = uint32(pVictim->GetHealth()); @@ -1485,8 +1474,8 @@ sLog.outDetail("PeriodicAuraLog: %u (TypeId: %u) health leech of %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", GetGUIDLow(), GetTypeId(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), pdamage, spellProto->Id,absorb); - SendSpellNonMeleeDamageLog(pVictim, spellProto->Id, pdamage, SpellSchools(spellProto->School), absorb, resist, false, 0); - DealDamage(pVictim, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, SpellSchools(spellProto->School), spellProto, false); + SendSpellNonMeleeDamageLog(pVictim, spellProto->Id, pdamage, GetSpellSchoolMask(spellProto), absorb, resist, false, 0); + DealDamage(pVictim, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), &cleanDamage, DOT, GetSpellSchoolMask(spellProto), spellProto, false); ProcDamageAndSpell(pVictim, PROC_FLAG_HIT_SPELL, PROC_FLAG_TAKE_DAMAGE, (pdamage <= absorb+resist) ? 0 : (pdamage-absorb-resist), spellProto); if (!pVictim->isAlive() && IsNonMeleeSpellCasted(false)) { @@ -1563,10 +1552,10 @@ } else { - SendSpellNonMeleeDamageLog(this, spellProto->Id, gain, SpellSchools(spellProto->School), 0, 0, false, 0, false); + SendSpellNonMeleeDamageLog(this, spellProto->Id, gain, GetSpellSchoolMask(spellProto), 0, 0, false, 0, false); CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - DealDamage(this, gain, &cleanDamage, NODAMAGE, SpellSchools(spellProto->School), spellProto, true); + DealDamage(this, gain, &cleanDamage, NODAMAGE, GetSpellSchoolMask(spellProto), spellProto, true); } } @@ -1622,7 +1611,7 @@ if(gain_amount) { int32 gain = ModifyPower(power,gain_amount); - pVictim->AddThreat(this, float(gain) * 0.5f, SpellSchools(spellProto->School), spellProto); + pVictim->AddThreat(this, float(gain) * 0.5f, GetSpellSchoolMask(spellProto), spellProto); } break; } @@ -1718,7 +1707,7 @@ AuraList const& mModTargetRes = GetAurasByType(SPELL_AURA_MOD_TARGET_RESISTANCE); for(AuraList::const_iterator i = mModTargetRes.begin(); i != mModTargetRes.end(); ++i) - if ((*i)->GetModifier()->m_miscvalue & int32(1 << SPELL_SCHOOL_NORMAL)) + if ((*i)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) armor += float((*i)->GetModifier()->m_amount); if (armor<0.0f) armor=0.0f; @@ -1739,19 +1728,19 @@ return (newdamage > 1) ? newdamage : 1; } -void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchools school, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist) +void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist) { if(!pVictim || !pVictim->isAlive() || !damage) return; // Magic damage, check for resists - if (school != SPELL_SCHOOL_NORMAL) + if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL)==0) { float tmpvalue2 = 0.0f; - tmpvalue2 += (float)pVictim->GetResistance(SpellSchools(school)); + tmpvalue2 += (float)pVictim->GetResistance(GetFirstSchoolInMask(schoolMask)); AuraList const& mModTargetRes = GetAurasByType(SPELL_AURA_MOD_TARGET_RESISTANCE); for(AuraList::const_iterator i = mModTargetRes.begin(); i != mModTargetRes.end(); ++i) - if ((*i)->GetModifier()->m_miscvalue & int32(1 << school)) + if ((*i)->GetModifier()->m_miscvalue & schoolMask) tmpvalue2 += (float)((*i)->GetModifier()->m_amount); tmpvalue2 *= (float)(0.15f / getLevel()); if (tmpvalue2 < 0.0f) @@ -1790,7 +1779,7 @@ { next = i; ++next; - if (((*i)->GetModifier()->m_miscvalue & int32(1<GetModifier()->m_miscvalue & schoolMask)==0) continue; // Cheat Death @@ -1870,7 +1859,7 @@ next = i; ++next; // check damage school mask - if(((*i)->GetModifier()->m_miscvalue & int32(1<< school))==0) + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) continue; int32 currentAbsorb; @@ -1906,7 +1895,7 @@ next = i; ++next; // check damage school mask - if(((*i)->GetModifier()->m_miscvalue & int32(1<< school))==0) + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) continue; // Damage can be splitted only if aura has an alive caster @@ -1922,10 +1911,10 @@ RemainingDamage -= currentAbsorb; - pVictim->SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, SpellSchools((*i)->GetSpellProto()->School), 0, 0, false, 0, false); + pVictim->SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, currentAbsorb, GetSpellSchoolMask((*i)->GetSpellProto()), 0, 0, false, 0, false); CleanDamage cleanDamage = CleanDamage(currentAbsorb, BASE_ATTACK, MELEE_HIT_NORMAL); - pVictim->DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, SpellSchools((*i)->GetSpellProto()->School), (*i)->GetSpellProto(), false); + pVictim->DealDamage(caster, currentAbsorb, &cleanDamage, DIRECT_DAMAGE, GetSpellSchoolMask((*i)->GetSpellProto()), (*i)->GetSpellProto(), false); } AuraList const& vSplitDamagePct = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_PCT); @@ -1934,7 +1923,7 @@ next = i; ++next; // check damage school mask - if(((*i)->GetModifier()->m_miscvalue & int32(1<< school))==0) + if(((*i)->GetModifier()->m_miscvalue & schoolMask)==0) continue; // Damage can be splitted only if aura has an alive caster @@ -1946,16 +1935,16 @@ RemainingDamage -= splitted; - pVictim->SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, SpellSchools((*i)->GetSpellProto()->School), 0, 0, false, 0, false); + pVictim->SendSpellNonMeleeDamageLog(caster, (*i)->GetSpellProto()->Id, splitted, GetSpellSchoolMask((*i)->GetSpellProto()), 0, 0, false, 0, false); CleanDamage cleanDamage = CleanDamage(splitted, BASE_ATTACK, MELEE_HIT_NORMAL); - pVictim->DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, SpellSchools((*i)->GetSpellProto()->School), (*i)->GetSpellProto(), false); + pVictim->DealDamage(caster, splitted, &cleanDamage, DIRECT_DAMAGE, GetSpellSchoolMask((*i)->GetSpellProto()), (*i)->GetSpellProto(), false); } *absorb = damage - RemainingDamage - *resist; } -void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchools damageType, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted, bool isTriggeredSpell) +void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted, bool isTriggeredSpell) { MeleeHitOutcome outcome; @@ -2010,7 +1999,7 @@ } //Calculate the damage after armor mitigation if SPELL_SCHOOL_NORMAL - if (damageType == SPELL_SCHOOL_NORMAL) + if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) { uint32 damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage); cleanDamage->damage += *damage - damageAfterArmor; @@ -2314,7 +2303,7 @@ if(*victimState != VICTIMSTATE_BLOCKS) { MeleeDamageBonus(pVictim, damage,attType,spellCasted); - CalcAbsorbResist(pVictim, damageType, DIRECT_DAMAGE, *damage-*blocked_amount, absorbDamage, resistDamage); + CalcAbsorbResist(pVictim, damageSchoolMask, DIRECT_DAMAGE, *damage-*blocked_amount, absorbDamage, resistDamage); } if (*absorbDamage) *hitInfo |= HITINFO_ABSORB; @@ -2447,32 +2436,32 @@ uint32 absorbed_dmg = 0; uint32 resisted_dmg = 0; - SpellSchools meleeSchool = GetMeleeDamageSchool(); + SpellSchoolMask meleeSchoolMask = GetMeleeDamageSchoolMask(); - if( meleeSchool == SPELL_SCHOOL_NORMAL && pVictim->IsImmunedToPhysicalDamage() ) + if( (meleeSchoolMask & SPELL_SCHOOL_MASK_NORMAL) && pVictim->IsImmunedToPhysicalDamage() ) { - SendAttackStateUpdate (HITINFO_MISS, pVictim, 1, meleeSchool, 0, 0, 0, VICTIMSTATE_IS_IMMUNE, 0); + SendAttackStateUpdate (HITINFO_MISS, pVictim, 1, meleeSchoolMask, 0, 0, 0, VICTIMSTATE_IS_IMMUNE, 0); return; } uint32 damage = CalculateDamage (attType, false); - DoAttackDamage (pVictim, &damage, &cleanDamage, &blocked_dmg, meleeSchool, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, attType); + DoAttackDamage (pVictim, &damage, &cleanDamage, &blocked_dmg, meleeSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, attType); if (hitInfo & HITINFO_MISS) //send miss - SendAttackStateUpdate (hitInfo, pVictim, 1, meleeSchool, damage, absorbed_dmg, resisted_dmg, victimState, blocked_dmg); + SendAttackStateUpdate (hitInfo, pVictim, 1, meleeSchoolMask, damage, absorbed_dmg, resisted_dmg, victimState, blocked_dmg); else { //do animation - SendAttackStateUpdate (hitInfo, pVictim, 1, meleeSchool, damage, absorbed_dmg, resisted_dmg, victimState, blocked_dmg); + SendAttackStateUpdate (hitInfo, pVictim, 1, meleeSchoolMask, damage, absorbed_dmg, resisted_dmg, victimState, blocked_dmg); if (damage > (absorbed_dmg + resisted_dmg + blocked_dmg)) damage -= (absorbed_dmg + resisted_dmg + blocked_dmg); else damage = 0; - DealDamage (pVictim, damage, &cleanDamage, DIRECT_DAMAGE, meleeSchool, NULL, true); + DealDamage (pVictim, damage, &cleanDamage, DIRECT_DAMAGE, meleeSchoolMask, NULL, true); if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive()) { @@ -2506,7 +2495,7 @@ // Talents AuraList const& mSpellCritSchool = GetAurasByType(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL); for(AuraList::const_iterator i = mSpellCritSchool.begin(); i != mSpellCritSchool.end(); ++i) - if((*i)->GetModifier()->m_miscvalue == -2 || ((*i)->GetModifier()->m_miscvalue & (int32)(1<School)) != 0) + if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellInfo)) crit_chance += (*i)->GetModifier()->m_amount; AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_CANNOT_BE_DODGED); @@ -2944,7 +2933,7 @@ if (!pVictim->isAlive()) return SPELL_MISS_NONE; - uint32 schoolMask = 1<School; + SpellSchoolMask schoolMask = GetSpellSchoolMask(spell); // PvP - PvE spell misschances per leveldif > 2 int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 7 : 11; int32 leveldif = int32(pVictim->getLevel()) - int32(getLevel()); @@ -3027,7 +3016,7 @@ Unit::AuraList const& mReflectSpellsSchool = pVictim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); for(Unit::AuraList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i) { - if((*i)->GetModifier()->m_miscvalue & int32(1 << spell->School)) + if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spell)) { int32 reflectchance = (*i)->GetModifier()->m_amount; if (reflectchance > 0 && roll_chance_i(reflectchance)) @@ -3071,7 +3060,7 @@ return SPELL_MISS_NONE; } - if (spell->School == SPELL_SCHOOL_NORMAL) + if (GetSpellSchoolMask(spell) & SPELL_SCHOOL_MASK_NORMAL) return SPELL_MISS_NONE; // TODO need use this code for spell hit result calculation @@ -3102,7 +3091,7 @@ bool isNormal = false; for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++) { - if (m_currentSpells[i] && m_currentSpells[i]->m_spellInfo->School == SPELL_SCHOOL_NORMAL) + if( m_currentSpells[i] && (GetSpellSchoolMask(m_currentSpells[i]->m_spellInfo) & SPELL_SCHOOL_MASK_NORMAL) ) { isNormal = true; break; @@ -4367,14 +4356,14 @@ } } -void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchools DamageType,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit) +void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit) { WorldPacket data(SMSG_SPELLNONMELEEDAMAGELOG, (16+31)); // we guess size data.append(target->GetPackGUID()); data.append(GetPackGUID()); data << uint32(SpellID); data << uint32(Damage-AbsorbedDamage-Resist-Blocked); - data << uint8(DamageType); // spell school + data << uint8(GetFirstSchoolInMask(damageSchoolMask)); // spell school data << uint32(AbsorbedDamage); // AbsorbedDamage data << uint32(Resist); // resist data << uint8(PhysicalDamage); @@ -4399,7 +4388,7 @@ SendMessageToSet(&data, true); } -void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchools DamageType, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount) +void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount) { sLog.outDebug("WORLD: Sending SMSG_ATTACKERSTATEUPDATE"); @@ -4412,7 +4401,7 @@ data << (uint8)SwingType; // count? // for(i = 0; i < SwingType; ++i) - data << (uint32)DamageType; + data << (uint32)GetFirstSchoolInMask(damageSchoolMask); data << (float)(Damage-AbsorbDamage-Resist-BlockedAmount); // still need to double check damage data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount); @@ -4626,7 +4615,7 @@ return; uint32 spellId = 0; - switch(procSpell->School) + switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) { case SPELL_SCHOOL_NORMAL: case SPELL_SCHOOL_HOLY: @@ -4666,7 +4655,7 @@ return; uint32 spellId = 0; - switch(procSpell->School) + switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) { case SPELL_SCHOOL_NORMAL: return; // ignore @@ -5014,7 +5003,7 @@ if(!castItem) return; - if(!procSpell || procSpell->School != SPELL_SCHOOL_FROST && procSpell->School != SPELL_SCHOOL_SHADOW ) + if(!procSpell || (GetSpellSchoolMask(procSpell) & (SPELL_SCHOOL_FROST | SPELL_SCHOOL_SHADOW))==0 ) return; int32 healamount = int32(damage * 2 / 100); @@ -6801,8 +6790,8 @@ if (CastingTime < 1500) CastingTime = 1500; // Taken/Done fixed damage bonus auras - int32 DoneAdvertisedBenefit = SpellBaseDamageBonus((int32)(1<School)); - int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim((int32)(1<School), pVictim); + int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto)); + int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); // Damage over Time spells bonus calculation float DotFactor = 1.0f; @@ -6847,7 +6836,7 @@ AuraList const& mModDamagePercentDone = this->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) { - if( ((*i)->GetModifier()->m_miscvalue & (int32)(1<School)) != 0 && + if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) && (*i)->GetSpellProto()->EquippedItemClass == -1 && // -1 == any item class (not wand then) (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 ) @@ -6866,7 +6855,7 @@ // ..taken AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) - if( ((*i)->GetModifier()->m_miscvalue & (int32)(1<School)) != 0 ) + if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) ) TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; // .. taken pct: scripted (increases damage of * against targets *) @@ -7205,11 +7194,11 @@ crit_chance = m_baseSpellCritChance; AuraList const& mSpellCritSchool = GetAurasByType(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL); for(AuraList::const_iterator i = mSpellCritSchool.begin(); i != mSpellCritSchool.end(); ++i) - if((*i)->GetModifier()->m_miscvalue == -2 || ((*i)->GetModifier()->m_miscvalue & (int32)(1<School)) != 0) + if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) crit_chance += (*i)->GetModifier()->m_amount; } else - crit_chance = GetFloatValue( PLAYER_SPELL_CRIT_PERCENTAGE1 + spellProto->School); + crit_chance = GetFloatValue( PLAYER_SPELL_CRIT_PERCENTAGE1 + GetFirstSchoolInMask(GetSpellSchoolMask(spellProto))); // percent done // only players use intelligence for critical chance computations @@ -7222,7 +7211,7 @@ // flat AuraList const& mAttackerSpellCrit = pVictim->GetAurasByType(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE); for(AuraList::const_iterator i = mAttackerSpellCrit.begin(); i != mAttackerSpellCrit.end(); ++i) - if((*i)->GetModifier()->m_miscvalue == -2 || ((*i)->GetModifier()->m_miscvalue & (int32)(1<School)) != 0) + if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) crit_chance += (*i)->GetModifier()->m_amount; if (pVictim->GetTypeId() == TYPEID_PLAYER) @@ -7297,13 +7286,13 @@ return healamount; bool Channeled = IsChanneledSpell(spellProto); - int32 AdvertisedBenefit = SpellBaseHealingBonus(1<School); + int32 AdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto)); uint32 CastingTime = GetSpellCastTime(sCastTimesStore.LookupEntry(spellProto->CastingTimeIndex)); if (CastingTime > 7000) CastingTime = 7000; if (CastingTime < 1500) CastingTime = 1500; // Healing Taken - AdvertisedBenefit += SpellBaseHealingBonusForVictim(1<School, pVictim); + AdvertisedBenefit += SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); //Blessing of Light dummy effects healing taken if (spellProto->SpellFamilyName == SPELLFAMILY_PALADIN && (spellProto->SpellFamilyFlags & 0x6000)) @@ -7491,7 +7480,7 @@ //If m_immuneToSchool type contain this school type, IMMUNE damage. SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr) - if(itr->type & uint32(1<School)) + if(itr->type & GetSpellSchoolMask(spellInfo)) return true; // charges dependent checks @@ -7500,7 +7489,7 @@ SpellImmuneList const& damageList = m_spellImmune[IMMUNITY_DAMAGE]; for (SpellImmuneList::const_iterator itr = damageList.begin(); itr != damageList.end(); ++itr) { - if(itr->type & uint32(1<School)) + if(itr->type & GetSpellSchoolMask(spellInfo)) { if(useCharges) { @@ -7556,8 +7545,8 @@ // not have spells with charges currently SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; for(SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr) - if(!(IsPositiveSpell(itr->spellId) && IsPositiveSpell(spellInfo->Id)) - && (itr->type & (1 << spellInfo->School))) + if( !(IsPositiveSpell(itr->spellId) && IsPositiveSpell(spellInfo->Id)) && + (itr->type & GetSpellSchoolMask(spellInfo)) ) return true; } @@ -8408,27 +8397,23 @@ //====================================================================== -float Unit::ApplyTotalThreatModifier(float threat, SpellSchools school) +float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask) { if(!HasAuraType(SPELL_AURA_MOD_THREAT)) return threat; - if(school >= MAX_SPELL_SCHOOL) - { - sLog.outError("Unit::ApplyTotalThreatModifier: Spell school with out-of-range value: %u",uint32(school)); - return threat; - } + SpellSchools school = GetFirstSchoolInMask(schoolMask); return threat * m_threatModifier[school]; } //====================================================================== -void Unit::AddThreat(Unit* pVictim, float threat, SpellSchools school, SpellEntry const *threatSpell) +void Unit::AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask, SpellEntry const *threatSpell) { // Only mobs can manage threat lists if(CanHaveThreatList()) - m_ThreatManager.addThreat(pVictim, threat, school, threatSpell); + m_ThreatManager.addThreat(pVictim, threat, schoolMask, threatSpell); } //====================================================================== @@ -9329,7 +9314,7 @@ { AuraList const& mRoot = GetAurasByType(SPELL_AURA_MOD_ROOT); for(AuraList::const_iterator i = mRoot.begin(); i != mRoot.end(); ++i) - if( (*i)->GetSpellProto()->School == SPELL_SCHOOL_FROST) + if( GetSpellSchoolMask((*i)->GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) return true; return false; } @@ -9519,18 +9504,18 @@ } } -SpellSchools Unit::GetMeleeDamageSchool() const +SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const { if(GetTypeId()==TYPEID_UNIT) { CreatureInfo const* cInfo = ((Creature*)this)->GetCreatureInfo(); if(cInfo) - return SpellSchools(cInfo->dmgschool); // checked at creature_template loading + return SpellSchoolMask(1 << cInfo->dmgschool); // checked at creature_template loading else - return SPELL_SCHOOL_NORMAL; + return SPELL_SCHOOL_MASK_NORMAL; } else - return SPELL_SCHOOL_NORMAL; + return SPELL_SCHOOL_MASK_NORMAL; } Player* Unit::GetSpellModOwner() Index: src/game/Unit.h =================================================================== --- src/game/Unit.h (revision 5635) +++ src/game/Unit.h (working copy) @@ -731,9 +731,9 @@ void Unmount(); uint16 GetMaxSkillValueForLevel() const { return getLevel()*5; } - void DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchools damageSchool, SpellEntry const *spellProto, bool durabilityLoss); + void DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellEntry const *spellProto, bool durabilityLoss); void DealDamageBySchool(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit = false, bool isTriggeredSpell = false); - void DoAttackDamage(Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchools damageType, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false); + void DoAttackDamage(Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false); void CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, WeaponAttackType attType, MeleeHitOutcome outcome, SpellEntry const *spellCasted = NULL, bool isTriggeredSpell = false); void ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 damage = 0, SpellEntry const *procSpell = NULL, bool isTriggeredSpell = false, WeaponAttackType attType = BASE_ATTACK); @@ -830,8 +830,8 @@ void DeMorph(); - void SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchools DamageType, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount); - void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchools DamageType,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); + void SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount); + void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo); void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, bool Run, uint32 Time); @@ -904,7 +904,7 @@ float GetCreateStat(Stats stat) const { return m_createStats[stat]; } void SetCurrentCastedSpell(Spell * pSpell); - virtual void ProhibitSpellScholl(SpellSchools /*idSchool*/, uint32 /*unTimeMs*/ ) { } + virtual void ProhibitSpellScholl(SpellSchoolMask /*idSchoolMask*/, uint32 /*unTimeMs*/ ) { } void InterruptSpell(uint32 spellType, bool withDelayed = true); // set withDelayed to true to account delayed spells as casted @@ -983,8 +983,8 @@ // Threat related methodes bool CanHaveThreatList() const; - void AddThreat(Unit* pVictim, float threat, SpellSchools school = SPELL_SCHOOL_NORMAL, SpellEntry const *threatSpell = NULL); - float ApplyTotalThreatModifier(float threat, SpellSchools school = SPELL_SCHOOL_NORMAL); + void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); void DeleteThreatList(); bool SelectHostilTarget(); void TauntApply(Unit* pVictim); @@ -1039,7 +1039,7 @@ // redefined in Creature uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage); - void CalcAbsorbResist(Unit *pVictim, SpellSchools school, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist); + void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist); float GetSpeed( UnitMoveType mtype ) const; float GetSpeedRate( UnitMoveType mtype ) const { return m_speed_rate[mtype]; } @@ -1129,7 +1129,7 @@ CharmInfo *m_charmInfo; - SpellSchools GetMeleeDamageSchool() const; + SpellSchoolMask GetMeleeDamageSchoolMask() const; MotionMaster i_motionMaster; bool m_moveRun; Index: src/shared/Database/DBCStructure.h =================================================================== --- src/shared/Database/DBCStructure.h (revision 5635) +++ src/shared/Database/DBCStructure.h (working copy) @@ -444,7 +444,7 @@ struct SpellEntry { uint32 Id; // 0 normally counted from 0 field (but some tools start counting from 1, check this before tool use for data view!) - uint32 School; // 1 + uint32 School; // 1 (will removed in 2.4.0) uint32 Category; // 2 // 3 not used uint32 Dispel; // 4