rendered paste bodyIndex: 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 ); }