SepArcher.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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 SepArcher : MonsterObject
  8. {
  9. public long FearTime, DecreaseMPTime;
  10. public byte AttackRange = 6;
  11. public bool Summoned;
  12. protected internal SepArcher(MonsterInfo info)
  13. : base(info)
  14. {
  15. }
  16. protected override bool InAttackRange()
  17. {
  18. return CurrentMap == Target.CurrentMap && Functions.InRange(CurrentLocation, Target.CurrentLocation, AttackRange);
  19. }
  20. protected override void Attack()
  21. {
  22. if (!Target.IsAttackTarget(this))
  23. {
  24. Target = null;
  25. return;
  26. }
  27. ShockTime = 0;
  28. ActionTime = Envir.Time + 500;
  29. AttackTime = Envir.Time + AttackSpeed;
  30. int damage = GetAttackPower(Stats[Stat.MinDC], Stats[Stat.MaxDC]);
  31. if (damage == 0) return;
  32. Direction = Functions.DirectionFromPoint(CurrentLocation, Target.CurrentLocation);
  33. if (Envir.Random.Next(3) == 0 && Functions.InRange(CurrentLocation, Target.CurrentLocation, 2))
  34. {
  35. Broadcast(new S.ObjectMagic { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Spell = Spell.BackStep, TargetID = Target.ObjectID, Target = Target.CurrentLocation, Cast = true, Level = 3 });
  36. int travel = 0;
  37. bool blocked = false;
  38. int jumpDistance = 3;
  39. MirDirection jumpDir = Functions.ReverseDirection(Direction);
  40. Point location = CurrentLocation;
  41. for (int i = 0; i < jumpDistance; i++)
  42. {
  43. location = Functions.PointMove(location, jumpDir, 1);
  44. if (!CurrentMap.ValidPoint(location)) break;
  45. Cell cInfo = CurrentMap.GetCell(location);
  46. if (cInfo.Objects != null)
  47. for (int c = 0; c < cInfo.Objects.Count; c++)
  48. {
  49. MapObject ob = cInfo.Objects[c];
  50. if (!ob.Blocking) continue;
  51. blocked = true;
  52. if ((cInfo.Objects == null) || blocked) break;
  53. }
  54. if (blocked) break;
  55. travel++;
  56. }
  57. jumpDistance = travel;
  58. if (jumpDistance > 0)
  59. {
  60. for (int i = 0; i < jumpDistance; i++)
  61. {
  62. location = Functions.PointMove(CurrentLocation, jumpDir, 1);
  63. CurrentMap.GetCell(CurrentLocation).Remove(this);
  64. RemoveObjects(jumpDir, 1);
  65. CurrentLocation = location;
  66. CurrentMap.GetCell(CurrentLocation).Add(this);
  67. AddObjects(jumpDir, 1);
  68. }
  69. //Enqueue(new S.UserBackStep { Direction = Direction, Location = location });
  70. Broadcast(new S.ObjectBackStep { ObjectID = ObjectID, Direction = Direction, Location = location, Distance = jumpDistance });
  71. }
  72. return;
  73. }
  74. if (Envir.Random.Next(5) > 0)
  75. {
  76. Broadcast(new S.ObjectMagic { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Spell = Spell.DoubleShot, TargetID = Target.ObjectID, Target = Target.CurrentLocation, Cast = true, Level = 3 });
  77. ProjectileAttack(damage);
  78. ProjectileAttack(damage);
  79. return;
  80. }
  81. Broadcast(new S.ObjectMagic { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Spell = Spell.StraightShot, TargetID = Target.ObjectID, Target = Target.CurrentLocation, Cast = true, Level = 3 });
  82. ProjectileAttack(damage);
  83. if (Target.Dead)
  84. FindTarget();
  85. }
  86. protected override void ProcessTarget()
  87. {
  88. if (Target == null || !CanAttack) return;
  89. if (!InAttackRange())
  90. {
  91. if (CurrentLocation == Target.CurrentLocation)
  92. {
  93. MirDirection direction = (MirDirection)Envir.Random.Next(8);
  94. int rotation = Envir.Random.Next(2) == 0 ? 1 : -1;
  95. for (int d = 0; d < 8; d++)
  96. {
  97. if (Walk(direction)) break;
  98. direction = Functions.ShiftDirection(direction, rotation);
  99. }
  100. }
  101. else
  102. MoveTo(Target.CurrentLocation);
  103. }
  104. if (!CanAttack) return;
  105. if (InAttackRange() && Envir.Time < FearTime)
  106. {
  107. Attack();
  108. return;
  109. }
  110. FearTime = Envir.Time + 5000;
  111. if (Envir.Time < ShockTime)
  112. {
  113. Target = null;
  114. return;
  115. }
  116. int dist = Functions.MaxDistance(CurrentLocation, Target.CurrentLocation);
  117. if (dist < AttackRange)
  118. {
  119. MirDirection dir = Functions.DirectionFromPoint(Target.CurrentLocation, CurrentLocation);
  120. if (Walk(dir)) return;
  121. switch (Envir.Random.Next(2)) //No favour
  122. {
  123. case 0:
  124. for (int i = 0; i < 7; i++)
  125. {
  126. dir = Functions.NextDir(dir);
  127. if (Walk(dir))
  128. return;
  129. }
  130. break;
  131. default:
  132. for (int i = 0; i < 7; i++)
  133. {
  134. dir = Functions.PreviousDir(dir);
  135. if (Walk(dir))
  136. return;
  137. }
  138. break;
  139. }
  140. }
  141. }
  142. public bool Walk(MirDirection dir, bool br = false)
  143. {
  144. if (!CanMove) return false;
  145. var temploc = Functions.PointMove(CurrentLocation, dir, 1);
  146. if (!CurrentMap.ValidPoint(temploc)) return false;
  147. var cell = CurrentMap.GetCell(temploc);
  148. if (cell.Objects != null)
  149. for (int i = 0; i < cell.Objects.Count; i++)
  150. {
  151. MapObject ob = cell.Objects[i];
  152. if (!ob.Blocking) continue;
  153. return false;
  154. }
  155. Point location = Functions.PointMove(CurrentLocation, dir, 2);
  156. if (!CurrentMap.ValidPoint(location)) return false;
  157. cell = CurrentMap.GetCell(location);
  158. bool isBreak = br;
  159. if (cell.Objects != null)
  160. for (int i = 0; i < cell.Objects.Count; i++)
  161. {
  162. MapObject ob = cell.Objects[i];
  163. if (!ob.Blocking) continue;
  164. isBreak = true;
  165. break;
  166. }
  167. if (isBreak)
  168. {
  169. location = Functions.PointMove(CurrentLocation, dir, 1);
  170. if (!CurrentMap.ValidPoint(location)) return false;
  171. cell = CurrentMap.GetCell(location);
  172. if (cell.Objects != null)
  173. for (int i = 0; i < cell.Objects.Count; i++)
  174. {
  175. MapObject ob = cell.Objects[i];
  176. if (!ob.Blocking) continue;
  177. return false;
  178. }
  179. }
  180. CurrentMap.GetCell(CurrentLocation).Remove(this);
  181. Direction = dir;
  182. RemoveObjects(dir, 1);
  183. CurrentLocation = location;
  184. CurrentMap.GetCell(CurrentLocation).Add(this);
  185. AddObjects(dir, 1);
  186. if (Hidden)
  187. {
  188. Hidden = false;
  189. for (int i = 0; i < Buffs.Count; i++)
  190. {
  191. if (Buffs[i].Type != BuffType.Hiding) continue;
  192. Buffs[i].ExpireTime = 0;
  193. break;
  194. }
  195. }
  196. CellTime = Envir.Time + 500;
  197. ActionTime = Envir.Time + 300;
  198. MoveTime = Envir.Time + MoveSpeed;
  199. if (MoveTime > AttackTime)
  200. AttackTime = MoveTime;
  201. InSafeZone = CurrentMap.GetSafeZone(CurrentLocation) != null;
  202. if (isBreak)
  203. Broadcast(new S.ObjectWalk { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation });
  204. else
  205. Broadcast(new S.ObjectRun { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation });
  206. cell = CurrentMap.GetCell(CurrentLocation);
  207. for (int i = 0; i < cell.Objects.Count; i++)
  208. {
  209. if (cell.Objects[i].Race != ObjectType.Spell) continue;
  210. SpellObject ob = (SpellObject)cell.Objects[i];
  211. ob.ProcessSpell(this);
  212. //break;
  213. }
  214. return true;
  215. }
  216. public override void Die()
  217. {
  218. if (Dead) return;
  219. HP = 0;
  220. Dead = true;
  221. //DeadTime = Envir.Time + DeadDelay;
  222. DeadTime = 0;
  223. Broadcast(new S.ObjectDied { ObjectID = ObjectID, Direction = Direction, Location = CurrentLocation, Type = (byte)(Master != null ? 1 : 0) });
  224. if (EXPOwner != null && Master == null && EXPOwner.Race == ObjectType.Player) EXPOwner.WinExp(Experience, Level);
  225. if (Respawn != null)
  226. Respawn.Count--;
  227. if (Master == null)
  228. Drop();
  229. Master = null;
  230. PoisonList.Clear();
  231. Envir.MonsterCount--;
  232. if (CurrentMap != null)
  233. CurrentMap.MonsterCount--;
  234. }
  235. public override Packet GetInfo()
  236. {
  237. PlayerObject master = null;
  238. short weapon = -1;
  239. short armour = 0;
  240. byte wing = 0;
  241. if (Master != null && Master is PlayerObject) master = (PlayerObject)Master;
  242. if (master != null)
  243. {
  244. weapon = master.Looks_Weapon;
  245. armour = master.Looks_Armour;
  246. wing = master.Looks_Wings;
  247. }
  248. return new S.ObjectPlayer
  249. {
  250. ObjectID = ObjectID,
  251. Name = master != null ? master.Name : Name,
  252. NameColour = NameColour,
  253. Class = MirClass.Archer,
  254. Gender = master != null ? master.Gender : Envir.Random.Next(2) == 0 ? MirGender.Male : MirGender.Female,
  255. Location = CurrentLocation,
  256. Direction = Direction,
  257. Hair = master != null ? master.Hair : (byte)Envir.Random.Next(0, 5),
  258. Weapon = 210,
  259. Armour = 37,
  260. Light = master != null ? master.Light : Light,
  261. Poison = CurrentPoison,
  262. Dead = Dead,
  263. Hidden = Hidden,
  264. Effect = SpellEffect.None,
  265. WingEffect = wing,
  266. Extra = Summoned,
  267. TransformType = -1,
  268. };
  269. }
  270. }
  271. }