All pastes #944146 Raw Edit

Someone

public diff v1 · immutable
·published 2008-03-15 22:01 UTC
rendered paste body
+static float debugChance = 0.0f;+static int deep = 0;+void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage )+{+    deep ++;+    if (deep > 5)+    {+        sLog.outError("Prevent possible stack owerflow in Unit::ProcDamageAndSpellFor");+        if (procSpell)+            sLog.outError("  Spell %u", procSpell->Id);+        deep--;+        return;+    }+    // For melee/ranged based attack need update skills and set some Aura states+    if (procFlag & MELEE_BASED_TRIGGER_MASK)+    {+      // Update skills here for players+      if (GetTypeId() == TYPEID_PLAYER)+      {+        // On melee based hit/miss/resist need update skill (for victim and attacker)+        if (procExtra&(PROC_EX_NORMAL_HIT|PROC_EX_MISS|PROC_EX_RESIST))+        {+          if (pTarget->GetTypeId() != TYPEID_PLAYER && pTarget->GetCreatureType() != CREATURE_TYPE_CRITTER)+            ((Player*)this)->UpdateCombatSkills(pTarget, attType, MELEE_HIT_MISS, isVictim);+        }+        // Update defence if player is victim and parry/dodge/block+        if (isVictim && procExtra&(PROC_EX_DODGE|PROC_EX_PARRY|PROC_EX_BLOCK))+          ((Player*)this)->UpdateDefense();+      }+      // If exist crit/parry/dodge/block need update aura state (for victim and attacker)+      if (procExtra & (PROC_EX_CRITICAL_HIT|PROC_EX_PARRY|PROC_EX_DODGE|PROC_EX_BLOCK))+      {+        // for victim+        if (isVictim)+        {+          // if victim and dodge attack+          if (procExtra&PROC_EX_DODGE)+          {+            //Update AURA_STATE on dodge+            if (getClass() != CLASS_ROGUE) // skip Rogue Riposte+            {+             ModifyAuraState(AURA_STATE_DEFENSE, true);+             StartReactiveTimer( REACTIVE_DEFENSE );+            }+          }+          // if victim and parry attack+          if (procExtra & PROC_EX_PARRY)+          {+            // For Hunters only Counterattack (skip Mongoose bite)+            if (getClass() == CLASS_HUNTER)+            {+              ModifyAuraState(AURA_STATE_HUNTER_PARRY, true);+              StartReactiveTimer( REACTIVE_HUNTER_PARRY );+            }+            else+            {+              ModifyAuraState(AURA_STATE_DEFENSE, true);+              StartReactiveTimer( REACTIVE_DEFENSE );+            }+          }+          // if and victim block attack+          if (procExtra & PROC_EX_BLOCK)+          {+            ModifyAuraState(AURA_STATE_DEFENSE,true);+            StartReactiveTimer( REACTIVE_DEFENSE );+          }+        }+        else //For attacker+        {+          // Overpower on victim dodge+          if (procExtra&PROC_EX_DODGE && GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR)+          {+            ((Player*)this)->AddComboPoints(pTarget, 1);+            StartReactiveTimer( REACTIVE_OVERPOWER );+          }+          // Enable AURA_STATE_CRIT on crit+          if (procExtra & PROC_EX_CRITICAL_HIT)+          {+            ModifyAuraState(AURA_STATE_CRIT, true);+            StartReactiveTimer( REACTIVE_CRIT );+            if(getClass()==CLASS_HUNTER)+            {+              ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true);+              StartReactiveTimer( REACTIVE_HUNTER_CRIT );+            }+          }+        }+      }+    }++    RemoveSpellList removedSpells;+    ProcTriggeredList procTriggered;+    // Fill procTriggered list +    for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr)+    {+        SpellEntry const *spellProto = itr->second->GetSpellProto();+        if(spellProto==NULL || spellProto->procFlags==0)+           continue;+        // Aura info stored here+        Modifier *mod = itr->second->GetModifier();+        SpellProcEventEntry const *spellProcEvent = spellmgr.GetSpellProcEvent(spellProto->Id);++        // If not trigger by default and spellProcEvent==NULL - skip+        if (!isTriggerAura[mod->m_auraname] && spellProcEvent==NULL)+           continue;++        // Check spellProcEvent data requirements+        if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, spellProto->procFlags, procSpell, procFlag, procExtra, damage > 0))+            continue;+        // Aura added by spell can`t trogger from self (prevent drop cahres/do triggers)+        // But except periodic triggers (can triggered from self)+        if(procSpell && procSpell->Id == spellProto->Id && !(spellProto->procFlags&PROC_FLAG_ON_TAKE_PERIODIC))+            continue;+        // Check if current equipment allows aura to proc+        if(!isVictim && GetTypeId() == TYPEID_PLAYER)+        {+            if(spellProto->EquippedItemClass == ITEM_CLASS_WEAPON)+            {+                Item *item = NULL;+                if(attType == BASE_ATTACK)+                    item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);+                else if (attType == OFF_ATTACK)+                    item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);+                else+                    item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);++                if (!((Player*)this)->IsUseEquipedWeapon(attType==BASE_ATTACK))+                    continue;++                if(!item || item->IsBroken() || item->GetProto()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask))+                    continue;+            }+            else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR)+            {+                // Check if player is wearing shield+                Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND);+                if(!item || item->IsBroken() || item->GetProto()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask))+                    continue;+            }+        }+        // Get chance from spell+        float chance = (float)spellProto->procChance;+        // If in spellProcEvent exist custom chance, chance = spellProcEvent->customChance;+        if(spellProcEvent && spellProcEvent->customChance)+            chance = spellProcEvent->customChance;+        // If PPM exist calculate chance from PPM+        if(!isVictim && spellProcEvent && spellProcEvent->ppmRate != 0)+        {+            uint32 WeaponSpeed = GetAttackTime(attType);+            chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate);+        }+        // Apply chance modifer aura+        if(Player* modOwner = GetSpellModOwner())+            modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance);++        if(roll_chance_f(chance+debugChance))+            procTriggered.push_back( ProcTriggeredData(spellProcEvent, itr->second) );+    }+    // Handle effects proceed this time+    for(ProcTriggeredList::iterator i = procTriggered.begin(); i != procTriggered.end(); ++i)+    {+        // Some auras can be deleted in function called in this loop (except first, ofc)+        // Until storing auars in std::multimap to hard check deleting by another way+        if(i != procTriggered.begin())+        {+            bool found = false;+            AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair);+            AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);+            for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)+            {+                if(itr->second==i->triggeredByAura)+                {+                    found = true;+                    break;+                }+            }+            if(!found)+            {+//                sLog.outDebug("Spell aura %u (id:%u effect:%u) has been deleted before call spell proc event handler", i->triggeredByAura->GetModifier()->m_auraname, i->triggeredByAura_SpellPair.first, i->triggeredByAura_SpellPair.second);+//                sLog.outDebug("It can be deleted one from early proccesed auras:");+//                for(ProcTriggeredList::iterator i2 = procTriggered.begin(); i != i2; ++i2)+//                    sLog.outDebug("     Spell aura %u (id:%u effect:%u)", i->triggeredByAura->GetModifier()->m_auraname,i2->triggeredByAura_SpellPair.first,i2->triggeredByAura_SpellPair.second);+//                    sLog.outDebug("     <end of list>");+                continue;+            }+        }++        SpellProcEventEntry const *spellProcEvent = i->spellProcEvent;+        Aura *triggeredByAura = i->triggeredByAura;+        Modifier *auraModifier = triggeredByAura->GetModifier();+        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;++        // For players check spell cooldown+        if (cooldown && ((Player *)this)->HasSpellCooldown(spellInfo->Id))+            continue;++        switch(auraModifier->m_auraname)+        {+            case SPELL_AURA_PROC_TRIGGER_SPELL:+            {+                sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());+                // Don`t drop charge or add cooldown for not started trigger+                if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra))+                    continue;+                // For players add colldown if need+                if (cooldown)+                   ((Player *)this)->AddSpellCooldown(spellInfo->Id, 0, time(NULL) + cooldown);+                break;+            }+            case SPELL_AURA_PROC_TRIGGER_DAMAGE:+            {+                sLog.outDebug("ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", auraModifier->m_amount, spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());+                SpellNonMeleeDamage damageInfo(this, pTarget, spellInfo->Id, spellInfo->School);+                CalculateSpellDamage(&damageInfo, auraModifier->m_amount, spellInfo);+                SendSpellNonMeleeDamageLog(&damageInfo);+                DealSpellDamage(&damageInfo, true);+                break;+            }+            case SPELL_AURA_MANA_SHIELD:+            case SPELL_AURA_MOD_HASTE:+            case SPELL_AURA_DUMMY:+            case SPELL_AURA_DUMMY_3:+            {+                sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());+                HandleDummyAuraProc(pTarget, spellInfo, effIndex, damage, triggeredByAura, procSpell, procFlag, procExtra);+                // For players add colldown if need+                if (cooldown)+                   ((Player *)this)->AddSpellCooldown(spellInfo->Id, 0, time(NULL) + cooldown);+                break;+            }+            case SPELL_AURA_MOD_STUN:+                // Remove by default, but if charge exist drop it+                if (triggeredByAura->m_procCharges == 0)+                   removedSpells.push_back(triggeredByAura->GetId());+                break;+            case SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS:+                // Hunter's Mark (1-4 Rangs)+                if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && (spellInfo->SpellFamilyFlags&0x0000000000000400LL))+                {+                    uint32 basevalue = triggeredByAura->GetBasePoints()+1;+                    auraModifier->m_amount += basevalue/10;+                    if (auraModifier->m_amount > basevalue*4)+                        auraModifier->m_amount = basevalue*4;+                }+                break;+            case SPELL_AURA_MOD_CASTING_SPEED:+                // Skip melee hits or instant cast spells+                if (procSpell == NULL || GetSpellCastTime(sCastTimesStore.LookupEntry(procSpell->CastingTimeIndex)) == 0)+                    continue;+                break;+            case SPELL_AURA_REFLECT_SPELLS_SCHOOL:+                // Skip Melee hits and spells ws wrong school+                if (procSpell == NULL || (auraModifier->m_miscvalue & (1<<procSpell->School)) == 0)+                    continue;+                break;+            case SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT:+            case SPELL_AURA_MOD_POWER_COST_SCHOOL:+                // Skip melee hits and spells ws wrong school or zero cost+                if (procSpell == NULL || +                    (procSpell->manaCost == 0 && procSpell->ManaCostPercentage == 0) || // Cost check+                    (auraModifier->m_miscvalue & (1<<procSpell->School)) == 0)          // School check+                    continue;+                break;+            case SPELL_AURA_MECHANIC_IMMUNITY:+                // Compare mechanic+                if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)+                    continue;+                break;+            case SPELL_AURA_MOD_MECHANIC_RESISTANCE:+                // Compare mechanic+                if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue)+                    continue;+                break;+            default:+                // nothing do, just charges counter+                break;+       }+       // Remove charge (aura can be removed by triggers)+       // Not validate aura on check (for speed)+       if(triggeredByAura->m_procCharges > 0)+       {+          // need found aura on drop (can be dropped by triggers)+          AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair);+          AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair);+          for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr)+          {+             if(itr->second == i->triggeredByAura)+             {+                  triggeredByAura->m_procCharges -=1;+                  if (triggeredByAura->m_procCharges == 0) +                       removedSpells.push_back(triggeredByAura->GetId());+                 break;+             }+          }+       }+    }+    // Remove auras from removedAuras+    for(RemoveSpellList::const_iterator i = removedSpells.begin(); i != removedSpells.end();i++)+       RemoveAurasDueToSpell(*i);+    deep--;+}