using System.Drawing; using Server.MirDatabase; using Server.MirEnvir; using S = ServerPackets; namespace Server.MirObjects.Monsters { public class AncientBringer : MonsterObject { protected virtual byte AttackRange { get { return 12; } } protected internal AncientBringer(MonsterInfo info) : base(info) { } protected override bool InAttackRange() { return CurrentMap == Target.CurrentMap && Functions.InRange(CurrentLocation, Target.CurrentLocation, AttackRange); } protected override void Attack() { if (!Target.IsAttackTarget(this)) { Target = null; return; } ActionTime = Envir.Time + 300; AttackTime = Envir.Time + AttackSpeed; ShockTime = 0; Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation); bool ranged = CurrentLocation == Target.CurrentLocation || !Functions.InRange(CurrentLocation, Target.CurrentLocation, 2); if (!ranged) { if (Envir.Random.Next(5) > 0) { Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation }); int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]); PoisonLineAttack(2, damage, DefenceType.ACAgility); } else { Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 1 }); int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC] * 2); PoisonLineAttack(2, damage, DefenceType.ACAgility, true); } } else { if (Envir.Random.Next(10) > 0) { Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, TargetID = Target.ObjectID }); int damage = GetAttackPower(Stats[Stat.MinMC], Stats[Stat.MaxMC]); int delay = Functions.MaxDistance(CurrentLocation, Target.CurrentLocation) * 50 + 500; //50 MS per Step DelayedAction action = new DelayedAction(DelayedType.RangeDamage, Envir.Time + delay, Target, damage, DefenceType.ACAgility, (byte)4); ActionList.Add(action); } else { Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, TargetID = Target.ObjectID, Type = 1 }); int damage = GetAttackPower(Stats[Stat.MinMC], Stats[Stat.MaxMC] * 2); DelayedAction action = new DelayedAction(DelayedType.RangeDamage, Envir.Time + 500, Target, damage, DefenceType.ACAgility, (byte)5); ActionList.Add(action); if (damage > 0) { SpawnSlaves(); } } } } protected override void CompleteRangeAttack(IList data) { MapObject target = (MapObject)data[0]; int damage = (int)data[1]; DefenceType defence = (DefenceType)data[2]; byte range = (byte)data[3]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; var targets = FindAllTargets(range, target.CurrentLocation); for (int i = 0; i < targets.Count; i++) { targets[i].Attacked(this, damage, defence); } } protected override void CompleteAttack(IList data) { MapObject target = (MapObject)data[0]; int damage = (int)data[1]; DefenceType defence = (DefenceType)data[2]; bool poison = (bool)data[3]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; var finalDamage = target.Attacked(this, damage, defence); if (finalDamage > 0 && poison) { PoisonTarget(target, 5, 5, PoisonType.Paralysis, 2000); } } protected void PoisonLineAttack(int distance, int additionalDelay = 500, DefenceType defenceType = DefenceType.ACAgility, bool poison = false) { int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]); if (damage == 0) return; for (int i = 1; i <= distance; i++) { Point target = Functions.PointMove(CurrentLocation, Direction, i); if (!CurrentMap.ValidPoint(target)) continue; Cell cell = CurrentMap.GetCell(target); if (cell.Objects == null) continue; for (int o = 0; o < cell.Objects.Count; o++) { MapObject ob = cell.Objects[o]; if (ob.Race == ObjectType.Monster || ob.Race == ObjectType.Player) { if (!ob.IsAttackTarget(this)) continue; DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 300, ob, damage, defenceType, poison); ActionList.Add(action); } } } } private void SpawnSlaves() { int count = Math.Min(6, 40 - SlaveList.Count); ActionTime = Envir.Time + 300; AttackTime = Envir.Time + AttackSpeed; for (int i = 0; i < count; i++) { MonsterObject mob = GetMonster(Envir.GetMonsterInfo(Settings.AncientBatName)); if (mob == null) continue; if (!mob.Spawn(CurrentMap, Target.CurrentLocation)) mob.Spawn(CurrentMap, Target.CurrentLocation); mob.Target = Target; mob.ActionTime = Envir.Time + 2000; SlaveList.Add(mob); } } protected override void ProcessTarget() { if (Target == null) return; if (InAttackRange() && CanAttack) { Attack(); return; } if (Envir.Time < ShockTime) { Target = null; return; } MoveTo(Target.CurrentLocation); } } }