public void Parry() { Damage = 0; VictimState = VictimState.Parry; HitFlags = HitFlags.Miss; ProcHitFlags |= ProcHitFlags.Parry; Blocked = 0; IsCritical = false; DoStrike(); }
public void StrikeGlancing() { Damage = (int)(Damage * CalcGlancingBlowDamageFactor()); VictimState = VictimState.Wound; HitFlags = HitFlags.PlayWoundAnimation | HitFlags.Glancing; ProcHitFlags |= ProcHitFlags.NormalHit; Blocked = 0; IsCritical = false; DoStrike(); }
public void StrikeCrushing() { Damage = (Damage * 10 + 5) / 15; // == Damage * 1.5f HitFlags = HitFlags.PlayWoundAnimation | HitFlags.Crushing; VictimState = VictimState.Wound; ProcHitFlags |= ProcHitFlags.NormalHit; Blocked = 0; IsCritical = false; DoStrike(); }
public void Dodge() { Damage = 0; VictimState = VictimState.Dodge; HitFlags = HitFlags.Miss; ProcHitFlags |= ProcHitFlags.Dodge; Blocked = 0; IsCritical = false; DoStrike(); }
public ProcHandlerTemplate(ProcTriggerFlags triggerFlags, ProcHitFlags hitFlags, ProcCallback procAction, ProcValidator validator = null, uint procChance = 100, int stackCount = 0) { ProcTriggerFlags = triggerFlags; ProcHitFlags = hitFlags; ProcChance = procChance; Validator = validator; ProcAction = procAction; m_stackCount = stackCount; }
public void StrikeCritical() { IsCritical = Victim.StandState == StandState.Stand; SetCriticalDamage(); HitFlags = HitFlags.PlayWoundAnimation | HitFlags.ResistType1 | HitFlags.ResistType2 | HitFlags.CriticalStrike; VictimState = VictimState.Wound; ProcHitFlags |= ProcHitFlags.CriticalHit; Blocked = 0; // Automatic double damage against sitting target - but doesn't proc crit abilities DoStrike(); }
public void StrikeCritical() { this.IsCritical = this.Victim.StandState == StandState.Stand; this.SetCriticalDamage(); this.HitFlags = HitFlags.PlayWoundAnimation | HitFlags.ResistType1 | HitFlags.ResistType2 | HitFlags.CriticalStrike; this.VictimState = VictimState.Wound; this.ProcHitFlags |= ProcHitFlags.CriticalHit; this.Blocked = 0; this.DoStrike(); }
public void StrikeCritical() { IsCritical = Victim.StandState == StandState.Stand; SetCriticalDamage(); HitFlags = HitFlags.PlayWoundAnimation | HitFlags.ResistType1 | HitFlags.ResistType2 | HitFlags.CriticalStrike; VictimState = VictimState.Wound; ProcHitFlags |= ProcHitFlags.CriticalHit; Blocked = 0; DoStrike(); }
public void Block() { HitFlags = HitFlags.PlayWoundAnimation | HitFlags.Block; VictimState = VictimState.Block; ProcHitFlags |= ProcHitFlags.Block; Blocked = CalcBlockDamage(); if (Damage == Blocked) { ProcHitFlags |= ProcHitFlags.FullBlock; } IsCritical = false; DoStrike(); }
public void Block() { this.HitFlags = HitFlags.PlayWoundAnimation | HitFlags.Block; this.VictimState = VictimState.Block; this.ProcHitFlags |= ProcHitFlags.Block; this.Blocked = this.CalcBlockDamage(); if (this.Damage == this.Blocked) { this.ProcHitFlags |= ProcHitFlags.FullBlock; } this.IsCritical = false; this.DoStrike(); }
/// <summary> /// Trigger proc on the caster of the spell. /// </summary> /// <param name="flags">What spell caster casted ie. ProcTriggerFlags.DoneHarmfulSpell</param> /// <param name="hitFlags">Hit result of the spell</param> private void TriggerProcOnCaster(ProcTriggerFlags flags, ProcHitFlags hitFlags) { var casterAction = new SimpleUnitAction { Attacker = CasterUnit, Spell = Spell, Victim = m_hitInfoByTarget.Count > 0 ? m_hitInfoByTarget.First().Key : null, IsCritical = hitFlags.HasAnyFlag(ProcHitFlags.CriticalHit) }; var triggerer = UnitTargets.FirstOrDefault(); CasterUnit.Proc(flags, triggerer, casterAction, true, hitFlags); }
/// <summary> /// Triggers proc on all targets of SpellCast /// </summary> /// <param name="flags">What happened to targets ie. ProcTriggerFlags.ReceivedHarmfulSpell</param> /// <returns>Combination of hit result on all targets.</returns> private ProcHitFlags TriggerProcOnTargets(ProcTriggerFlags flags) { ProcHitFlags hitFlagsCombination = ProcHitFlags.None; foreach (var hitInfo in m_hitInfoByTarget) { Unit target = hitInfo.Key; ProcHitFlags targetHitFlags = hitInfo.Value; hitFlagsCombination |= targetHitFlags; var action = new SimpleUnitAction { Attacker = CasterUnit, Spell = Spell, Victim = target, IsCritical = targetHitFlags.HasAnyFlag(ProcHitFlags.CriticalHit) }; target.Proc(flags, CasterUnit, action, true, targetHitFlags); } return(hitFlagsCombination); }
/// <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(); }
public void MissImmune() { Damage = 0; VictimState = VictimState.Immune; ProcHitFlags |= ProcHitFlags.Immune; DoStrike(); }
public void Miss() { this.Damage = 0; this.ProcHitFlags |= ProcHitFlags.Miss; this.DoStrike(); }
public TriggerSpellProcHandlerTemplate(Spell spell, ProcTriggerFlags triggerFlags, ProcHitFlags hitFlags = ProcHitFlags.None, uint procChance = 100u, int stackCount = 0) : this(spell, triggerFlags, null, hitFlags, procChance, stackCount) { }
public void Evade() { Damage = 0; VictimState = VictimState.Evade; ProcHitFlags |= ProcHitFlags.Evade; DoStrike(); }
public TriggerSpellProcHandlerTemplate(Spell spell, ProcTriggerFlags triggerFlags, ProcValidator validator = null, ProcHitFlags hitFlags = ProcHitFlags.None, uint procChance = 100u, int stackCount = 0) : base(triggerFlags, hitFlags, null, validator, procChance, stackCount) { Spell = spell; ProcAction = ProcSpell; }
void TriggerProcOnCasted() { // Set the flags for caster and target based on the spell ProcTriggerFlags casterProcFlags = ProcTriggerFlags.None; ProcTriggerFlags targetProcFlags = ProcTriggerFlags.None; switch (Spell.DamageType) { case DamageType.None: { if (Spell.IsBeneficial) { casterProcFlags |= ProcTriggerFlags.DoneBeneficialSpell; targetProcFlags |= ProcTriggerFlags.ReceivedBeneficialSpell; } else if (Spell.IsHarmful) { casterProcFlags |= ProcTriggerFlags.DoneHarmfulSpell; targetProcFlags |= ProcTriggerFlags.ReceivedHarmfulSpell; } break; } case DamageType.Magic: { if (Spell.IsBeneficial) { casterProcFlags |= ProcTriggerFlags.DoneBeneficialMagicSpell; targetProcFlags |= ProcTriggerFlags.ReceivedBeneficialMagicSpell; } else if (Spell.IsHarmful) { casterProcFlags |= ProcTriggerFlags.DoneHarmfulMagicSpell; targetProcFlags |= ProcTriggerFlags.ReceivedHarmfulMagicSpell; } break; } case DamageType.Melee: { casterProcFlags |= ProcTriggerFlags.DoneMeleeSpell; targetProcFlags |= ProcTriggerFlags.ReceivedMeleeSpell; break; } case DamageType.Ranged: { if (Spell.IsAutoRepeating) { casterProcFlags |= ProcTriggerFlags.DoneRangedAutoAttack; targetProcFlags |= ProcTriggerFlags.ReceivedRangedAutoAttack; } else { casterProcFlags |= ProcTriggerFlags.DoneRangedSpell; targetProcFlags |= ProcTriggerFlags.ReceivedRangedSpell; } break; } } ProcHitFlags casterHitFlags = TriggerProcOnTargets(targetProcFlags); TriggerProcOnCaster(casterProcFlags, casterHitFlags); }
public ProcHandlerTemplate(ProcTriggerFlags triggerFlags, ProcHitFlags hitFlags, ProcCallback procAction, ProcValidator validator = null, uint procChance = 100u, int stackCount = 0) { ProcTriggerFlags = triggerFlags; ProcHitFlags = hitFlags; ProcChance = procChance; Validator = validator; ProcAction = procAction; m_stackCount = stackCount; }
public static bool HasAnyFlag(this ProcHitFlags flags, ProcHitFlags otherFlags) { return((flags & otherFlags) != ProcHitFlags.None); }
internal void Reset(Unit attacker, Unit target, IWeapon weapon) { Attacker = attacker; Victim = target; Weapon = weapon; ProcHitFlags = ProcHitFlags.None; }
/// <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); }
public void Miss() { Damage = 0; ProcHitFlags |= ProcHitFlags.Miss; DoStrike(); }
/// <summary> /// Do a single attack on the target using given weapon, ability and action. /// </summary> public ProcHitFlags Strike(IAsda2Weapon weapon, DamageAction action, Unit target, SpellCast ability) { ProcHitFlags procHitFlags = ProcHitFlags.None; EnsureContext(); if (!IsAlive) { return(procHitFlags); } if (!target.IsInContext || !target.IsAlive) { return(procHitFlags); } if (weapon == null) { log.Info("Trying to strike without weapon: " + this); return(procHitFlags); } //if (IsMovementControlled) //{ // // stop running when landing a hit // m_Movement.Stop(); //} target.IsInCombat = true; action.Victim = target; action.Attacker = this; action.Weapon = weapon; if (ability != null) { action.Schools = ability.Spell.SchoolMask; action.SpellEffect = ability.Spell.Effects[0]; // calc damage GetWeaponDamage(action, weapon, ability); procHitFlags = action.DoAttack(); if (ability.Spell.AttributesExC.HasFlag(SpellAttributesExC.RequiresTwoWeapons) && m_offhandWeapon != null) { // also strike with offhand action.Reset(this, target, m_offhandWeapon); GetWeaponDamage(action, m_offhandWeapon, ability); procHitFlags |= action.DoAttack(); m_lastOffhandStrike = Environment.TickCount; } } else { // no combat ability m_extraAttacks += 1; do { // calc damage GetWeaponDamage(action, weapon, null); action.Schools = weapon.Damages.AllSchools(); if (action.Schools == DamageSchoolMask.None) { action.Schools = DamageSchoolMask.Physical; } // normal attack action.DoAttack(); } while (--m_extraAttacks > 0); } action.OnFinished(); return(procHitFlags); }
public static bool HasAnyFlag(this ProcHitFlags flags, ProcHitFlags otherFlags) { return (flags & otherFlags) != 0; }
public void StrikeNormal() { HitFlags = HitFlags.PlayWoundAnimation; VictimState = VictimState.Wound; ProcHitFlags |= ProcHitFlags.NormalHit; Blocked = 0; IsCritical = false; DoStrike(); }