PageRenderTime 64ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/Services/WCell.RealmServer/Battlegrounds/BattlegroundInfo.cs

https://github.com/enjoii/WCell
C# | 492 lines | 341 code | 63 blank | 88 comment | 66 complexity | 8960d25420fc62d0cd5e15570aa07f55 MD5 | raw file
  1. using WCell.RealmServer.Global;
  2. using WCell.Constants;
  3. using WCell.RealmServer.Entities;
  4. using WCell.RealmServer.Handlers;
  5. using WCell.Util;
  6. using WCell.Util.Graphics;
  7. namespace WCell.RealmServer.Battlegrounds
  8. {
  9. /// <summary>
  10. /// Contains all the neccessary battleground information about a player.
  11. /// </summary>
  12. public class BattlegroundInfo
  13. {
  14. #region Fields
  15. private Character _chr;
  16. private BattlegroundRelation[] _relations;
  17. private BattlegroundInvitation _invitation;
  18. private int _relationCount;
  19. private Region _entryRegion;
  20. private Vector3 _entryPosition;
  21. private float _entryOrientation;
  22. private bool _isDeserter;
  23. private BattlegroundTeam _team;
  24. private BattlegroundStats _stats;
  25. #endregion
  26. public BattlegroundInfo(Character chr)
  27. {
  28. _chr = chr;
  29. _relations = new BattlegroundRelation[BattlegroundMgr.MaxQueuesPerChar];
  30. }
  31. #region Properties
  32. /// <summary>
  33. /// The character this information is associated with.
  34. /// </summary>
  35. public Character Character
  36. {
  37. get { return _chr; }
  38. internal set { _chr = value; }
  39. }
  40. /// <summary>
  41. /// The battlegrounds team this character is associated with.
  42. /// </summary>
  43. public BattlegroundTeam Team
  44. {
  45. get { return _team; }
  46. internal set
  47. {
  48. _team = value;
  49. _chr.Record.BattlegroundTeam = value == null ? BattlegroundSide.End : value.Side;
  50. }
  51. }
  52. /// <summary>
  53. /// Stats of current or last Battleground (or null)
  54. /// </summary>
  55. public BattlegroundStats Stats
  56. {
  57. get { return _stats; }
  58. internal set { _stats = value; }
  59. }
  60. /// <summary>
  61. /// Holds the outstanding, if any, invitation to a battleground team.
  62. /// </summary>
  63. public BattlegroundInvitation Invitation
  64. {
  65. get { return _invitation; }
  66. internal set
  67. {
  68. if (value != _invitation)
  69. {
  70. if (value == null)
  71. {
  72. _chr.RemoveUpdateAction(_invitation.CancelTimer);
  73. }
  74. _invitation = value;
  75. }
  76. }
  77. }
  78. /// <summary>
  79. /// The region that this character was originally in before going to the battlegrounds.
  80. /// </summary>
  81. public Region EntryRegion
  82. {
  83. get { return _entryRegion; }
  84. set { _entryRegion = value; }
  85. }
  86. /// <summary>
  87. /// The position that this character was originally at before going to the battlegrounds.
  88. /// </summary>
  89. public Vector3 EntryPosition
  90. {
  91. get { return _entryPosition; }
  92. set { _entryPosition = value; }
  93. }
  94. /// <summary>
  95. /// The orientation that this character was originally in before going to the battlegrounds.
  96. /// </summary>
  97. public float EntryOrientation
  98. {
  99. get { return _entryOrientation; }
  100. set { _entryOrientation = value; }
  101. }
  102. /// <summary>
  103. /// Whether or not this character is considered a deserter. (Deserters cannot join battlegrounds)
  104. /// </summary>
  105. public bool IsDeserter
  106. {
  107. get { return _isDeserter; }
  108. set
  109. {
  110. _isDeserter = value;
  111. if (_isDeserter)
  112. {
  113. CancelAllRelations();
  114. }
  115. }
  116. }
  117. /// <summary>
  118. /// Whether or not this character is enqueued for any battlegrounds.
  119. /// </summary>
  120. public bool IsEnqueuedForBattleground
  121. {
  122. get
  123. {
  124. return _relationCount > 0;
  125. }
  126. }
  127. /// <summary>
  128. /// The battlegrounds relations for this character, if any.
  129. /// </summary>
  130. public BattlegroundRelation[] Relations
  131. {
  132. get { return _relations; }
  133. }
  134. /// <summary>
  135. /// The number of current battlegrounds relations.
  136. /// </summary>
  137. public int RelationCount
  138. {
  139. get { return _relationCount; }
  140. }
  141. /// <summary>
  142. /// Whether or not this character can queue for any more battlegrounds.
  143. /// </summary>
  144. public bool HasAvailableQueueSlots
  145. {
  146. get { return _relationCount < BattlegroundMgr.MaxQueuesPerChar; }
  147. }
  148. #endregion
  149. /// <summary>
  150. /// Returns the character to their original location prior to entering the Battleground.
  151. /// </summary>
  152. public void TeleportBack()
  153. {
  154. if (_entryRegion == null || _entryRegion.IsDisposed || _entryPosition.X == 0)
  155. {
  156. _chr.TeleportToBindLocation();
  157. }
  158. else
  159. {
  160. _chr.TeleportTo(_entryRegion, ref _entryPosition, _entryOrientation);
  161. }
  162. _entryRegion = null;
  163. }
  164. /// <summary>
  165. /// Sets the entry position of the character.
  166. /// </summary>
  167. public void SetCharacterEntry(Region region, ref Vector3 pos, float orientation)
  168. {
  169. _entryRegion = region;
  170. _entryPosition = pos;
  171. _entryOrientation = orientation;
  172. }
  173. /// <summary>
  174. /// Gets the <see cref="BattlegroundRelation"/> for the given Battleground for
  175. /// the Character.
  176. /// </summary>
  177. /// <param name="bgId"></param>
  178. /// <returns></returns>
  179. public BattlegroundRelation GetRelation(BattlegroundId bgId)
  180. {
  181. for (var i = 0; i < _relations.Length; i++)
  182. {
  183. var request = _relations[i];
  184. if (request != null && request.Queue.ParentQueue.Template.Id == bgId)
  185. {
  186. return request;
  187. }
  188. }
  189. return null;
  190. }
  191. public bool IsEnqueuedFor(BattlegroundId bgId)
  192. {
  193. var relation = GetRelation(bgId);
  194. return relation != null && relation.IsEnqueued;
  195. }
  196. public bool CancelIfEnqueued(BattlegroundId bgId)
  197. {
  198. _chr.ContextHandler.EnsureContext();
  199. for (var i = 0; i < _relations.Length; i++)
  200. {
  201. var request = _relations[i];
  202. if (request != null && request.Queue.ParentQueue.Template.Id == bgId)
  203. {
  204. if (request.IsEnqueued)
  205. {
  206. request.Cancel();
  207. return true;
  208. }
  209. return false;
  210. }
  211. }
  212. return false;
  213. }
  214. public void Cancel(BattlegroundInvitation invite)
  215. {
  216. RemoveRelation(invite.QueueIndex);
  217. }
  218. public int RemoveRelation(BattlegroundRelation relation)
  219. {
  220. return RemoveRelation(relation.BattlegroundId);
  221. }
  222. /// <summary>
  223. /// Removes the <see cref="BattlegroundRelation"/> for the given Battleground.
  224. /// This also cancels invitations and leaves the Battleground.
  225. /// If it was a Queue request for the Group and this is the GroupLeader, it also
  226. /// removes everyone else from the Queue.
  227. /// </summary>
  228. /// <param name="id"></param>
  229. /// <returns>The index of the removed relation or -1 if none removed</returns>
  230. public int RemoveRelation(BattlegroundId id)
  231. {
  232. _chr.EnsureContext();
  233. for (var i = 0; i < _relations.Length; i++)
  234. {
  235. var relation = _relations[i];
  236. if (relation != null && relation.Queue.ParentQueue.Template.Id == id)
  237. {
  238. RemoveRelation(i, relation, true);
  239. return i;
  240. }
  241. }
  242. return -1;
  243. }
  244. /// <summary>
  245. /// Removes the corresponding relation and removes it from the queue
  246. /// if it is enqueued.
  247. /// </summary>
  248. /// <param name="id"></param>
  249. /// <returns></returns>
  250. public int CancelRelation(BattlegroundId id)
  251. {
  252. _chr.EnsureContext();
  253. for (var i = 0; i < _relations.Length; i++)
  254. {
  255. var relation = _relations[i];
  256. if (relation != null && relation.Queue.ParentQueue.Template.Id == id)
  257. {
  258. CancelRelation(i, relation, true);
  259. return i;
  260. }
  261. }
  262. return -1;
  263. }
  264. public int CancelRelation(int index, BattlegroundRelation relation, bool charActive)
  265. {
  266. _chr.EnsureContext();
  267. var queue = relation.Queue;
  268. if (queue != null)
  269. {
  270. queue.Remove(relation);
  271. }
  272. RemoveRelation(index, relation, charActive);
  273. return index;
  274. }
  275. /// <summary>
  276. /// Make sure the given index is valid
  277. /// </summary>
  278. /// <param name="index"></param>
  279. public void RemoveRelation(int index)
  280. {
  281. RemoveRelation(index, _relations[index], true);
  282. }
  283. internal void RemoveRelation(int index, BattlegroundRelation relation, bool isCharActive)
  284. {
  285. _chr.EnsureContext();
  286. _relations[index] = null;
  287. var invite = Invitation;
  288. if (invite != null)
  289. {
  290. // cancel reserved slot
  291. invite.Team.ReservedSlots--;
  292. Invitation = null;
  293. }
  294. var bgId = relation.BattlegroundId;
  295. var bg = _chr.Region as Battleground;
  296. if (bg != null &&
  297. bg.Template.Id == bgId &&
  298. !relation.IsEnqueued &&
  299. !_chr.IsTeleporting &&
  300. isCharActive)
  301. {
  302. bg.TeleportOutside(_chr);
  303. }
  304. if (isCharActive)
  305. {
  306. BattlegroundHandler.ClearStatus(_chr, index);
  307. }
  308. if (relation.IsEnqueued && relation.Characters.Count > 1)
  309. {
  310. var group = _chr.Group;
  311. if (group != null && group.IsLeader(_chr))
  312. {
  313. // also dequeue everyone else
  314. relation.Characters.ForeachCharacter(chr =>
  315. {
  316. if (chr != _chr)
  317. {
  318. chr.ExecuteInContext(() =>
  319. {
  320. chr.Battlegrounds.RemoveRelation(bgId);
  321. });
  322. }
  323. });
  324. }
  325. }
  326. }
  327. /// <summary>
  328. /// Invites this Character to the given Battleground or enqueues him/her.
  329. /// </summary>
  330. internal void InviteTo(BattlegroundTeam team)
  331. {
  332. var index = GetIndex(team.Battleground.Template.Id);
  333. BattlegroundRelation relation;
  334. if (index == -1)
  335. {
  336. index = AddRelation(relation = new BattlegroundRelation(team.Queue, _chr, false));
  337. }
  338. else
  339. {
  340. relation = _relations[index];
  341. }
  342. InviteTo(team, index, relation);
  343. }
  344. internal void InviteTo(BattlegroundTeam team, int queueIndex, BattlegroundRelation relation)
  345. {
  346. _chr.EnsureContext();
  347. relation.IsEnqueued = false;
  348. var bg = team.Battleground;
  349. var invite = new BattlegroundInvitation(team, queueIndex);
  350. _chr.Battlegrounds.Invitation = invite;
  351. invite.CancelTimer = _chr.CallDelayed(BattlegroundMgr.InvitationTimeoutMillis, obj =>
  352. {
  353. RemoveRelation(bg.Template.Id);
  354. });
  355. BattlegroundHandler.SendStatusInvited(_chr);
  356. }
  357. /// <summary>
  358. ///
  359. /// </summary>
  360. /// <param name="relation"></param>
  361. /// <returns>The index of the newly created relation</returns>
  362. public int AddRelation(BattlegroundRelation relation)
  363. {
  364. _chr.EnsureContext();
  365. var index = (int)ArrayUtil.AddOnlyOne(ref _relations, relation);
  366. _relationCount++;
  367. var queue = relation.Queue.ParentQueue;
  368. if (queue != null)
  369. {
  370. BattlegroundHandler.SendStatusEnqueued(_chr, index, relation, queue);
  371. }
  372. return index;
  373. }
  374. public int GetIndex(BattlegroundRelation request)
  375. {
  376. var queue = request.Queue.ParentQueue;
  377. if (queue != null)
  378. {
  379. return GetIndex(queue.Template.Id);
  380. }
  381. return 0;
  382. }
  383. /// <summary>
  384. ///
  385. /// </summary>
  386. /// <param name="id"></param>
  387. /// <returns></returns>
  388. /// <remarks>Requires Context</remarks>
  389. public int GetIndex(BattlegroundId id)
  390. {
  391. _chr.ContextHandler.EnsureContext();
  392. for (var i = 0; i < _relations.Length; i++)
  393. {
  394. var request = _relations[i];
  395. if (request != null && request.Queue.ParentQueue.Template.Id == id)
  396. {
  397. return i;
  398. }
  399. }
  400. return -1;
  401. }
  402. /// <summary>
  403. /// Cancel all relations
  404. /// </summary>
  405. public void CancelAllRelations()
  406. {
  407. for (var i = 0; i < _relations.Length; i++)
  408. {
  409. var relation = _relations[i];
  410. if (relation != null)
  411. {
  412. CancelRelation(i, relation, false);
  413. }
  414. }
  415. }
  416. internal void OnLogout()
  417. {
  418. CancelAllRelations();
  419. }
  420. public bool IsParticipating(BattlegroundId bgId)
  421. {
  422. if (Team != null)
  423. {
  424. return Team.Battleground.Template.Id == bgId;
  425. }
  426. return false;
  427. }
  428. }
  429. }