All pastes #939927 Raw Edit

Miscellany

public text v1 · immutable
·published 2008-03-12 17:47 UTC
rendered paste body
Index: game/Player.cpp
===================================================================
--- game/Player.cpp	(revision 5407)
+++ game/Player.cpp	(working copy)
@@ -4529,6 +4529,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 5407)
+++ game/Unit.cpp	(working copy)
@@ -1109,6 +1109,7 @@
             // Classify outcome
             switch (outcome)
             {
+                case MELEE_HIT_BLOCK_CRIT:
                 case MELEE_HIT_CRIT:
                 {
                     uint32 bonusDmg = *damage;
@@ -1139,18 +1140,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;
@@ -1214,14 +1227,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();
 
@@ -1250,14 +1255,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)
                     {
@@ -1957,7 +1954,6 @@
 
 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;
 
@@ -2027,6 +2023,7 @@
 
     switch (outcome)
     {
+        case MELEE_HIT_BLOCK_CRIT:
         case MELEE_HIT_CRIT:
         {
             //*hitInfo = 0xEA;
@@ -2081,11 +2078,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;
@@ -2158,7 +2179,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;
@@ -2190,12 +2211,6 @@
             return;
 
         case MELEE_HIT_BLOCK:
-            if( unavoidable )
-            {
-                outcome = MELEE_HIT_NORMAL;
-                break;
-            }
-
             *blocked_amount = pVictim->GetShieldBlockValue();
 
             if (pVictim->GetUnitBlockChance())
@@ -2500,6 +2515,15 @@
         }
     }
 
+    // pary can be avoided only by some abilites
+    float parry_chance = pVictim->GetUnitParryChance();
+    // block might be bypassed by it as well
+	float block_chance = pVictim->GetUnitBlockChance();
+
+    // cannot be dodged/parried/blocked
+    if(spellInfo->Attributes & 0x200000)
+        block_chance = parry_chance = dodge_chance = 0.0f;
+
     // Spellmods
     if(Player* modOwner = GetSpellModOwner())
         modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance);
@@ -2508,9 +2532,9 @@
     if (attType == RANGED_ATTACK) modHitChance = m_modRangedHitChance;
     else                          modHitChance = m_modMeleeHitChance;
 
-    DEBUG_LOG("PHYSICAL OUTCOME: hit %f crit %f miss %f dodge %f",modHitChance,crit_chance,miss_chance,dodge_chance);
+    DEBUG_LOG("PHYSICAL OUTCOME: hit %f crit %f miss %f dodge %f parry %f block %f",modHitChance,crit_chance,miss_chance,dodge_chance,parry_chance, block_chance);
 
-    return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(modHitChance),int32(dodge_chance*100));
+    return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(modHitChance),int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100), true);
 }
 
 MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const
@@ -2529,14 +2553,16 @@
 
     // stunned target cannot dodge and this is check in GetUnitDodgeChance() (returned 0 in this case)
     float dodge_chance = pVictim->GetUnitDodgeChance();
+    float block_chance = pVictim->GetUnitBlockChance();
+    float parry_chance = pVictim->GetUnitParryChance();
 
     // Useful if want to specify crit & miss chances for melee, else it could be removed
-    DEBUG_LOG("MELEE OUTCOME: hit %f crit %f miss %f dodge %f", modHitChance,crit_chance,miss_chance,dodge_chance);
+    DEBUG_LOG("MELEE OUTCOME: hit %f crit %f miss %f dodge %f parry %f block %f", modHitChance,crit_chance,miss_chance,dodge_chance,parry_chance,block_chance);
 
-    return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(modHitChance),int32(dodge_chance*100));
+    return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(modHitChance),int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100), false);
 }
 
-MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 hit_chance, int32 dodge_chance) const
+MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 hit_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const
 {
     if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode())
         return MELEE_HIT_EVADE;
@@ -2612,22 +2638,26 @@
     }
 
     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
     {
-        // cannot parry or block attacks from behind, but can from forward
-        float parry = pVictim->GetUnitParryChance();
         // Reduce parry chance by attacker expertise rating
         if (GetTypeId() == TYPEID_PLAYER)
-            parry-=((Player*)this)->GetExpertiseDodgeOrParryReduction();
-        int32 tmp = int32(parry * 100.0f);
+            parry_chance-=((Player*)this)->GetExpertiseDodgeOrParryReduction();
+        int32 tmp = int32(parry_chance * 100.0f);
         if (   (tmp > 0)                                    // check if unit _can_ parry
             && ((tmp -= skillBonus2) > 0)
             && (roll < (sum += tmp)))
@@ -2636,25 +2666,26 @@
             return MELEE_HIT_PARRY;
         }
 
-        tmp = (int32)(pVictim->GetUnitBlockChance()*100);
+        tmp = block_chance;
         if (   (tmp > 0)                                    // check if unit _can_ block
             && ((tmp -= skillBonus2) > 0)
             && (roll < (sum += tmp)))
         {
+			// Critical chance
+			tmp = crit_chance + skillBonus + modCrit;
+            if ( GetTypeId() == TYPEID_PLAYER && SpellCasted && 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;
 
@@ -2665,7 +2696,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 && !SpellCasted &&
+        (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);
@@ -2689,7 +2723,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;
@@ -4229,11 +4263,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 5407)
+++ game/Unit.h	(working copy)
@@ -421,7 +421,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
 {
@@ -701,7 +701,7 @@
         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, int32 dodge_chance ) const;
+        MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 hit_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) 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 ); }