All pastes #917572 Raw Edit

Someone

public text v1 · immutable
#917572 ·published 2008-02-25 14:43 UTC
rendered paste body
Index: game/Player.cpp
===================================================================
--- game/Player.cpp	(revision 5306)
+++ game/Player.cpp	(working copy)
@@ -4532,6 +4532,7 @@
         case MELEE_HIT_DODGE:
         case MELEE_HIT_PARRY:
         case MELEE_HIT_BLOCK:
+        case MELEE_HIT_BLOCK_CRIT:
             return;
 
         default:
Index: game/Unit.cpp
===================================================================
--- game/Unit.cpp	(revision 5306)
+++ game/Unit.cpp	(working copy)
@@ -1107,6 +1107,7 @@
             // Classify outcome
             switch (outcome)
             {
+                case MELEE_HIT_BLOCK_CRIT:
                 case MELEE_HIT_CRIT:
                 {
                     uint32 bonusDmg = *damage;
@@ -1137,18 +1138,30 @@
                         StartReactiveTimer( REACTIVE_HUNTER_CRIT );
                     }
 
+                    if ( outcome == MELEE_HIT_BLOCK_CRIT )
+                    {
+                        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;
+                        }
+
+                            pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true);
+                            pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
+                        }
                     break;
                 }
                 case MELEE_HIT_PARRY:
                 {
-                    // this special attack can't be parryed
-                    if ( spellInfo->Attributes & 0x200000 )
-                    {
-                        outcome = MELEE_HIT_NORMAL;
-                        cleanDamage->hitOutCome = MELEE_HIT_NORMAL;
-                        break;
-                    }
-
                     cleanDamage->damage += *damage;         // To Help Calculate Rage
                     *damage = 0;
                     victimState = VICTIMSTATE_PARRY;
@@ -1212,14 +1225,6 @@
                 }
                 case MELEE_HIT_DODGE:
                 {
-                    // this special attack can't be dodged
-                    if ( spellInfo->Attributes & 0x200000 )
-                    {
-                        outcome = MELEE_HIT_NORMAL;
-                        cleanDamage->hitOutCome = MELEE_HIT_NORMAL;
-                        break;
-                    }
-
                     if(pVictim->GetTypeId() == TYPEID_PLAYER)
                         ((Player*)pVictim)->UpdateDefense();
 
@@ -1248,14 +1253,6 @@
                 }
                 case MELEE_HIT_BLOCK:
                 {
-                    // this special attack can't be blocked
-                    if ( spellInfo->Attributes & 0x200000 )
-                    {
-                        outcome = MELEE_HIT_NORMAL;
-                        cleanDamage->hitOutCome = MELEE_HIT_NORMAL;
-                        break;
-                    }
-
                     blocked_amount = uint32(pVictim->GetShieldBlockValue());
                     if (blocked_amount >= *damage)
                     {
@@ -1940,13 +1937,12 @@
 
 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)
 {
-    bool unavoidable = spellCasted && (spellCasted->Attributes & 0x200000);
 
     MeleeHitOutcome outcome;
 
     // If is casted Melee spell, calculate like physical
     if(!spellCasted)
-        outcome = RollMeleeOutcomeAgainst (pVictim, attType);
+        outcome = RollMeleeOutcomeAgainst (pVictim, attType, NULL);
     else
         outcome = RollPhysicalOutcomeAgainst (pVictim, attType, spellCasted);
 
@@ -2010,6 +2006,7 @@
 
     switch (outcome)
     {
+        case MELEE_HIT_BLOCK_CRIT:
         case MELEE_HIT_CRIT:
         {
             //*hitInfo = 0xEA;
@@ -2063,11 +2060,35 @@
                 StartReactiveTimer( REACTIVE_HUNTER_CRIT );
             }
 
+            if ( outcome == MELEE_HIT_BLOCK_CRIT )
+            {
+                *blocked_amount = pVictim->GetShieldBlockValue();
+
+                if (pVictim->GetUnitBlockChance())
+                    pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD);
+                else
+                    pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED);
+
+                //Only set VICTIMSTATE_BLOCK on a full block
+                if (*blocked_amount >= uint32(*damage))
+                {
+                    *victimState = VICTIMSTATE_BLOCKS;
+                    *blocked_amount = uint32(*damage);
+                }
+
+                if(pVictim->GetTypeId() == TYPEID_PLAYER)
+                    ((Player*)pVictim)->UpdateDefense();
+
+                pVictim->ModifyAuraState(AURA_STATE_DEFENSE,true);
+                pVictim->StartReactiveTimer( REACTIVE_DEFENSE );
+                break;
+            }
+
             pVictim->HandleEmoteCommand(EMOTE_ONESHOT_WOUNDCRITICAL);
             break;
         }
         case MELEE_HIT_PARRY:
