TucsonGeneral.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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 TucsonGeneral : MonsterObject
  8. {
  9. private long _RageTime;
  10. private const int _RockCount = 15;
  11. protected internal TucsonGeneral(MonsterInfo info)
  12. : base(info)
  13. {
  14. }
  15. protected override bool InAttackRange()
  16. {
  17. return CurrentMap == Target.CurrentMap && Functions.InRange(CurrentLocation, Target.CurrentLocation, Info.ViewRange);
  18. }
  19. protected override void Attack()
  20. {
  21. if (!Target.IsAttackTarget(this))
  22. {
  23. Target = null;
  24. return;
  25. }
  26. ActionTime = Envir.Time + 300;
  27. AttackTime = Envir.Time + AttackSpeed;
  28. ShockTime = 0;
  29. Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation);
  30. bool ranged = CurrentLocation == Target.CurrentLocation || !Functions.InRange(CurrentLocation, Target.CurrentLocation, 2);
  31. if (Envir.Time > _RageTime)
  32. {
  33. Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 0 });
  34. _RageTime = Envir.Time + 20000;
  35. AttackTime = Envir.Time + 8000;
  36. var targets = FindAllTargets(10, CurrentLocation, false);
  37. for (int i = 0; i < _RockCount; i++)
  38. {
  39. Point location = new Point(CurrentLocation.X + Envir.Random.Next(-Info.ViewRange, Info.ViewRange + 1),
  40. CurrentLocation.Y + Envir.Random.Next(-Info.ViewRange, Info.ViewRange + 1));
  41. if (Envir.Random.Next(3) == 0 && targets.Count > 0)
  42. {
  43. location = targets[Envir.Random.Next(targets.Count)].CurrentLocation;
  44. }
  45. if (location.X == CurrentLocation.X || location.Y == CurrentLocation.Y) continue;
  46. var start = Envir.Random.Next(0, 5000);
  47. var value = Envir.Random.Next(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
  48. var spellObj = new SpellObject
  49. {
  50. Spell = Spell.TucsonGeneralRock,
  51. Value = value,
  52. ExpireTime = Envir.Time + 2000 + start,
  53. TickSpeed = 1000,
  54. Caster = this,
  55. CurrentLocation = location,
  56. CurrentMap = CurrentMap,
  57. Direction = MirDirection.Up,
  58. StartTime = Envir.Time + 1000 + start
  59. };
  60. DelayedAction action = new DelayedAction(DelayedType.Spawn, Envir.Time + start, spellObj);
  61. CurrentMap.ActionList.Add(action);
  62. }
  63. return;
  64. }
  65. if (!ranged && Envir.Random.Next(4) > 0)
  66. {
  67. if (Envir.Random.Next(3) > 0)
  68. {
  69. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 0 });
  70. int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
  71. if (damage == 0) return;
  72. DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 500, Target, damage, DefenceType.ACAgility, false);
  73. ActionList.Add(action);
  74. }
  75. else
  76. {
  77. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = 1 });
  78. int damage = GetAttackPower(Stats[Stat.MinMC], Stats[Stat.MaxMC]);
  79. if (damage == 0) return;
  80. DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 500, Target, damage, DefenceType.ACAgility, true);
  81. ActionList.Add(action);
  82. }
  83. }
  84. else
  85. {
  86. if (Envir.Random.Next(4) > 0)
  87. {
  88. Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, TargetID = Target.ObjectID, Type = 1 });
  89. int damage = GetAttackPower(Stats[Stat.MinSC], Stats[Stat.MaxSC]);
  90. if (damage == 0) return;
  91. ProjectileAttack(damage, DefenceType.MACAgility);
  92. }
  93. else
  94. {
  95. Broadcast(new S.ObjectRangeAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, TargetID = Target.ObjectID, Type = 2 });
  96. int damage = GetAttackPower(Stats[Stat.MinSC], Stats[Stat.MaxSC] * 2);
  97. if (damage == 0) return;
  98. DelayedAction action = new DelayedAction(DelayedType.RangeDamage, Envir.Time + 500, Target, damage, DefenceType.ACAgility, true);
  99. ActionList.Add(action);
  100. }
  101. }
  102. }
  103. protected override void CompleteAttack(IList<object> data)
  104. {
  105. MapObject target = (MapObject)data[0];
  106. int damage = (int)data[1];
  107. DefenceType defence = (DefenceType)data[2];
  108. bool stomp = (bool)data[3];
  109. if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return;
  110. if (stomp)
  111. {
  112. var targets = FindAllTargets(3, CurrentLocation, false);
  113. for (int i = 0; i < targets.Count; i++)
  114. {
  115. if (targets[i].Attacked(this, damage, defence) <= 0) continue;
  116. PoisonTarget(targets[i], 3, 5, PoisonType.Paralysis, 1000);
  117. }
  118. }
  119. else
  120. {
  121. target.Attacked(this, damage, defence);
  122. }
  123. }
  124. protected override void ProcessTarget()
  125. {
  126. if (Target == null) return;
  127. if (InAttackRange() && CanAttack)
  128. {
  129. Attack();
  130. return;
  131. }
  132. if (Envir.Time < ShockTime)
  133. {
  134. Target = null;
  135. return;
  136. }
  137. MoveTo(Target.CurrentLocation);
  138. }
  139. }
  140. }