SnakeTotem.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. using Server.MirDatabase;
  2. using Server.MirEnvir;
  3. using S = ServerPackets;
  4. namespace Server.MirObjects.Monsters
  5. {
  6. public class SnakeTotem : MonsterObject
  7. {
  8. public bool Summoned;
  9. public long AliveTime;
  10. public long DieTime;
  11. public int MaxMinions;
  12. protected internal SnakeTotem(MonsterInfo info) : base(info)
  13. {
  14. ActionTime = Envir.Time + 1000;
  15. Direction = MirDirection.Up;
  16. }
  17. public override string Name
  18. {
  19. get { return Master == null ? Info.GameName : (Dead ? Info.GameName : string.Format("{0}({1})", Info.GameName, Master.Name)); }
  20. set { throw new NotSupportedException(); }
  21. }
  22. public override void Turn(MirDirection dir)
  23. {
  24. }
  25. public override bool Walk(MirDirection dir) { return false; }
  26. protected override void ProcessRoam() { }
  27. public override void Process()
  28. {
  29. MaxMinions = PetLevel + 1;
  30. if (!Dead && Summoned)
  31. {
  32. bool selfDestruct = false;
  33. if (Master != null)
  34. {
  35. if (Master.CurrentMap != CurrentMap || !Functions.InRange(Master.CurrentLocation, CurrentLocation, 15)) selfDestruct = true;
  36. if (Summoned && Envir.Time > AliveTime) selfDestruct = true;
  37. if (selfDestruct)
  38. {
  39. Die();
  40. DieTime = Envir.Time + 3000;
  41. }
  42. }
  43. base.Process();
  44. }
  45. else if (Envir.Time >= DieTime) Despawn();
  46. }
  47. public override void Process(DelayedAction action)
  48. {
  49. switch (action.Type)
  50. {
  51. case DelayedType.Damage:
  52. CompleteAttack(action.Params);
  53. break;
  54. }
  55. }
  56. protected override void ProcessAI()
  57. {
  58. if (Dead) return;
  59. //Search for target
  60. if (Envir.Time < SearchTime) return;
  61. SearchTime = Envir.Time + SearchDelay;
  62. //Cant agro when shocked
  63. if (Envir.Time < ShockTime)
  64. {
  65. Target = null;
  66. return;
  67. }
  68. //update targets all the time ?
  69. AgroAllMobsInRange();
  70. //Refresh Minions
  71. for (int i = SlaveList.Count - 1; i >= 0; i--)
  72. if (SlaveList[i].Dead || SlaveList[i].Node == null)
  73. {
  74. SlaveList[i].DeadTime = 0;
  75. }
  76. //Keep Minions Updated
  77. if (SlaveList.Count < MaxMinions) SpawnMinion();
  78. }
  79. public void AgroAllMobsInRange()
  80. {
  81. for (int d = 0; d <= Info.ViewRange; d++)
  82. {
  83. for (int y = CurrentLocation.Y - d; y <= CurrentLocation.Y + d; y++)
  84. {
  85. if (y < 0) continue;
  86. if (y >= CurrentMap.Height) break;
  87. for (int x = CurrentLocation.X - d; x <= CurrentLocation.X + d; x += Math.Abs(y - CurrentLocation.Y) == d ? 1 : d * 2)
  88. {
  89. if (x < 0) continue;
  90. if (x >= CurrentMap.Width) break;
  91. Cell cell = CurrentMap.GetCell(x, y);
  92. if (!cell.Valid || cell.Objects == null) continue;
  93. for (int i = 0; i < cell.Objects.Count; i++)
  94. {
  95. MapObject ob = cell.Objects[i];
  96. switch (ob.Race)
  97. {
  98. case ObjectType.Monster:
  99. if (!ob.IsAttackTarget(this)) continue;
  100. if (ob.Hidden && (!CoolEye || Level < ob.Level)) continue;
  101. if (((MonsterObject)ob).Info.CoolEye == 100) continue;
  102. ob.Target = this;//Agro the mobs in range - Very simple agro system overwriting mobs target
  103. continue;
  104. default:
  105. continue;
  106. }
  107. }
  108. }
  109. }
  110. }
  111. }
  112. public bool SpawnMinion()
  113. {
  114. if (Pets.Count >= MaxMinions) return false;
  115. MonsterInfo info = Envir.GetMonsterInfo(Settings.SnakesName);
  116. if (info == null) return false;
  117. MonsterObject monster;
  118. monster = MonsterObject.GetMonster(info);
  119. monster.PetLevel = PetLevel;
  120. monster.Master = this;
  121. monster.MaxPetLevel = (byte)(1 + PetLevel * 2);
  122. monster.Direction = Direction;
  123. monster.ActionTime = Envir.Time + 1000;
  124. ((Monsters.CharmedSnake)monster).AliveTime = Envir.Time + ((PetLevel * 2000) + 10000);
  125. ((Monsters.CharmedSnake)monster).MasterTotem = this;
  126. SlaveList.Add(monster);
  127. monster.Spawn(CurrentMap, CurrentLocation);
  128. return true;
  129. }
  130. public override void Die()
  131. {
  132. base.Die();
  133. DeadTime = 0;
  134. //Kill Minions
  135. for (int i = SlaveList.Count - 1; i >= 0; i--)
  136. if (!SlaveList[i].Dead && SlaveList[i].Node != null)
  137. {
  138. SlaveList[i].Die();
  139. SlaveList[i].DeadTime = 0;
  140. }
  141. }
  142. public override void Spawned()
  143. {
  144. base.Spawned();
  145. Summoned = true;
  146. }
  147. public override Packet GetInfo()
  148. {
  149. var packet = (S.ObjectMonster)base.GetInfo();
  150. packet.Image = Monster.SnakeTotem;
  151. packet.Extra = Summoned;
  152. return packet;
  153. }
  154. }
  155. }