All pastes #944150 Raw Edit

DiSlord

public cpp v1 · immutable
·published 2008-03-15 22:04 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--;}