diff --git a/Source/Game/Chat/Commands/MiscCommands.cs b/Source/Game/Chat/Commands/MiscCommands.cs index e4c700869..c3d5c1800 100644 --- a/Source/Game/Chat/Commands/MiscCommands.cs +++ b/Source/Game/Chat/Commands/MiscCommands.cs @@ -236,7 +236,7 @@ namespace Game.Chat { Unit.DealDamage(attacker, target, damage, null, DamageEffectType.Direct, SpellSchoolMask.Normal, null, false); if (target != attacker) - attacker.SendAttackStateUpdate(HitInfo.AffectsVictim, target, SpellSchoolMask.Normal, damage, 0, 0, VictimState.Hit, 0); + attacker.SendAttackStateUpdate(HitInfo.AffectsVictim, target, SpellSchoolMask.Normal, damage, 0, 0, VictimState.Hit, 0, 0); return true; } @@ -260,7 +260,7 @@ namespace Game.Chat uint resist = dmgInfo.GetResist(); Unit.DealDamageMods(attacker, target, ref damage, ref absorb); Unit.DealDamage(attacker, target, damage, null, DamageEffectType.Direct, schoolmask, null, false); - attacker.SendAttackStateUpdate(HitInfo.AffectsVictim, target, schoolmask, damage, absorb, resist, VictimState.Hit, 0); + attacker.SendAttackStateUpdate(HitInfo.AffectsVictim, target, schoolmask, damage, absorb, resist, VictimState.Hit, 0, 0); return true; } diff --git a/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index b91bcc635..bd9882bfd 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -560,7 +560,7 @@ namespace Game.Entities return AttackSwingErr.BadFacing; return null; - }; + } if (IsAttackReady(WeaponAttackType.BaseAttack)) { @@ -602,6 +602,19 @@ namespace Game.Entities } } + // Calculates the normalized rage amount per weapon swing + static uint CalcMeleeAttackRageGain(Unit attacker, WeaponAttackType attType) + { + if (attacker == null || (attType != WeaponAttackType.BaseAttack && attType != WeaponAttackType.OffAttack)) + return 0; + + uint rage = (uint)(attacker.GetBaseAttackTime(attType) / 1000.0f * 1.75f); + if (attType == WeaponAttackType.OffAttack) + rage /= 2; + + return rage; + } + public void AttackerStateUpdate(Unit victim, WeaponAttackType attType = WeaponAttackType.BaseAttack, bool extra = false) { if (HasUnitFlag(UnitFlags.Pacified)) @@ -670,6 +683,17 @@ namespace Game.Entities damageInfo.HitInfo |= HitInfo.FakeDamage; } + // Rage reward + if (this != victim && damageInfo.HitOutCome != MeleeHitOutcome.Miss && GetPowerType() == PowerType.Rage) + { + uint rageReward = CalcMeleeAttackRageGain(this, attType); + if (rageReward != 0) + { + damageInfo.HitInfo |= HitInfo.RageGain; + damageInfo.RageGained = (uint)RewardRage(rageReward); + } + } + SendAttackStateUpdate(damageInfo); _lastDamagedTargetGuid = victim.GetGUID(); @@ -689,7 +713,7 @@ namespace Game.Entities if (attType == WeaponAttackType.OffAttack) hitInfo |= HitInfo.OffHand; - SendAttackStateUpdate(hitInfo, victim, GetMeleeDamageSchoolMask(), 0, 0, 0, VictimState.Hit, 0); + SendAttackStateUpdate(hitInfo, victim, GetMeleeDamageSchoolMask(), 0, 0, 0, VictimState.Hit, 0, 0); } } } @@ -714,7 +738,7 @@ namespace Game.Entities return victim; } - public void SendAttackStateUpdate(HitInfo HitInfo, Unit target, SpellSchoolMask damageSchoolMask, uint Damage, uint AbsorbDamage, uint Resist, VictimState TargetState, uint BlockedAmount) + public void SendAttackStateUpdate(HitInfo HitInfo, Unit target, SpellSchoolMask damageSchoolMask, uint Damage, uint AbsorbDamage, uint Resist, VictimState TargetState, uint BlockedAmount, uint RageGained) { CalcDamageInfo dmgInfo = new(); dmgInfo.HitInfo = HitInfo; @@ -727,6 +751,7 @@ namespace Game.Entities dmgInfo.Resist = Resist; dmgInfo.TargetState = TargetState; dmgInfo.Blocked = BlockedAmount; + dmgInfo.RageGained = RageGained; SendAttackStateUpdate(dmgInfo); } @@ -751,6 +776,8 @@ namespace Game.Entities packet.VictimState = (byte)damageInfo.TargetState; packet.BlockAmount = (int)damageInfo.Blocked; + packet.RageGained = (int)damageInfo.RageGained; + packet.LogData.Initialize(damageInfo.Attacker); ContentTuningParams contentTuningParams = new(); @@ -1178,6 +1205,7 @@ namespace Game.Entities damageInfo.Blocked = 0; damageInfo.HitInfo = 0; damageInfo.TargetState = 0; + damageInfo.RageGained = 0; damageInfo.AttackType = attackType; damageInfo.ProcAttacker = new ProcFlagsInit(); diff --git a/Source/Game/Entities/Unit/Unit.Fields.cs b/Source/Game/Entities/Unit/Unit.Fields.cs index c5b0835d5..6674c0f6f 100644 --- a/Source/Game/Entities/Unit/Unit.Fields.cs +++ b/Source/Game/Entities/Unit/Unit.Fields.cs @@ -430,6 +430,7 @@ namespace Game.Entities public uint Blocked { get; set; } public HitInfo HitInfo { get; set; } public VictimState TargetState { get; set; } + public uint RageGained { get; set; } // Helper public WeaponAttackType AttackType { get; set; } diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 3c6089e1d..03dc9345c 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -2661,16 +2661,6 @@ namespace Game.Entities } } - // Rage from Damage made (only from direct weapon damage) - if (attacker != null && cleanDamage != null && (cleanDamage.attackType == WeaponAttackType.BaseAttack || cleanDamage.attackType == WeaponAttackType.OffAttack) && damagetype == DamageEffectType.Direct && attacker != victim && attacker.GetPowerType() == PowerType.Rage) - { - uint rage = (uint)(attacker.GetBaseAttackTime(cleanDamage.attackType) / 1000.0f * 1.75f); - if (cleanDamage.attackType == WeaponAttackType.OffAttack) - rage /= 2; - - attacker.RewardRage(rage); - } - if (damageDone == 0) return 0; @@ -3284,7 +3274,7 @@ namespace Game.Entities } } - public void RewardRage(uint baseRage) + public int RewardRage(uint baseRage) { float addRage = baseRage; @@ -3293,7 +3283,7 @@ namespace Game.Entities addRage *= WorldConfig.GetFloatValue(WorldCfg.RatePowerRageIncome); - ModifyPower(PowerType.Rage, (int)(addRage * 10)); + return ModifyPower(PowerType.Rage, (int)(addRage * 10), false); } public float GetPPMProcChance(uint WeaponSpeed, float PPM, SpellInfo spellProto)