using Server.MirDatabase; using Server.MirEnvir; using S = ServerPackets; namespace Server.MirObjects.Monsters { public class DemonWolf : MonsterObject { private readonly int _MaxPackSize = 5; public List Pack = new List(); protected internal DemonWolf(MonsterInfo info) : base(info) { } protected override bool InAttackRange() { if (Target.CurrentMap != CurrentMap) return false; if (Target.CurrentLocation == CurrentLocation) return false; int x = Math.Abs(Target.CurrentLocation.X - CurrentLocation.X); int y = Math.Abs(Target.CurrentLocation.Y - CurrentLocation.Y); if (x > 2 || y > 2) return false; return (x <= 1 && y <= 1) || (x == y || x % 2 == y % 2); } protected override void ProcessSearch() { if (Envir.Time < SearchTime) return; base.ProcessSearch(); Pack = FindPackNearby(5); } protected override void Attack() { if (!Target.IsAttackTarget(this)) { Target = null; return; } Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation); bool ranged = CurrentLocation == Target.CurrentLocation || !Functions.InRange(CurrentLocation, Target.CurrentLocation, 1); ShockTime = 0; ActionTime = Envir.Time + 300; AttackTime = Envir.Time + AttackSpeed; int damageMultiplier = (Pack.Count > _MaxPackSize ? _MaxPackSize : Pack.Count) + 1; if (Info.Effect == 1) { if (!ranged && Envir.Random.Next(4) > 0) { Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 1 }); int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC] * damageMultiplier); if (damage == 0) return; DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 500, Target, damage, DefenceType.MACAgility); ActionList.Add(action); } else { Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 0 }); int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]); if (damage == 0) return; LineAttack(damage, 3); MoveTo(Target.CurrentLocation); } } else { Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 0 }); int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC] * damageMultiplier); if (damage == 0) return; DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 300, Target, damage, DefenceType.MACAgility); ActionList.Add(action); } } protected override void CompleteAttack(IList data) { MapObject target = (MapObject)data[0]; int damage = (int)data[1]; DefenceType defence = (DefenceType)data[2]; if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return; if (target.Attacked(this, damage, defence) <= 0) return; if (Info.Effect == 1) { PoisonTarget(target, 4, 5, PoisonType.Bleeding, 1000); } } public List FindPackNearby(int distance) { List pack = new List(); for (int d = 0; d <= distance; d++) { for (int y = CurrentLocation.Y - d; y <= CurrentLocation.Y + d; y++) { if (y < 0) continue; if (y >= CurrentMap.Height) break; for (int x = CurrentLocation.X - d; x <= CurrentLocation.X + d; x += Math.Abs(y - CurrentLocation.Y) == d ? 1 : d * 2) { if (x < 0) continue; if (x >= CurrentMap.Width) break; if (!CurrentMap.ValidPoint(x, y)) continue; Cell cell = CurrentMap.GetCell(x, y); if (cell.Objects == null) continue; for (int i = 0; i < cell.Objects.Count; i++) { MapObject ob = cell.Objects[i]; switch (ob.Race) { case ObjectType.Monster: if (ob == this || ob.Dead) continue; if (ob.IsAttackTarget(this)) continue; if (((MonsterObject)ob).Info.AI != Info.AI) continue; pack.Add((MonsterObject)ob); continue; } } } } } return pack; } } }