/// <summary> /// Deals environmental damage to this Unit (cannot be resisted) /// </summary> public virtual void DealEnvironmentalDamage(EnviromentalDamageType dmgType, int amount) { DoRawDamage(new SimpleDamageAction { Damage = amount, Victim = this }); CombatLogHandler.SendEnvironmentalDamage(this, dmgType, (uint)amount); }
/// <summary> /// Deals environmental damage to this Unit (cannot be resisted) /// </summary> public virtual void DealEnvironmentalDamage(EnviromentalDamageType dmgType, int amount) { //if (dmgType == EnviromentalDamageType.Fall) //{ // amount -= (int)(SafeFall * (amount / 100f)); //} DoRawDamage(new SimpleDamageAction { Damage = amount, Victim = this }); CombatLogHandler.SendEnvironmentalDamage(this, dmgType, (uint)amount); }
public override void Process(CmdTrigger <RealmServerCmdArgs> trigger) { var unkBool = trigger.Text.NextBool(); var flags = trigger.Text.NextEnum(SpellLogFlags.SpellLogFlag_0x1); var spell = trigger.Text.NextEnum(SpellId.ClassSkillFireballRank1); var damage = trigger.Text.NextUInt(10); var overkill = trigger.Text.NextUInt(0); var schools = trigger.Text.NextEnum(DamageSchoolMask.Fire); var absorbed = trigger.Text.NextUInt(0); var resisted = trigger.Text.NextUInt(0); var blocked = trigger.Text.NextUInt(0); CombatLogHandler.SendMagicDamage(trigger.Args.Target, trigger.Args.User, spell, damage, overkill, schools, absorbed, resisted, blocked, unkBool, flags); }
/// <summary> /// Strikes the target /// </summary> public void DoStrike() { if (Damage > 0) { var level = Attacker.Level; var res = Victim.GetResistance(UsedSchool) - Attacker.GetTargetResistanceMod(UsedSchool); if (res > 0) { ProcHitFlags |= ProcHitFlags.Resist; // This formula only applies for armor if (UsedSchool == DamageSchool.Physical) { if (level < 60) { ResistPct = (res / (res + 400f + 85f * level)) * 100f; } else { ResistPct = (res / (res - 22167.5f + 467.5f * level)) * 100f; } } else { // Magical damageschool ResistPct = Victim.GetResistChancePct(Attacker, UsedSchool); } } else { ResistPct = 0; } if (ResistPct > 75) { ResistPct = 75; } if (ResistPct < 0) { ResistPct = 0; } Victim.DeathPrevention++; Attacker.DeathPrevention++; try { // add mods and call events AddDamageMods(); Victim.OnDefend(this); Attacker.OnAttack(this); Resisted = MathUtil.RoundInt(ResistPct * Damage / 100f); if (Absorbed > 0) { HitFlags |= HitFlags.AbsorbType1 | HitFlags.AbsorbType2; ProcHitFlags |= ProcHitFlags.Absorb; } else { Absorbed = Resisted = 0; } if (Weapon == Attacker.OffHandWeapon) { HitFlags |= HitFlags.OffHand; } Victim.DoRawDamage(this); } finally { Victim.DeathPrevention--; Attacker.DeathPrevention--; } } //if () //CombatHandler.SendMeleeDamage(attacker, this, schools, hitInfo, (uint)totalDamage, //(uint)absorbed, (uint)resisted, (uint)blocked, victimState); if (SpellEffect != null) { CombatLogHandler.SendMagicDamage(this); } else { CombatHandler.SendAttackerStateUpdate(this); } TriggerProcOnStrike(); }
/// <summary> /// Validates targets and applies all SpellEffects /// </summary> public SpellFailedReason Impact() { if (!IsCasting) { return(SpellFailedReason.Ok); } // apply effects foreach (var handler in Handlers) { if (handler.Effect.IsPeriodic || handler.Effect.IsStrikeEffect) { // weapon ability or handled by Aura or Channel continue; } handler.Apply(); if (!IsCasting) { // the last handler cancelled the SpellCast return(SpellFailedReason.DontReport); } } if (CasterObject is Unit && Spell.IsPhysicalAbility) { // strike at everyone foreach (var target in UnitTargets) { ProcHitFlags hitFlags = CasterUnit.Strike(GetWeapon(), target, this); m_hitInfoByTarget[target] = hitFlags; } } // open Channel and spawn DynamicObject DynamicObject dynObj = null; if (Spell.DOEffect != null) { dynObj = new DynamicObject(this, Spell.DOEffect.GetRadius(CasterReference)); } if (!IsCasting) { return(SpellFailedReason.Ok); } List <MissedTarget> missedTargets = null; // create auras List <IAura> auras = null; if (m_auraApplicationInfos != null) { CreateAuras(ref missedTargets, ref auras, dynObj); } // check for missed targets if (missedTargets != null) { if (missedTargets.Count > 0) { // TODO: Flash message ontop of missed heads when impact is delayed CombatLogHandler.SendSpellMiss(this, true, missedTargets); missedTargets.Clear(); } CastMissListPool.Recycle(missedTargets); } // open channel if (Spell.IsChanneled && CasterObject != null) { Channel = SpellChannel.SpellChannelPool.Obtain(); Channel.m_cast = this; if (CasterObject is Unit) { if (dynObj != null) { CasterUnit.ChannelObject = dynObj; } else if (SelectedTarget != null) { CasterUnit.ChannelObject = SelectedTarget; if (SelectedTarget is NPC && Spell.IsTame) { ((NPC)SelectedTarget).CurrentTamer = CasterObject as Character; } } } var len = Handlers.Length; var channelEffectHandlers = SpellEffectHandlerListPool.Obtain(); //var channelEffectHandlers = new List<SpellEffectHandler>(6); for (var i = 0; i < len; i++) { var handler = Handlers[i]; if (handler.Effect.IsPeriodic) { channelEffectHandlers.Add(handler); } } Channel.Open(channelEffectHandlers, auras); } // start Auras if (auras != null) { for (var i = 0; i < auras.Count; i++) { var aura = auras[i]; aura.Start(Spell.IsChanneled ? Channel : null, false); } if (!IsChanneling) { auras.Clear(); AuraListPool.Recycle(auras); auras = null; } } // applying debuffs might cancel other Auras if (Spell.HasHarmfulEffects && !Spell.IsPreventionDebuff) { foreach (var target in Targets) { if (target is Unit && Spell.IsHarmfulFor(CasterReference, target)) { ((Unit)target).Auras.RemoveByFlag(AuraInterruptFlags.OnHostileSpellInflicted); } } } //if (CasterChar != null) //{ // CasterChar.SendSystemMessage("SpellCast (Impact): {0} ms", sw1.ElapsedTicks / 10000d); //} return(SpellFailedReason.Ok); }
/// <summary> /// Does spell-damage to this Unit /// </summary> public void DealSpellDamage(Unit attacker, SpellEffect effect, int dmg, bool addDamageBonuses = true, bool mayCrit = true, bool forceCrit = false) { EnsureContext(); if (!IsAlive) { return; } if (attacker != null && !attacker.IsInContext) { attacker = null; } if (attacker is NPC) { dmg = (int)(dmg * NPCMgr.DefaultNPCDamageFactor + 0.999999f); } DamageSchool school; if (effect != null) { school = GetLeastResistantSchool(effect.Spell); if (effect.Spell.DamageIncreasedByAP) { int ap; if (effect.Spell.IsRangedAbility) { ap = TotalRangedAP; } else { ap = TotalMeleeAP; } dmg += (ap + 7) / 14; // round } } else { school = DamageSchool.Physical; } if (IsEvading || IsImmune(school) || IsInvulnerable || !IsAlive) { // cannot deal damage to this guy return; } var action = GetUnusedAction(); // reset values action.Attacker = attacker; action.HitFlags = 0; action.VictimState = 0; action.Weapon = null; if (effect != null) { // Some kind of spell is involved action.UsedSchool = school; action.Schools = effect.Spell.SchoolMask; action.IsDot = effect.IsPeriodic; } else { // pure white melee damage action.UsedSchool = DamageSchool.Physical; action.Schools = DamageSchoolMask.Physical; action.IsDot = false; } action.Damage = dmg; action.ResistPct = GetResistChancePct(this, action.UsedSchool); action.Absorbed = 0; action.SpellEffect = effect; action.Victim = this; if (attacker != null) { attacker.DeathPrevention++; } DeathPrevention++; try { if (attacker != null) { // the damage is caused by someone else (i.e. not environmental damage etc) // critical hits if (forceCrit || action.CalcCritChance() > Utility.Random(0, 10000)) { action.IsCritical = true; action.SetCriticalDamage(); } else { action.IsCritical = false; } // add mods and call events if (addDamageBonuses) { action.AddDamageMods(); } OnDefend(action); attacker.OnAttack(action); } action.Resisted = (int)Math.Round(action.Damage * action.ResistPct / 100); action.Blocked = 0; // TODO: Deflect DoRawDamage(action); CombatLogHandler.SendMagicDamage(action); } finally { DeathPrevention--; if (attacker != null) { attacker.DeathPrevention--; } action.OnFinished(); } //Your average resistance can still be anywhere betweeen 0% and 75%. If your average resistance is maxed out, then there's a really good chance of having 75% of the spell's damage be resisted. //There's also a fairly good chance of having 100% of the spell's damage be resisted, a slightly lower chance of 50% of its damage being resisted, a small chances of only 25%, or even 0% of the damage being resisted. //It's a weighted average. Visualize it as a bell curve around your average resistance. }