SepHighAssassin.cs 11 KB

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