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