Yimoogi.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. using System.Drawing;
  2. using Server.MirDatabase;
  3. using Server.MirEnvir;
  4. using S = ServerPackets;
  5. namespace Server.MirObjects.Monsters
  6. {
  7. public class Yimoogi : MonsterObject
  8. {
  9. protected byte AttackRange = 7;
  10. protected byte PoisonAttackRange = 4;
  11. public bool NoAttack, ChildSpawned, IsChild, FinalTeleport;
  12. protected Yimoogi SisterMob;
  13. public long SpawnTime;
  14. public int WhiteSnakeCount = 2;
  15. public override MapObject Target
  16. {
  17. get { return _target; }
  18. set
  19. {
  20. if (_target == value) return;
  21. _target = value;
  22. if (SisterMobReady()) SisterMob.Target = value;
  23. NoAttack = value == null ? true : false;
  24. }
  25. }
  26. protected internal Yimoogi(MonsterInfo info)
  27. : base(info)
  28. {
  29. SpawnTime = Envir.Time + 4000;
  30. NoAttack = true;
  31. }
  32. protected bool SisterMobReady()
  33. {
  34. if (SisterMob == null) return false;
  35. if (SisterMob.Dead) return false;
  36. return true;
  37. }
  38. protected override bool InAttackRange()
  39. {
  40. if (Target.CurrentMap != CurrentMap) return false;
  41. if (Target.CurrentLocation == CurrentLocation) return false;
  42. int x = Math.Abs(Target.CurrentLocation.X - CurrentLocation.X);
  43. int y = Math.Abs(Target.CurrentLocation.Y - CurrentLocation.Y);
  44. if (x > 2 || y > 2) return false;
  45. return (x <= 1 && y <= 1) || (x == y || x % 2 == y % 2);
  46. }
  47. protected bool InRangedAttackRange(int distance)
  48. {
  49. return CurrentMap == Target.CurrentMap && Functions.InRange(CurrentLocation, Target.CurrentLocation, distance);
  50. }
  51. protected override void FindTarget()
  52. {
  53. if (!NoAttack) base.FindTarget();
  54. }
  55. protected override void Attack()
  56. {
  57. if (!Target.IsAttackTarget(this) || NoAttack)
  58. {
  59. Target = null;
  60. return;
  61. }
  62. ShockTime = 0;
  63. Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation);
  64. bool ranged = CurrentLocation == Target.CurrentLocation || !InAttackRange();
  65. ActionTime = Envir.Time + 300;
  66. AttackTime = Envir.Time + AttackSpeed;
  67. int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
  68. if (!ranged && Envir.Random.Next(5) > 0)
  69. {
  70. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation });
  71. if (damage == 0) return;
  72. DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 300, Target, damage, DefenceType.MACAgility);
  73. ActionList.Add(action);
  74. }
  75. else
  76. {
  77. AttackTime = Envir.Time + AttackSpeed + 500;
  78. if (damage == 0) return;
  79. if (InRangedAttackRange(PoisonAttackRange) && Envir.Random.Next(6) == 0)
  80. {
  81. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 1 });
  82. //TODO - Delay this
  83. PoisonTarget(Target, 1, 6, PoisonType.Red, 2000);
  84. }
  85. else
  86. {
  87. Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, TargetID = Target.ObjectID });
  88. DelayedAction action = new DelayedAction(DelayedType.RangeDamage, Envir.Time + 500, Target, damage, DefenceType.MAC);
  89. ActionList.Add(action);
  90. }
  91. }
  92. }
  93. protected override void ProcessAI()
  94. {
  95. if (Dead) return;
  96. if (!IsChild && HP <= Stats[Stat.HP] / 10 && !FinalTeleport)
  97. {
  98. Point teleportlocation = CurrentLocation;
  99. if (TeleportRandom(40, 0))
  100. {
  101. FinalTeleport = true;
  102. MonsterObject mob = null;
  103. for (int i = 0; i < WhiteSnakeCount; i++)
  104. {
  105. mob = GetMonster(Envir.GetMonsterInfo(Settings.WhiteSnake));
  106. if (mob == null) continue;
  107. if (!mob.Spawn(CurrentMap, teleportlocation)) continue;
  108. mob.Target = Target;
  109. mob.ActionTime = Envir.Time + 2000;
  110. }
  111. Target = null;
  112. }
  113. }
  114. if (!IsChild && !ChildSpawned && Envir.Time > SpawnTime)
  115. {
  116. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 2 });
  117. SpawnSlave();
  118. return;
  119. }
  120. if (IsChild && SisterMobReady())
  121. {
  122. if (Functions.InRange(CurrentLocation, SisterMob.CurrentLocation, 2) && Target == null &&
  123. Functions.MaxDistance(CurrentLocation, SisterMob.CurrentLocation) < 10)
  124. {
  125. MoveTo(SisterMob.CurrentLocation);
  126. return;
  127. }
  128. }
  129. base.ProcessAI();
  130. }
  131. protected override void ProcessTarget()
  132. {
  133. if (Target == null) return;
  134. if (InAttackRange() && !CanAttack) return;
  135. if (InRangedAttackRange(AttackRange) && CanAttack)
  136. {
  137. Attack();
  138. return;
  139. }
  140. if (Envir.Time < ShockTime)
  141. {
  142. Target = null;
  143. return;
  144. }
  145. MoveTo(Target.CurrentLocation);
  146. }
  147. protected void SpawnSlave()
  148. {
  149. ActionTime = Envir.Time + 300;
  150. AttackTime = Envir.Time + AttackSpeed;
  151. MonsterObject mob = GetMonster(Envir.GetMonsterInfo(Info.Name));
  152. if (mob == null)
  153. {
  154. base.ProcessAI();
  155. return;
  156. }
  157. Yimoogi childmob = (Yimoogi)mob;
  158. if (!childmob.Spawn(CurrentMap, Front))
  159. childmob.Spawn(CurrentMap, CurrentLocation);
  160. if (Target != null)
  161. {
  162. childmob.Target = Target;
  163. childmob.NoAttack = false;
  164. }
  165. childmob.IsChild = true;
  166. childmob.SisterMob = this;
  167. childmob.ActionTime = Envir.Time + 2000;
  168. SisterMob = childmob;
  169. ChildSpawned = true;
  170. }
  171. public override bool TeleportRandom(int attempts, int distance, Map temp = null)
  172. {
  173. for (int i = 0; i < attempts; i++)
  174. {
  175. Point location;
  176. if (distance <= 0)
  177. location = new Point(Envir.Random.Next(CurrentMap.Width), Envir.Random.Next(CurrentMap.Height));
  178. else
  179. location = new Point(CurrentLocation.X + Envir.Random.Next(-distance, distance + 1),
  180. CurrentLocation.Y + Envir.Random.Next(-distance, distance + 1));
  181. if (Teleport(CurrentMap, location, true, 1)) return true;
  182. }
  183. return false;
  184. }
  185. protected override void Drop()
  186. {
  187. if (!SisterMobReady())
  188. base.Drop();
  189. }
  190. }
  191. }