PlayerEXP.cs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using Microsoft.Xna.Framework;
  5. using OpenVIII.AV;
  6. using OpenVIII.IGMDataItem;
  7. namespace OpenVIII.IGMData.Group
  8. {
  9. public class PlayerEXP : Base, IDisposable
  10. {
  11. #region Fields
  12. /// <summary>
  13. /// <para>The Speed the exp counts down.</para>
  14. /// <para>Cannot be 0.</para>
  15. /// The smaller the number the faster it'll Count down.
  16. /// </summary>
  17. /// <list type="bullet">
  18. /// <item>
  19. /// <term>1</term>
  20. /// <description>1000 per second</description>
  21. /// </item>
  22. /// <item>
  23. /// <term>2</term>
  24. /// <description>500 per second</description>
  25. /// </item>
  26. /// <item>
  27. /// <term>3</term>
  28. /// <description>333.333... per second</description>
  29. /// </item>
  30. /// <item>
  31. /// <term>4</term>
  32. /// <description>250 per second</description>
  33. /// </item>
  34. /// </list>
  35. private const float speedOfEarningExp = 4;
  36. /// <summary>
  37. /// Total exp left to earn.
  38. /// </summary>
  39. private int _exp;
  40. /// <summary>
  41. /// Are we in counting down exp mode.
  42. /// </summary>
  43. private bool countingDown;
  44. private bool disposedValue;
  45. /// <summary>
  46. /// The looping exp sound. Need to track the object here to stop the loop.
  47. /// </summary>
  48. private Audio EXPsnd;
  49. private Box header;
  50. /// <summary>
  51. /// Keeps remainder between cycles
  52. /// </summary>
  53. private double remaining;
  54. #endregion Fields
  55. #region Destructors
  56. // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
  57. ~PlayerEXP()
  58. {
  59. // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
  60. Dispose(false);
  61. }
  62. #endregion Destructors
  63. #region Properties
  64. public int EXP
  65. {
  66. get => _exp; set
  67. {
  68. _exp = value;
  69. RefreshEXP();
  70. }
  71. }
  72. public ConcurrentDictionary<Characters, int> EXPExtra { get; set; }
  73. public bool NoEarnExp { get; internal set; } = false;
  74. private bool remainEXP => (_exp > 0 || EXPExtra != null && EXPExtra.Count > 0);
  75. #endregion Properties
  76. #region Methods
  77. public static new PlayerEXP Create(params Menu_Base[] d) => Create<PlayerEXP>(d);
  78. // This code added to correctly implement the disposable pattern.
  79. public void Dispose()
  80. {
  81. // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
  82. Dispose(true);
  83. // TODO: uncomment the following line if the finalizer is overridden above.
  84. GC.SuppressFinalize(this);
  85. }
  86. public override void Draw()
  87. {
  88. if (Enabled)
  89. header?.Draw();
  90. base.Draw();
  91. }
  92. public override bool Inputs_CANCEL() => false;
  93. public override bool Inputs_OKAY()
  94. {
  95. base.Inputs_OKAY();
  96. if (!countingDown && remainEXP)
  97. {
  98. countingDown = true;
  99. if (EXPsnd == null)
  100. EXPsnd = Sound.Play(34, loop: true);
  101. return true;
  102. }
  103. if (countingDown && remainEXP)
  104. {
  105. countingDown = false;
  106. EXPsnd.Stop();
  107. EXPsnd = null;
  108. EXP = 0;
  109. return true;
  110. }
  111. return false;
  112. }
  113. public override bool Update()
  114. {
  115. if (countingDown)
  116. {
  117. if (remainEXP)
  118. {
  119. if ((remaining += Memory.ElapsedGameTime.TotalMilliseconds / speedOfEarningExp) > 1)
  120. {
  121. if (EXP > 0)
  122. {
  123. EXP -= (int)remaining;
  124. }
  125. else
  126. {
  127. var total = 0;
  128. if (EXPExtra != null)
  129. {
  130. foreach (var e in EXPExtra)
  131. {
  132. if (e.Value > 0)
  133. total += (EXPExtra[e.Key] -= (int) remaining);
  134. RefreshEXP();
  135. }
  136. if (total <= 0)
  137. EXPExtra = null;
  138. }
  139. }
  140. remaining -= (int)remaining;
  141. }
  142. }
  143. else
  144. {
  145. countingDown = false;
  146. EXPsnd.Stop();
  147. EXPsnd = null;
  148. }
  149. }
  150. return base.Update();
  151. }
  152. protected virtual void Dispose(bool disposing)
  153. {
  154. if (!disposedValue)
  155. {
  156. if (disposing)
  157. {
  158. // TODO: dispose managed state (managed objects).
  159. }
  160. // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
  161. // TODO: set large fields to null.
  162. header.Dispose();
  163. disposedValue = true;
  164. }
  165. }
  166. protected override void Init()
  167. {
  168. base.Init();
  169. Cursor_Status |= (Cursor_Status.Hidden | (Cursor_Status.Enabled | Cursor_Status.Static));
  170. header = new Box { Data = Strings.Name.EXP_received, Pos = new Rectangle(0, 0, CONTAINER.Width, 78), Title = Icons.ID.INFO, Options = Box_Options.Middle };
  171. }
  172. private void RefreshEXP()
  173. {
  174. foreach (var i in ITEM)
  175. {
  176. var tmpexp = EXP;
  177. if (EXPExtra != null && i.Damageable.GetCharacterData(out var c) && EXPExtra.TryGetValue(c.ID, out var bonus))
  178. tmpexp += bonus;
  179. ((IGMData.PlayerExp)i).NoEarnExp = NoEarnExp;
  180. ((IGMData.PlayerExp)i).Exp = tmpexp;
  181. }
  182. header.Width = Width;
  183. }
  184. #endregion Methods
  185. }
  186. }