using Microsoft.Xna.Framework;
using OpenVIII.IGMDataItem;
using System;
using System.Collections.Concurrent;
namespace OpenVIII.IGMData.Group
{
public class PlayerEXP : IGMData.Group.Base, IDisposable
{
#region Fields
///
/// The Speed the exp counts down.
/// Cannot be 0.
/// The smaller the number the faster it'll count down.
///
///
/// -
/// 1
/// 1000 per second
///
/// -
/// 2
/// 500 per second
///
/// -
/// 3
/// 333.333... per second
///
/// -
/// 4
/// 250 per second
///
///
private const float speedOfEarningExp = 4;
///
/// Total exp left to earn.
///
private int _exp;
///
/// Are we in counting down exp mode.
///
private bool countingDown = false;
private bool disposedValue = false;
///
/// The looping exp sound. Need to track the object here to stop the loop.
///
private AV.Audio EXPsnd = null;
private Box header;
///
/// Keeps remainder between cycles
///
private double remaining = 0;
#endregion Fields
#region Destructors
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
~PlayerEXP()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
#endregion Destructors
#region Properties
public int EXP
{
get => _exp; set
{
_exp = value;
RefreshEXP();
}
}
public ConcurrentDictionary EXPExtra { get; set; }
public bool NoEarnExp { get; internal set; } = false;
private bool remainEXP => (_exp > 0 || EXPExtra != null && EXPExtra.Count > 0);
#endregion Properties
#region Methods
public static new PlayerEXP Create(params Menu_Base[] d) => Create(d);
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
GC.SuppressFinalize(this);
}
public override void Draw()
{
if (Enabled)
header?.Draw();
base.Draw();
}
public override bool Inputs_CANCEL() => false;
public override bool Inputs_OKAY()
{
base.Inputs_OKAY();
if (!countingDown && remainEXP)
{
countingDown = true;
if (EXPsnd == null)
EXPsnd = init_debugger_Audio.PlaySound(34, loop: true);
return true;
}
else if (countingDown && remainEXP)
{
countingDown = false;
EXPsnd.Stop();
EXPsnd = null;
EXP = 0;
return true;
}
return false;
}
public override bool Update()
{
if (countingDown)
{
if (remainEXP)
{
if ((remaining += Memory.gameTime.ElapsedGameTime.TotalMilliseconds / speedOfEarningExp) > 1)
{
if (EXP > 0)
{
EXP -= (int)remaining;
}
else
{
int total = 0;
foreach (System.Collections.Generic.KeyValuePair e in EXPExtra)
{
if (e.Value > 0)
total += (EXPExtra[e.Key] -= (int)remaining);
RefreshEXP();
}
if (total <= 0)
EXPExtra = null;
}
remaining -= (int)remaining;
}
}
else
{
countingDown = false;
EXPsnd.Stop();
EXPsnd = null;
}
}
return base.Update();
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects).
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
header.Dispose();
disposedValue = true;
}
}
protected override void Init()
{
base.Init();
Cursor_Status |= (Cursor_Status.Hidden | (Cursor_Status.Enabled | Cursor_Status.Static));
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 };
}
private void RefreshEXP()
{
foreach (Menu_Base i in ITEM)
{
int tmpexp = EXP;
if (EXPExtra != null && i.Damageable.GetCharacterData(out Saves.CharacterData c) && EXPExtra.TryGetValue(c.ID, out int bonus))
tmpexp += bonus;
((IGMData.PlayerEXP)i).NoEarnExp = NoEarnExp;
((IGMData.PlayerEXP)i).EXP = tmpexp;
}
header.Width = Width;
}
#endregion Methods
}
}