CharmedSnake.cs 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using Server.MirDatabase;
  2. using Server.MirEnvir;
  3. using S = ServerPackets;
  4. namespace Server.MirObjects.Monsters
  5. {
  6. public class CharmedSnake : MonsterObject
  7. {
  8. public bool Summoned;
  9. public long AliveTime;
  10. public MapObject MasterTotem;
  11. protected internal CharmedSnake(MonsterInfo info) : base(info)
  12. {
  13. ActionTime = Envir.Time + 1000;
  14. }
  15. public override string Name
  16. {
  17. get { return Master == null ? Info.GameName : (Dead ? Info.GameName : string.Format("{0}({1})", Info.GameName, Master.Name)); }
  18. set { throw new NotSupportedException(); }
  19. }
  20. public override void Process()
  21. {
  22. if (!Dead && Summoned)
  23. {
  24. bool selfDestruct = false;
  25. if (Master != null)
  26. {
  27. if (FindObject(Master.ObjectID, 15) == null) selfDestruct = true;
  28. if (Summoned && Envir.Time > AliveTime) selfDestruct = true;
  29. if (selfDestruct && Master != null) Die();
  30. }
  31. }
  32. base.Process();
  33. }
  34. public override void Process(DelayedAction action)
  35. {
  36. switch (action.Type)
  37. {
  38. case DelayedType.Damage:
  39. CompleteAttack(action.Params);
  40. break;
  41. }
  42. }
  43. // protected override void ProcessAI()
  44. // {
  45. // ProcessSearch();
  46. // ProcessRoam();
  47. // ProcessTarget();
  48. //}
  49. protected override void ProcessAI()
  50. {
  51. if (Dead) return;
  52. ProcessSearch();
  53. //todo ProcessRoaming(); needs no master follow just target roaming
  54. ProcessTarget();
  55. }
  56. protected override void ProcessSearch()
  57. {
  58. if (Envir.Time < SearchTime) return;
  59. SearchTime = Envir.Time + SearchDelay;
  60. //Stacking or Infront of master - Move
  61. bool stacking = false;
  62. Cell cell = CurrentMap.GetCell(CurrentLocation);
  63. if (cell.Objects != null)
  64. for (int i = 0; i < cell.Objects.Count; i++)
  65. {
  66. MapObject ob = cell.Objects[i];
  67. if (ob == this || !ob.Blocking) continue;
  68. stacking = true;
  69. break;
  70. }
  71. if (CanMove && ((MasterTotem != null && MasterTotem.Front == CurrentLocation) || stacking))
  72. {
  73. //Walk Randomly
  74. if (!Walk(Direction))
  75. {
  76. MirDirection dir = Direction;
  77. switch (Envir.Random.Next(3)) // favour Clockwise
  78. {
  79. case 0:
  80. for (int i = 0; i < 7; i++)
  81. {
  82. dir = Functions.NextDir(dir);
  83. if (Walk(dir))
  84. break;
  85. }
  86. break;
  87. default:
  88. for (int i = 0; i < 7; i++)
  89. {
  90. dir = Functions.PreviousDir(dir);
  91. if (Walk(dir))
  92. break;
  93. }
  94. break;
  95. }
  96. }
  97. }
  98. if (Target == null || Envir.Random.Next(3) == 0) FindTarget();
  99. }
  100. protected override void ProcessRoam()
  101. {
  102. if (Target != null || Envir.Time < RoamTime) return;
  103. if (ProcessRoute()) return;
  104. if (MasterTotem != null)
  105. {
  106. MoveTo(MasterTotem.Back);
  107. return;
  108. }
  109. RoamTime = Envir.Time + RoamDelay;
  110. if (Envir.Random.Next(10) != 0) return;
  111. switch (Envir.Random.Next(3)) //Face Walk
  112. {
  113. case 0:
  114. Turn((MirDirection)Envir.Random.Next(8));
  115. break;
  116. default:
  117. Walk(Direction);
  118. break;
  119. }
  120. }
  121. protected override void ProcessTarget()
  122. {
  123. if (Target == null || !CanAttack) return;
  124. if (InAttackRange())
  125. {
  126. Attack();
  127. if (Target.Dead)
  128. FindTarget();
  129. return;
  130. }
  131. if (Envir.Time < ShockTime)
  132. {
  133. Target = null;
  134. return;
  135. }
  136. MoveTo(Target.CurrentLocation);
  137. }
  138. protected override void Attack()
  139. {
  140. if (!Target.IsAttackTarget(this))
  141. {
  142. Target = null;
  143. return;
  144. }
  145. Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation);
  146. Broadcast(new S.ObjectAttack { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation });
  147. int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
  148. if (damage > 0)
  149. {
  150. DelayedAction action = new DelayedAction(DelayedType.Damage, Envir.Time + 300, Target, damage, DefenceType.MAC);
  151. ActionList.Add(action);
  152. }
  153. ActionTime = Envir.Time + 300;
  154. AttackTime = Envir.Time + AttackSpeed;
  155. ShockTime = 0;
  156. }
  157. protected override void CompleteAttack(IList<object> data)
  158. {
  159. MapObject target = (MapObject)data[0];
  160. int damage = (int)data[1];
  161. DefenceType defence = (DefenceType)data[2];
  162. if (target == null || !target.IsAttackTarget(this) || target.CurrentMap != CurrentMap || target.Node == null) return;
  163. if (target.Attacked(this, damage, defence) <= 0) return;
  164. PoisonTarget(target, 10 - PetLevel, 4 + PetLevel, PoisonType.Paralysis, 1000);
  165. }
  166. public override void Die()
  167. {
  168. base.Die();
  169. //Explosion
  170. for (int y = CurrentLocation.Y - 1; y <= CurrentLocation.Y + 1; y++)
  171. {
  172. if (y < 0) continue;
  173. if (y >= CurrentMap.Height) break;
  174. for (int x = CurrentLocation.X - 1; x <= CurrentLocation.X + 1; x++)
  175. {
  176. if (x < 0) continue;
  177. if (x >= CurrentMap.Width) break;
  178. Cell cell = CurrentMap.GetCell(x, y);
  179. if (!cell.Valid || cell.Objects == null) continue;
  180. for (int i = 0; i < cell.Objects.Count; i++)
  181. {
  182. MapObject target = cell.Objects[i];
  183. switch (target.Race)
  184. {
  185. case ObjectType.Monster:
  186. case ObjectType.Player:
  187. //Only targets
  188. if (!target.IsAttackTarget(this) || target.Dead) break;
  189. target.Attacked(this, 10 * PetLevel, DefenceType.MACAgility);
  190. break;
  191. }
  192. }
  193. }
  194. }
  195. }
  196. public override void Spawned()
  197. {
  198. base.Spawned();
  199. Summoned = true;
  200. }
  201. public override Packet GetInfo()
  202. {
  203. var packet = (S.ObjectMonster)base.GetInfo();
  204. packet.Image = Monster.CharmedSnake;
  205. packet.Extra = Summoned;
  206. return packet;
  207. }
  208. }
  209. }