PlayerEXP.cs 6.3 KB

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