/// <summary> /// Does spell-damage to this Unit /// </summary> public DamageAction DealSpellDamage(Unit attacker, SpellEffect effect, int dmg, bool addDamageBonuses = true, bool mayCrit = true, bool forceCrit = false, bool clearAction = true) { EnsureContext(); if (!IsAlive) { return(null); } 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); } else { school = DamageSchool.Physical; } if (IsEvading || IsImmune(school) || IsInvulnerable || !IsAlive) { // cannot deal damage to this guy return(null); } 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; var deffence = (Asda2MagicDefence + Asda2Defence) / 2; var atackerChr = action.Attacker as Character; if (atackerChr != null) { switch (atackerChr.Archetype.ClassId) { case ClassId.OHS: deffence = Asda2Defence; break; case ClassId.THS: deffence = Asda2Defence; break; case ClassId.Spear: deffence = Asda2Defence; break; case ClassId.Bow: deffence = Asda2Defence; break; case ClassId.Crossbow: deffence = Asda2Defence; break; case ClassId.Balista: deffence = Asda2Defence; break; case ClassId.AtackMage: deffence = Asda2MagicDefence; break; case ClassId.HealMage: deffence = Asda2MagicDefence; break; case ClassId.SupportMage: deffence = Asda2MagicDefence; break; } } action.ResistPct = DamageAction.CalcResistPrc(deffence, action.Damage, 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) var random = Utility.Random(1, 10000); var hitChance = action.CalcHitChance(); if (random > hitChance) { // missed the target action.Miss(); } else { var block = action.CalcBlockChance(); if (random > (hitChance - block)) { // block action.Block(); } else { var critical = action.CalcCritChance(); if (forceCrit || random > (hitChance - critical - block)) { // critical hit action.StrikeCritical(); } } if (addDamageBonuses) { action.AddDamageMods(); } } // add mods and call events OnDefend(action); attacker.OnAttack(action); } action.Resisted = (int)Math.Round(action.Damage * action.ResistPct / 100); DoRawDamage(action); } finally { DeathPrevention--; if (attacker != null) { attacker.DeathPrevention--; } if (clearAction) { action.OnFinished(); } } if (clearAction) { return(null); } return(action); }