diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a3aa876ec..73208cd59 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1298,7 +1298,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss) } // TODO for melee need create structure as in -void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType) +void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType, const bool sittingVictim) { damageInfo->attacker = this; damageInfo->target = victim; @@ -1368,6 +1368,11 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType); + // If the victim was a sitting player and we didn't roll a miss, then crit. + if (sittingVictim && damageInfo->hitOutCome != MELEE_HIT_MISS) + { + damageInfo->hitOutCome = MELEE_HIT_CRIT; + } switch (damageInfo->hitOutCome) { case MELEE_HIT_EVADE: @@ -2199,6 +2204,9 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr if ((attType == BASE_ATTACK || attType == OFF_ATTACK) && !IsWithinLOSInMap(victim)) return; + // CombatStart puts the target into stand state, so we need to cache sit state here to know if we should crit later + const bool sittingVictim = victim->GetTypeId() == TYPEID_PLAYER && (victim->IsSitState() || victim->getStandState() == UNIT_STAND_STATE_SLEEP) ? true : false; + CombatStart(victim); RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MELEE_ATTACK); @@ -2212,9 +2220,9 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr { // attack can be redirected to another target victim = GetMeleeHitRedirectTarget(victim); - CalcDamageInfo damageInfo; - CalculateMeleeDamage(victim, 0, &damageInfo, attType); + CalculateMeleeDamage(victim, 0, &damageInfo, attType, sittingVictim); + // Send log damage message to client Unit::DealDamageMods(victim, damageInfo.damage, &damageInfo.absorb); SendAttackStateUpdate(&damageInfo); @@ -2359,7 +2367,9 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const { if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()) + { return MELEE_HIT_EVADE; + } int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim); int32 victimMaxSkillValueForLevel = victim->GetMaxSkillValueForLevel(this); @@ -2374,25 +2384,20 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy int32 sum = 0, tmp = 0; int32 roll = urand (0, 10000); - //LOG_DEBUG("server", "RollMeleeOutcomeAgainst: skill bonus of %d for attacker", skillBonus); +#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) + LOG_DEBUG("server", "RollMeleeOutcomeAgainst: skill bonus of %d for attacker", skillBonus); +#endif //LOG_DEBUG("server", "RollMeleeOutcomeAgainst: rolled %d, miss %d, dodge %d, parry %d, block %d, crit %d", // roll, miss_chance, dodge_chance, parry_chance, block_chance, crit_chance); tmp = miss_chance; if (tmp > 0 && roll < (sum += tmp)) - { - //LOG_DEBUG("server", "RollMeleeOutcomeAgainst: MISS"); - return MELEE_HIT_MISS; - } - - // always crit against a sitting target (except 0 crit chance) - if (victim->GetTypeId() == TYPEID_PLAYER && crit_chance > 0 && !victim->IsStandState()) { #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) - LOG_DEBUG("server", "RollMeleeOutcomeAgainst: CRIT (sitting victim)"); + LOG_DEBUG("server", "RollMeleeOutcomeAgainst: MISS"); #endif - return MELEE_HIT_CRIT; + return MELEE_HIT_MISS; } // Dodge chance diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 769812d5c..c0d5f5ab1 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1633,7 +1633,7 @@ public: void HandleEmoteCommand(uint32 anim_id); void AttackerStateUpdate (Unit* victim, WeaponAttackType attType = BASE_ATTACK, bool extra = false); - void CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK); + void CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK, const bool sittingVictim = false); void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss); void HandleProcExtraAttackFor(Unit* victim);