HornedSorceror.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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 HornedSorceror : MonsterObject
  8. {
  9. private long _TornadoTime;
  10. private long _ChargedStompTime;
  11. private bool _Immune;
  12. protected virtual byte AttackRange
  13. {
  14. get
  15. {
  16. return 5;
  17. }
  18. }
  19. protected internal HornedSorceror(MonsterInfo info)
  20. : base(info)
  21. {
  22. }
  23. protected override bool InAttackRange()
  24. {
  25. return CurrentMap == Target.CurrentMap && Functions.InRange(CurrentLocation, Target.CurrentLocation, AttackRange);
  26. }
  27. public override bool IsAttackTarget(MonsterObject attacker)
  28. {
  29. return !_Immune && base.IsAttackTarget(attacker);
  30. }
  31. public override bool IsAttackTarget(HumanObject attacker)
  32. {
  33. return !_Immune && base.IsAttackTarget(attacker);
  34. }
  35. protected override void Attack()
  36. {
  37. if (!Target.IsAttackTarget(this))
  38. {
  39. Target = null;
  40. return;
  41. }
  42. ShockTime = 0;
  43. Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation);
  44. bool ranged = CurrentLocation == Target.CurrentLocation || !Functions.InRange(CurrentLocation, Target.CurrentLocation, 1);
  45. AttackTime = Envir.Time + AttackSpeed;
  46. //Charged Stomp
  47. if (Envir.Time > _ChargedStompTime && HealthPercent < 90 && Envir.Random.Next(4) == 0)
  48. {
  49. byte stompLoops = (byte)Envir.Random.Next(5, 10);
  50. int stompDuration = stompLoops * 500;
  51. _ChargedStompTime = Envir.Time + 20000;
  52. ActionTime = Envir.Time + (stompDuration) + 500;
  53. AttackTime = Envir.Time + (stompDuration) + 500 + AttackSpeed;
  54. _Immune = true;
  55. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 2, Level = stompLoops });
  56. int damage = GetAttackPower(Stats[Stat.MinSC], Stats[Stat.MaxSC]) * stompLoops;
  57. if (damage == 0) return;
  58. DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + stompDuration + 500, Target, damage, DefenceType.AC, true);
  59. ActionList.Add(action);
  60. return;
  61. }
  62. //Dust Tornado
  63. if (Envir.Time > _TornadoTime && HealthPercent < 90 && Envir.Random.Next(4) == 0)
  64. {
  65. _TornadoTime = Envir.Time + 15000;
  66. Tornado();
  67. return;
  68. }
  69. if (!ranged)
  70. {
  71. if (Envir.Random.Next(5) > 2) //Thrust hit
  72. {
  73. ActionTime = Envir.Time + 300;
  74. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 0 });
  75. int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
  76. if (damage == 0) return;
  77. LineAttack(damage, 2, 300);
  78. }
  79. else if (Envir.Random.Next(5) > 2) //Dust hit
  80. {
  81. ActionTime = Envir.Time + 300;
  82. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 1 });
  83. int damage = GetAttackPower(Stats[Stat.MinMC], Stats[Stat.MaxMC]);
  84. if (damage == 0) return;
  85. LineAttack(damage, 3, 300);
  86. }
  87. else
  88. {
  89. ActionTime = Envir.Time + 500;
  90. Thrust(Target);
  91. }
  92. }
  93. else
  94. {
  95. if (Envir.Random.Next(3) == 0)
  96. {
  97. ActionTime = Envir.Time + 500;
  98. Thrust(Target);
  99. }
  100. else
  101. {
  102. MoveTo(Target.CurrentLocation);
  103. }
  104. }
  105. }
  106. protected override void ProcessTarget()
  107. {
  108. if (Target == null) return;
  109. if (InAttackRange() && CanAttack)
  110. {
  111. Attack();
  112. return;
  113. }
  114. if (Envir.Time < ShockTime)
  115. {
  116. Target = null;
  117. return;
  118. }
  119. MoveTo(Target.Front);
  120. }
  121. private void Tornado()
  122. {
  123. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 3 });
  124. var location = CurrentLocation;
  125. for (int y = location.Y - 2; y <= location.Y + 2; y++)
  126. {
  127. if (y < 0) continue;
  128. if (y >= CurrentMap.Height) break;
  129. for (int x = location.X - 2; x <= location.X + 2; x++)
  130. {
  131. if (x < 0) continue;
  132. if (x >= CurrentMap.Width) break;
  133. var cell = CurrentMap.GetCell(x, y);
  134. if (!cell.Valid) continue;
  135. int damage = GetAttackPower(Stats[Stat.MinMC], Stats[Stat.MaxMC]);
  136. var start = 1000;
  137. var time = Settings.Second * 15;
  138. SpellObject ob = new SpellObject
  139. {
  140. Spell = Spell.HornedSorcererDustTornado,
  141. Value = damage,
  142. ExpireTime = Envir.Time + time + start,
  143. TickSpeed = 1000,
  144. Direction = Direction,
  145. CurrentLocation = new Point(x, y),
  146. CastLocation = CurrentLocation,
  147. Show = location.X == x && location.Y == y,
  148. CurrentMap = CurrentMap,
  149. Owner = this,
  150. Caster = this
  151. };
  152. DelayedAction action = new DelayedAction(DelayedType.Spawn, Envir.Time + start, ob);
  153. CurrentMap.ActionList.Add(action);
  154. }
  155. }
  156. }
  157. private void Thrust(MapObject target)
  158. {
  159. MirDirection jumpDir = Functions.DirectionFromPoint(CurrentLocation, target.CurrentLocation);
  160. Point location;
  161. for (int i = 0; i < 3; i++)
  162. {
  163. location = Functions.PointMove(CurrentLocation, jumpDir, 1);
  164. if (!CurrentMap.ValidPoint(location)) return;
  165. }
  166. for (int i = 0; i < 3; i++)
  167. {
  168. location = Functions.PointMove(CurrentLocation, jumpDir, 1);
  169. CurrentMap.GetCell(CurrentLocation).Remove(this);
  170. RemoveObjects(jumpDir, 1);
  171. CurrentLocation = location;
  172. CurrentMap.GetCell(CurrentLocation).Add(this);
  173. AddObjects(jumpDir, 1);
  174. int damage = Stats[Stat.MaxDC];
  175. if (damage > 0)
  176. {
  177. DelayedAction action = new DelayedAction(DelayedType.RangeDamage, Envir.Time + 500, location, damage, DefenceType.AC);
  178. ActionList.Add(action);
  179. }
  180. }
  181. Broadcast(new S.ObjectDashAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Distance = 3 });
  182. }
  183. protected override void CompleteRangeAttack(IList<object> data)
  184. {
  185. Point location = (Point)data[0];
  186. int damage = (int)data[1];
  187. DefenceType defence = (DefenceType)data[2];
  188. var cell = CurrentMap.GetCell(location);
  189. if (cell.Objects == null) return;
  190. for (int o = 0; o < cell.Objects.Count; o++)
  191. {
  192. MapObject ob = cell.Objects[o];
  193. if (ob.Race != ObjectType.Player && ob.Race != ObjectType.Monster) continue;
  194. if (!ob.IsAttackTarget(this)) continue;
  195. ob.Attacked(this, damage, defence);
  196. break;
  197. }
  198. }
  199. protected override void CompleteAttack(IList<object> data)
  200. {
  201. MapObject target = (MapObject)data[0];
  202. int damage = (int)data[1];
  203. DefenceType defence = (DefenceType)data[2];
  204. bool aoe = data.Count >= 4 && (bool)data[3];
  205. _Immune = false;
  206. if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return;
  207. if (aoe)
  208. {
  209. var targets = FindAllTargets(2, CurrentLocation, false);
  210. for (int i = 0; i < targets.Count; i++)
  211. {
  212. targets[i].Attacked(this, damage, defence);
  213. }
  214. }
  215. else
  216. {
  217. target.Attacked(this, damage, defence);
  218. }
  219. }
  220. }
  221. }