-            if(attType == RANGED_ATTACK || unavoidable)     //range attack - no parry
+            if(attType == RANGED_ATTACK)     //range attack - no parry
             {
                 outcome = MELEE_HIT_NORMAL;
                 break;
@@ -2140,7 +2161,7 @@
             return;
 
         case MELEE_HIT_DODGE:
-            if(attType == RANGED_ATTACK || unavoidable )    //range attack - no dodge
+            if(attType == RANGED_ATTACK)    //range attack - no dodge
             {
                 outcome = MELEE_HIT_NORMAL;
                 break;
@@ -2172,12 +2193,6 @@
             return;
 
         case MELEE_HIT_BLOCK:
-            if( unavoidable )
-            {
-                outcome = MELEE_HIT_NORMAL;
-                break;
-            }
-
             *blocked_amount = pVictim->GetShieldBlockValue();
 
             if (pVictim->GetUnitBlockChance())
@@ -2474,10 +2489,10 @@
 
     DEBUG_LOG("PHYSICAL OUTCOME: hit %f crit %f miss %u",modHitChance,crit_chance,miss_chance);
 
-    return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance * 100 ), miss_chance, int32(modHitChance));
+    return RollMeleeOutcomeAgainst(pVictim, attType, spellInfo, int32(crit_chance * 100 ), miss_chance, int32(modHitChance));
 }
 
-MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType) const
+MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo) const
 {
     // This is only wrapper
 
@@ -2494,10 +2509,10 @@
     // Useful if want to specify crit & miss chances for melee, else it could be removed
     DEBUG_LOG("MELEE OUTCOME: hit %f crit %u miss %u", modHitChance,crit_chance,miss_chance);
 
-    return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance * 100 ), miss_chance, int32(modHitChance));
+    return RollMeleeOutcomeAgainst(pVictim, attType, spellInfo, int32(crit_chance * 100 ), miss_chance, int32(modHitChance));
 }
 
-MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 hit_chance) const
+MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo, int32 crit_chance, int32 miss_chance, int32 hit_chance) const
 {
     if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
         return MELEE_HIT_EVADE;
@@ -2560,6 +2575,9 @@
     // stunned target cannot dodge and this is check in GetUnitDodgeChance()
     float dodge = pVictim->GetUnitDodgeChance();
 
+    if ( spellInfo && spellInfo->Attributes & 0x200000 )
+        dodge = 0;
+
     // Reduce dodge chance by attacker expertise rating
     if (GetTypeId() == TYPEID_PLAYER)
         dodge-=((Player*)this)->GetExpertiseDodgeOrParryReduction();
@@ -2573,13 +2591,23 @@
     }
 
     int32   modCrit = 0;
+    // reduce crit chance from Rating for players
+    if (pVictim->GetTypeId()==TYPEID_PLAYER)
+    {
+        if (attType==RANGED_ATTACK)
+            modCrit -= int32(((Player*)pVictim)->GetRatingBonusValue(PLAYER_FIELD_CRIT_TAKEN_RANGED_RATING)*100);
+        else
+            modCrit -= int32(((Player*)pVictim)->GetRatingBonusValue(PLAYER_FIELD_CRIT_TAKEN_MELEE_RATING)*100);
+    }
 
     // check if attack comes from behind
     if (!pVictim->HasInArc(M_PI,this))
     {
-        // ASSUME +10% crit from behind
         DEBUG_LOG ("RollMeleeOutcomeAgainst: attack came from behind.");
-        modCrit += 1000;
+    }	
+    else if ( spellInfo && (spellInfo->Attributes & 0x200000))
+    {
+        DEBUG_LOG ("RollMeleeOutcomeAgainst: melee spell that cannot be evaded.");
     }
     else
     {
@@ -2602,20 +2630,21 @@
             && ((tmp -= skillBonus2) > 0)
             && (roll < (sum += tmp)))
         {
+			// Critical chance
+			tmp = crit_chance + skillBonus + modCrit;
+            if ( GetTypeId() == TYPEID_PLAYER && spellInfo && tmp > 0 )
+            {
+				if ( roll_chance_f(tmp/100))
+                {
+                    DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCKED CRIT");
+                    return MELEE_HIT_BLOCK_CRIT;
+                }
+            } 
             DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCK <%d, %d)", sum-tmp, sum);
             return MELEE_HIT_BLOCK;
         }
     }
 
