using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
namespace OpenVIII.IGMData
{
public class NamesHPATB : IGMData.Base
{
#region Fields
private const float ATBalpha = .8f;
private const int ATBWidth = 150;
private static Texture2D dot;
private static object locker = new object();
private Damageable.BattleMode BattleMode = Damageable.BattleMode.EndTurn;
private bool EventAdded = false;
#endregion Fields
#region Destructors
~NamesHPATB()
{
if (EventAdded)
Damageable.BattleModeChangeEventHandler -= ModeChangeEvent;
}
#endregion Destructors
#region Enums
private enum DepthID : byte
{
///
/// Name
///
Name,
///
/// HP
///
HP,
///
/// Box with GF HP
///
GFHPBox,
///
/// Box with GF name
///
GFNameBox,
///
/// ATB charging orange red or dark blue (haste/slowed)
///
ATBCharging,
///
/// ATB charged blink yellow
///
ATBCharged,
///
/// blue white gradient that decreases as the gf is charging.
///
GFCharging,
///
/// border around ATB bar
///
ATBBorder,
///
/// Max?
///
Max
}
#endregion Enums
#region Methods
public static NamesHPATB Create(Rectangle pos, Damageable damageable) => Create(1, (int)DepthID.Max, new IGMDataItem.Empty { Pos = pos }, 1, 3, damageable);
public static Texture2D ThreadUnsafeOperations()
{
lock (locker)
{
if (dot == null)
{
//if (Memory.IsMainThread)
//{
Texture2D localdot = new Texture2D(Memory.graphics.GraphicsDevice, 4, 4);
Color[] tmp = new Color[localdot.Height * localdot.Width];
for (int i = 0; i < tmp.Length; i++)
tmp[i] = Color.White;
localdot.SetData(tmp);
dot = localdot;
IGMDataItem.Gradient.ATB.ThreadUnsafeOperations(ATBWidth);
//}
//else throw new Exception("Must be in main thread!");
}
return dot;
}
}
public override void ModeChangeEvent(object sender, Enum e)
{
if (!e.Equals(BattleMode))
{
base.ModeChangeEvent(sender, e);
BattleMode = (Damageable.BattleMode)e;
if (!e.Equals(Damageable.BattleMode.EndTurn)) //because endturn triggers BattleMenu refresh.
Refresh();
}
}
public override void Refresh(Damageable damageable)
{
if (EventAdded && damageable != Damageable)
{
EventAdded = false;
if (Damageable != null)
Damageable.BattleModeChangeEventHandler -= ModeChangeEvent;
}
base.Refresh(damageable);
}
public override void Refresh()
{
if (Damageable != null)
{
if (Memory.State?.Characters != null && Damageable.GetCharacterData(out Saves.CharacterData c))
{
List> party = GetParty();
if (GetCharPos(party) == 0xFF) return;
}
else
{
}
sbyte pos = PartyPos;
Rectangle rectangle = SIZE[0];
Vector2 vector = SIZE[1].Location.ToVector2() - SIZE[0].Location.ToVector2();
rectangle.Offset(vector * pos);
Rectangle atbbarpos = new Rectangle(rectangle.X + 230, rectangle.Y + 12, ATBWidth, 15);
((IGMDataItem.Gradient.ATB)ITEM[0, (int)DepthID.ATBCharging]).Pos = atbbarpos;
((IGMDataItem.Texture)ITEM[0, (byte)DepthID.ATBCharged]).Pos = atbbarpos;
((IGMDataItem.Icon)ITEM[0, (byte)DepthID.ATBBorder]).Pos = atbbarpos;
((IGMDataItem.Gradient.GF)ITEM[0, (byte)DepthID.GFCharging]).Pos = atbbarpos;
((IGMDataItem.Text)ITEM[0, (byte)DepthID.Name]).Data = Damageable.Name;
((IGMDataItem.Text)ITEM[0, (byte)DepthID.Name]).Pos = new Rectangle(rectangle.X - 60, rectangle.Y, 0, 0);
((IGMDataItem.Integer)ITEM[0, (byte)DepthID.HP]).Pos = new Rectangle(rectangle.X + 128, rectangle.Y, 0, 0);
((IGMDataItem.Text)ITEM[0, (byte)DepthID.Name]).Draw(true);
((IGMDataItem.Integer)ITEM[0, (byte)DepthID.HP]).Draw(true);
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFHPBox]).Pos = Rectangle.Union(
((IGMDataItem.Text)ITEM[0, (byte)DepthID.Name]).DataSize,
((IGMDataItem.Integer)ITEM[0, (byte)DepthID.HP]).DataSize);
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFHPBox]).Y -= 4;
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFNameBox]).Y = ((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFHPBox]).Y;
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFNameBox]).Height = ((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFHPBox]).Height = rectangle.Height;
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFNameBox]).X =
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFHPBox]).X -
(((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFHPBox]).Width * 3) / 8;
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFNameBox]).Width = (((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFHPBox]).Width * 7) / 8;
if (Damageable.SummonedGF != null)
{
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFNameBox]).Data = Damageable.SummonedGF.Name;
((IGMDataItem.Box)ITEM[0, (byte)DepthID.GFHPBox]).Data = $"{Damageable.SummonedGF.CurrentHP()}";
}
if (EventAdded == false)
{
EventAdded = true;
Damageable.BattleModeChangeEventHandler += ModeChangeEvent;
}
bool blink = false;
bool charging = false;
BattleMode = (Damageable.BattleMode)Damageable.GetBattleMode();
ITEM[0, (byte)DepthID.HP].Show();
ITEM[0, (byte)DepthID.Name].Show();
ITEM[0, (byte)DepthID.GFNameBox].Hide();
ITEM[0, (byte)DepthID.GFHPBox].Hide();
ITEM[0, (int)DepthID.ATBCharged].Hide();
ITEM[0, (int)DepthID.GFCharging].Hide();
ITEM[0, (int)DepthID.ATBCharging].Hide();
if (BattleMode.Equals(Damageable.BattleMode.YourTurn))
{
((IGMDataItem.Texture)ITEM[0, (int)DepthID.ATBCharged]).Color = Color.LightYellow * ATBalpha;
blink = true;
}
else if (BattleMode.Equals(Damageable.BattleMode.ATB_Charged))
{
((IGMDataItem.Texture)ITEM[0, (int)DepthID.ATBCharged]).Color = Color.Yellow * ATBalpha;
}
else if (BattleMode.Equals(Damageable.BattleMode.ATB_Charging))
{
charging = true;
((IGMDataItem.Gradient.ATB)ITEM[0, (int)DepthID.ATBCharging]).Refresh(Damageable);
ITEM[0, (int)DepthID.ATBCharging].Show();
}
else if (BattleMode.Equals(Damageable.BattleMode.GF_Charging))
{
charging = true;
ITEM[0, (byte)DepthID.HP].Hide();
ITEM[0, (byte)DepthID.Name].Hide();
ITEM[0, (byte)DepthID.GFNameBox].Show();
ITEM[0, (byte)DepthID.GFHPBox].Show();
ITEM[0, (int)DepthID.GFCharging].Show();
ITEM[0, (int)DepthID.GFCharging].Refresh(Damageable.SummonedGF);
}
if (!charging)
{
ITEM[0, (int)DepthID.ATBCharged].Show();
}
((IGMDataItem.Texture)ITEM[0, (int)DepthID.ATBCharged]).Blink = blink;
((IGMDataItem.Text)ITEM[0, (byte)DepthID.Name]).Blink = blink;
((IGMDataItem.Integer)ITEM[0, (byte)DepthID.HP]).Blink = blink;
base.Refresh();
}
}
public override bool Update()
{
if (ITEM[0, 2].GetType() == typeof(IGMDataItem.Gradient.ATB))
{
IGMDataItem.Gradient.ATB hg = (IGMDataItem.Gradient.ATB)ITEM[0, 2];
}
if (Damageable != null)
{
int HP = Damageable.CurrentHP();
int CriticalHP = Damageable.CriticalHP();
Font.ColorID colorid = Font.ColorID.White;
if (HP < CriticalHP)
{
colorid = Font.ColorID.Yellow;
}
if (HP <= 0)
{
colorid = Font.ColorID.Red;
}
((IGMDataItem.Text)ITEM[0, (byte)DepthID.Name]).FontColor = colorid;
((IGMDataItem.Integer)ITEM[0, (byte)DepthID.HP]).Data = HP;
((IGMDataItem.Integer)ITEM[0, (byte)DepthID.HP]).FontColor = colorid;
}
return base.Update();
}
protected override void Init()
{
base.Init();
ThreadUnsafeOperations();
// TODO: make a font render that can draw right to left from a point. For Right aligning the names.
Rectangle atbbarpos = new Rectangle(SIZE[0].X + 230, SIZE[0].Y + 12, ATBWidth, 15);
ITEM[0, (byte)DepthID.Name] = new IGMDataItem.Text { };
ITEM[0, (byte)DepthID.HP] = new IGMDataItem.Integer { Spaces = 4, NumType = Icons.NumType.Num_8x16_1 };
ITEM[0, (byte)DepthID.GFHPBox] = new IGMDataItem.Box { Options = Box_Options.Right | Box_Options.Middle };
ITEM[0, (byte)DepthID.GFHPBox].Hide();
ITEM[0, (byte)DepthID.GFNameBox] = new IGMDataItem.Box { Options = Box_Options.Center | Box_Options.Middle };
ITEM[0, (byte)DepthID.GFNameBox].Hide();
ITEM[0, (byte)DepthID.ATBBorder] = new IGMDataItem.Icon { Data = Icons.ID.Size_08x64_Bar, Palette = 0 };
ITEM[0, (byte)DepthID.ATBCharged] = new IGMDataItem.Texture { Data = dot, Color = Color.LightYellow * ATBalpha, Faded_Color = new Color(125, 125, 0, 255) * ATBalpha };
ITEM[0, (byte)DepthID.ATBCharged].Hide();
ITEM[0, (int)DepthID.ATBCharging] = IGMDataItem.Gradient.ATB.Create(atbbarpos);
ITEM[0, (int)DepthID.GFCharging] = IGMDataItem.Gradient.GF.Create(atbbarpos);
((IGMDataItem.Gradient.ATB)ITEM[0, (byte)DepthID.ATBCharging]).Color = Color.Orange * ATBalpha;
((IGMDataItem.Gradient.ATB)ITEM[0, (byte)DepthID.ATBCharging]).Faded_Color = Color.Orange * ATBalpha;
((IGMDataItem.Gradient.ATB)ITEM[0, (byte)DepthID.ATBCharging]).Refresh(Damageable);
}
private static List> GetParty()
{
if (Memory.State != null && Memory.State.Characters != null)
return Memory.State.Party.Select((element, index) => new { element, index }).ToDictionary(m => m.index, m => m.element).Where(m => !m.Value.Equals(Characters.Blank)).ToList();
return null;
}
private byte GetCharPos() => GetCharPos(GetParty());
private byte GetCharPos(List> party)
{
int i = -1;
if (party != null && (i = party.FindIndex(x => Damageable.GetCharacterData(out Saves.CharacterData c) && x.Value == c.ID)) > -1)
return checked((byte)i);
return 0xFF;
}
#endregion Methods
}
}