-    // reduce crit chance from Rating for players
-    if (pVictim->GetTypeId()==TYPEID_PLAYER)
-    {
-        if (attType==RANGED_ATTACK)
-            modCrit -= int32(((Player*)pVictim)->GetRatingBonusValue(PLAYER_FIELD_CRIT_TAKEN_RANGED_RATING)*100);
-        else
-            modCrit -= int32(((Player*)pVictim)->GetRatingBonusValue(PLAYER_FIELD_CRIT_TAKEN_MELEE_RATING)*100);
-    }
-
     // Critical chance
     tmp = crit_chance + skillBonus + modCrit;
 
@@ -2626,7 +2655,10 @@
     }
 
     // Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon)
-    if( attType != RANGED_ATTACK && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet()) && pVictim->GetTypeId() != TYPEID_PLAYER && getLevel() < pVictim->getLevel() )
+    if( attType != RANGED_ATTACK && !spellInfo &&
+        (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet()) &&
+        pVictim->GetTypeId() != TYPEID_PLAYER && !((Creature*)pVictim)->isPet() &&
+        getLevel() < pVictim->getLevel() )
     {
         // cap possible value (with bonuses > max skill)
         int32 skill = GetWeaponSkillValue(attType);
@@ -2650,7 +2682,7 @@
     tmp = tmp > tmpmax ? tmpmax : tmp;
     // tmp = mob's level * 5 - player's current defense skill
     tmp = GetMaxSkillValueForLevel() - tmp;
-    if (GetTypeId() != TYPEID_PLAYER && (tmp >= 15))
+    if (GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->isPet() && (tmp >= 15))
     {
         // add 2% chance per lacking skill point, min. is 15%
         tmp = tmp * 200 - 1500;
@@ -4193,11 +4225,17 @@
                 procAttacker = PROC_FLAG_MISS;
             }
             break;
+        case MELEE_HIT_BLOCK_CRIT:
         case MELEE_HIT_CRIT:
             if(spellCasted && attType == BASE_ATTACK)
             {
                 procAttacker |= PROC_FLAG_CRIT_SPELL;
                 procVictim   |= PROC_FLAG_STRUCK_CRIT_SPELL;
+                if ( outcome == MELEE_HIT_BLOCK_CRIT )
+                {
+                    procVictim |= PROC_FLAG_BLOCK;
+                    procAttacker |= PROC_FLAG_TARGET_BLOCK;
+                }
             }
             else if(attType == BASE_ATTACK || attType == OFF_ATTACK)
             {
Index: game/Unit.h
===================================================================
--- game/Unit.h	(revision 5306)
+++ game/Unit.h	(working copy)
@@ -419,7 +419,7 @@
 enum MeleeHitOutcome
 {
     MELEE_HIT_EVADE, MELEE_HIT_MISS, MELEE_HIT_DODGE, MELEE_HIT_BLOCK, MELEE_HIT_PARRY,
-    MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL
+    MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL, MELEE_HIT_BLOCK_CRIT
 };
 struct CleanDamage
 {
@@ -698,8 +698,8 @@
         float GetWeaponProcChance() const;
         float GetPPMProcChance(uint32 WeaponSpeed, float PPM) const;
         MeleeHitOutcome RollPhysicalOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo);
-        MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType) const;
-        MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 hit_chance) const;
+        MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo) const;
+        MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo, int32 crit_chance, int32 miss_chance, int32 hit_chance) const;
 
         bool isVendor()       const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR ); }
         bool isTrainer()      const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER ); }