| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- using Microsoft.Xna.Framework;
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq;
- namespace OpenVIII.IGMData
- {
- public class Commands : Base, IDisposable
- {
- #region Fields
- private bool disposedValue = false;
- private bool EventAdded;
- private Kernel.BattleCommand[] commands;
- private Battle.Dat.Abilities[] enemycommands;
- private int nonbattleWidth;
- private sbyte page = 0;
- private bool skipRefresh;
- private static int s_cidoff = 0;
- #endregion Fields
- #region Properties
- //Selphie_Slots
- private SelphieSlots Selphie_Slots { get => (SelphieSlots)ITEM[Offsets.Selphie_Slots, 0]; set => ITEM[Offsets.Selphie_Slots, 0] = value; }
- private Pool.GF GFPool { get => (Pool.GF)ITEM[Offsets.GF_Pool, 0]; set => ITEM[Offsets.GF_Pool, 0] = value; }
- private Pool.Item ItemPool { get => (Pool.Item)ITEM[Offsets.Item_Pool, 0]; set => ITEM[Offsets.Item_Pool, 0] = value; }
- private Pool.Magic MagPool { get => (Pool.Magic)ITEM[Offsets.Mag_Pool, 0]; set => ITEM[Offsets.Mag_Pool, 0] = value; }
- private Pool.BlueMagic BluePool { get => (Pool.BlueMagic)ITEM[Offsets.Blue_Pool, 0]; set => ITEM[Offsets.Blue_Pool, 0] = value; }
- private Pool.Combine CombinePool { get => (Pool.Combine)ITEM[Offsets.Combine_Pool, 0]; set => ITEM[Offsets.Combine_Pool, 0] = value; }
- private Pool.Bullet BulletPool { get => (Pool.Bullet)ITEM[Offsets.Bullet_Pool, 0]; set => ITEM[Offsets.Bullet_Pool, 0] = value; }
- private IGMDataItem.Icon LimitArrow { get => (IGMDataItem.Icon)ITEM[Offsets.Limit_Arrow, 0]; set => ITEM[Offsets.Limit_Arrow, 0] = value; }
- public IGMData.Target.Group TargetGroup
- {
- get => (IGMData.Target.Group)ITEM[Offsets.Targets_Window, 0];
- protected set => ITEM[Offsets.Targets_Window, 0] = value;
- }
- public IGMData.Pool.EnemyAttacks EnemyAttacks
- {
- get => ((IGMData.Pool.EnemyAttacks)ITEM[Offsets.Enemy_Attacks_Pool, 0]);
- protected set => ITEM[Offsets.Enemy_Attacks_Pool, 0] = value;
- }
- private static class Offsets
- {
- public const int
- Limit_Arrow = 4,
- Start = 5,
- Blue_Pool = Start,
- Mag_Pool = 6,
- GF_Pool = 7,
- Enemy_Attacks_Pool = 8,
- Item_Pool = 9,
- Targets_Window = 10,
- Combine_Pool = 11,
- Selphie_Slots = 12,
- Bullet_Pool = 13,
- Count = 14;
- }
- //base.Inputs_CANCEL();
- private static int Cidoff
- {
- get => s_cidoff; set
- {
- if (value >= Memory.KernelBin.BattleCommands.Count)
- value = 0;
- else if (value < 0)
- value = Memory.KernelBin.BattleCommands.Count - 1;
- s_cidoff = value;
- }
- }
- #endregion Properties
- #region Methods
- // To detect redundant calls
- 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.
- disposedValue = true;
- UnsubscribeEvents();
- GC.SuppressFinalize(this);
- }
- }
- // 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);
- public static Commands Create(Rectangle pos, Damageable damageable = null, bool battle = false)
- {
- var r = new Commands
- {
- skipRefresh = damageable == null,
- Battle = battle
- };
- r.SetDamageable(damageable, null);
- r.Init(Offsets.Count, 1, new IGMDataItem.Box { Pos = pos, Title = Icons.ID.COMMAND }, 1, 4);
- return r;
- }
- public override bool Inputs()
- {
- var ret = false;
- var found = false;
- //loop through Start to Count
- //This is to only check for input from the dialogs that popup.
- for (var i = Offsets.Start; i < Offsets.Count; i++)
- {
- if (InputITEM(ITEM[i, 0], ref ret))
- {
- found = true;
- break;
- }
- }
- if (!found)
- {
- Cursor_Status |= Cursor_Status.Enabled;
- Cursor_Status &= ~Cursor_Status.Blinking;
- ret = base.Inputs();
- }
- return ret;
- }
- public override bool Inputs_CANCEL() => false;
- public override void Inputs_Left()
- {
- if (Battle && CURSOR_SELECT == 0 && CrisisLevel > -1)
- {
- if (page == 1)
- {
- Refresh();
- skipsnd = true;
- base.Inputs_Left();
- }
- }
- }
- public override bool Inputs_OKAY()
- {
- var c = commands[CURSOR_SELECT];
- if (c == null) return false;
- base.Inputs_OKAY();
- TargetGroup.SelectTargetWindows(c);
- if (c.BattleID == 1 && Damageable != null && Damageable.GetEnemy(out var e))
- {
- var ecattacks = e.Abilities.Where(x => x.Monster != null);
- if (ecattacks.Count() == 1)
- {
- var monster = ecattacks.First().Monster;
- TargetGroup.SelectTargetWindows(monster);
- TargetGroup.ShowTargetWindows();
- }
- else
- {
- EnemyAttacks.Refresh();
- EnemyAttacks.Show();
- }
- return true;
- }
- else
- switch (c.BattleID)
- {
- default:
- // ITEM[Targets_Window, 0].Show();
- throw new ArgumentOutOfRangeException($"{this}::Command ({c.Name}, {c.BattleID}) doesn't have explict operation defined!");
- case 1: //ATTACK
- case 5: //Renzokuken
- case 12: //MUG
- case 6: //DRAW
- case 29: //CARD
- case 32: //ABSORB
- case 28: //DARKSIDE
- case 30: //DOOM
- case 26: //RECOVER
- case 27: //REVIVE
- case 33: //LVL DOWN
- case 34: //LVL UP
- case 31: //Kamikaze
- case 38: //MiniMog
- case 24: //MADRUSH
- case 25: //Treatment
- case 20: //Desperado
- case 21: //Blood Pain
- case 22: //Massive Anchor
- case 7: //DEVOUR
- case 11: //DUEL
- case 17: //FIRE CROSS / NO MERCY
- case 18: //SORCERY / ICE STRIKE
- TargetGroup.ShowTargetWindows();
- return true;
- case 16: // SLOT
- //TODO add slot menu to randomly choose spell to cast.
- Selphie_Slots.Show();
- Selphie_Slots.Refresh();
- return true;
- case 14: //SHOT
- BulletPool.Show();
- BulletPool.Refresh();
- return true;
- case 19: //COMBINE (ANGELO or ANGEL WING)
- //TODO see if ANGEL WING unlock if so show menu to choose angelo or angel wing.
- //TargetGroup.ShowTargetWindows();
- CombinePool.Show();
- CombinePool.Refresh();
- return true;
- case 0: //null
- case 9: //CAST is part of DRAW menu.
- case 10: // Stock is part of DRAW menu.
- case 8: // NOMSG
- case 13: // NOMSG
- return false;
- case 36: //DOUBLE
- case 37: //TRIPLE
- //TODO 2 casts 2 targets
- //TODO 3 casts 3 targets
- MagPool.Show();
- MagPool.Refresh();
- return true;
- case 2: //magic
- //TODO ADD a menu for DOUBLE and TRIPLE to choose SINGLE DOUBLE OR TRIPLE
- case 35: //SINGLE
- MagPool.Show();
- MagPool.Refresh();
- return true;
- case 3: //GF
- GFPool.Show();
- GFPool.Refresh();
- return true;
- case 4: //items
- ItemPool.Show();
- ItemPool.Refresh();
- return true;
- case 15: //Blue magic
- BluePool.Show();
- BluePool.Refresh();
- return true;
- case 23: //Defend
- Debug.WriteLine($"{Damageable.Name} is using {c.Name}({c.BattleID})");
- Damageable.EndTurn();
- return true;
- }
- }
- public override void Inputs_Right()
- {
- if (Battle && CURSOR_SELECT == 0 && CrisisLevel > -1)
- {
- if (page == 0 && Damageable.GetCharacterData(out var c))
- {
- commands[CURSOR_SELECT] = c.CharacterStats.Limit;
- ((IGMDataItem.Text)ITEM[0, 0]).Data = commands[CURSOR_SELECT].Name;
- skipsnd = true;
- base.Inputs_Right();
- page++;
- LimitArrow.Hide();
- }
- }
- }
- /// <summary>
- /// Things that may of changed before screen loads or junction is changed.
- /// </summary>
- public override void Refresh()
- {
- if (Damageable != null)
- {
- if (!skipRefresh)
- {
- if (Battle)
- {
- if ((Damageable.IsGameOver || !Damageable.GetBattleMode().Equals(Damageable.BattleMode.YourTurn)))
- {
- Hide();
- goto end;
- }
- else
- Show();
- }
- if (Damageable.GetEnemy(out var e))
- {
- enemycommands = e.Abilities;
- var pos = 0;
- bool Item, Magic, Attack;
- Item = Magic = Attack = false;
- foreach (var a in enemycommands)
- {
- if (pos >= Rows) break;
- ((IGMDataItem.Text)ITEM[pos, 0]).Hide();
- BLANKS[pos] = true;
- if (a.Item != null)
- {
- Item = true;
- //((IGMDataItem.Text)ITEM[pos, 0]).Data = a.ITEM.Value.Name;
- //((IGMDataItem.Text)ITEM[pos, 0]).Show();
- //BLANKS[pos] = false;
- }
- else if (a.Magic != null)
- {
- Magic = true;
- //((IGMDataItem.Text)ITEM[pos, 0]).Data = a.MAGIC.Name;
- //((IGMDataItem.Text)ITEM[pos, 0]).Show();
- //BLANKS[pos] = false;
- }
- else if (a.Monster != null)
- {
- Attack = true;
- //((IGMDataItem.Text)ITEM[pos, 0]).Data = a.MONSTER.Name;
- //((IGMDataItem.Text)ITEM[pos, 0]).Show();
- //BLANKS[pos] = false;
- }
- //((IGMDataItem.Text)ITEM[pos, 0]).Pos = SIZE[pos];
- //pos++;
- }
- if (Attack)
- {
- var ecattacks = enemycommands.Where(x => x.Monster != null);
- AddCommand(Memory.KernelBin.BattleCommands[1], (ecattacks.Count() == 1 ? ecattacks.First().Monster.Name : null));
- }
- if (Magic || e.DrawList.Any(x => x.Data != null))
- AddCommand(Memory.KernelBin.BattleCommands[2]);
- if (Item || e.DropList.Any(x => x.Data?.Battle != null) || e.MugList.Any(x => x.Data?.Battle != null))
- AddCommand(Memory.KernelBin.BattleCommands[4]);
- if (e.JunctionedGFs?.Any() ?? false)
- AddCommand(Memory.KernelBin.BattleCommands[3]);
- void AddCommand(Kernel.BattleCommand c, FF8String alt = null)
- {
- commands[pos] = c;
- ((IGMDataItem.Text)ITEM[pos, 0]).Data = alt ?? c.Name;
- ((IGMDataItem.Text)ITEM[pos, 0]).Pos = SIZE[pos];
- ITEM[pos, 0].Show();
- BLANKS[pos] = false;
- pos++;
- }
- for (; pos < Rows; pos++)
- {
- ITEM[pos, 0].Hide();
- BLANKS[pos] = true;
- }
- }
- else if (Memory.State.Characters && Damageable.GetCharacterData(out var c))
- {
- if (Battle)
- c.GenerateCrisisLevel();
- var DataSize = Rectangle.Empty;
- page = 0;
- Cursor_Status &= ~Cursor_Status.Horizontal;
- commands[0] = Memory.KernelBin.BattleCommands[(c.Abilities.Contains(Kernel.Abilities.Mug) ? 12 : 1)];
- ITEM[0, 0] = new IGMDataItem.Text
- {
- Data = commands[0].Name,
- Pos = SIZE[0]
- };
- for (var pos = 1; pos < Rows; pos++)
- {
- var cmd = c.Commands[pos - 1];
- if (cmd != Kernel.Abilities.None)
- {
- if (!Memory.KernelBin.CommandAbilities.TryGetValue(cmd, out var cmdval))
- {
- continue;
- }
- #if DEBUG
- if (!Battle) commands[pos] = cmdval.BattleCommand;
- else commands[pos] = Memory.KernelBin.BattleCommands[Cidoff++];
- #else
- commands[pos] = cmdval.BattleCommand;
- #endif
- ((IGMDataItem.Text)ITEM[pos, 0]).Data = commands[pos].Name;
- ((IGMDataItem.Text)ITEM[pos, 0]).Pos = SIZE[pos];
- ITEM[pos, 0].Show();
- CheckBounds(ref DataSize, pos);
- BLANKS[pos] = false;
- }
- else
- {
- ITEM[pos, 0]?.Hide();
- BLANKS[pos] = true;
- }
- }
- const int crisisWidth = 294;
- if (Battle && CrisisLevel > -1)
- {
- CONTAINER.Width = crisisWidth;
- LimitArrow.Show();
- }
- else
- {
- CONTAINER.Width = nonbattleWidth;
- LimitArrow.Hide();
- }
- AutoAdjustContainerWidth(DataSize);
- }
- }
- end:
- skipRefresh = false;
- base.Refresh();
- }
- }
- public override void Refresh(Damageable damageable)
- {
- if (Damageable != damageable)
- skipRefresh = false;
- base.Refresh(damageable);
- }
- /// <summary>
- /// Things fixed at startup.
- /// </summary>
- protected override void Init()
- {
- base.Init();
- BLANKS[Offsets.Limit_Arrow] = true;
- for (var pos = 0; pos < Rows; pos++)
- ITEM[pos, 0] = new IGMDataItem.Text
- {
- Pos = SIZE[pos]
- };
- GFPool = Pool.GF.Create(new Rectangle(X + 50, Y - 20, 320, 192), Damageable, true);
- GFPool.Hide();
- BluePool = Pool.BlueMagic.Create(new Rectangle(X + 50, Y - 20, 300, 192), Damageable, true);
- BluePool.Hide();
- MagPool = Pool.Magic.Create(new Rectangle(X + 50, Y - 20, 300, 192), Damageable, true);
- MagPool.Hide();
- ItemPool = Pool.Item.Create(new Rectangle(X + 50, Y - 22, 400, 194), Damageable, true);
- ItemPool.Hide();
- EnemyAttacks = Pool.EnemyAttacks.Create(new Rectangle(X + 50, Y - 22, 400, 194), Damageable, true);
- EnemyAttacks.Hide();
- CombinePool = Pool.Combine.Create(new Rectangle(X + 50, Y - 22, 300, 112), Damageable, true);
- CombinePool.Hide();
- BulletPool = Pool.Bullet.Create(new Rectangle(X + 50, Y - 22, 400, 168), Damageable, true);
- BulletPool.Hide();
- Selphie_Slots = SelphieSlots.Create(new Rectangle(X + 50, Y - 22, 300, 168), Damageable, true);
- Selphie_Slots.Hide();
- LimitArrow = new IGMDataItem.Icon { Data = Icons.ID.Arrow_Right, Pos = new Rectangle(SIZE[0].X + Width - 55, SIZE[0].Y, 0, 0), Palette = 2, Faded_Palette = 7, Blink = true };
- LimitArrow.Hide();
- TargetGroup = Target.Group.Create(Damageable);
- TargetGroup.Hide();
- commands = new Kernel.BattleCommand[Rows];
- enemycommands = null;
- PointerZIndex = Offsets.Limit_Arrow;
- nonbattleWidth = Width;
- }
- protected override void InitShift(int i, int col, int row)
- {
- base.InitShift(i, col, row);
- SIZE[i].Inflate(-22, -8);
- SIZE[i].Offset(0, 12 + (-8 * row));
- }
- private Damageable.BattleMode BattleMode = Damageable.BattleMode.EndTurn;
- public override void ModeChangeEvent(object sender, Enum e)
- {
- base.ModeChangeEvent(sender, e);
- if (e.GetType() == typeof(Damageable.BattleMode) && !BattleMode.Equals(e))
- {
- BattleMode = (Damageable.BattleMode)e;
- Refresh();
- }
- }
- public override Damageable Damageable
- {
- get => base.Damageable;
- protected set
- {
- if (value != base.Damageable)
- {
- if (Battle)
- {
- UnsubscribeEvents();
- base.Damageable = value;
- SubscribeEvents();
- }
- else
- base.Damageable = value;
- }
- }
- }
- public sbyte CrisisLevel => Damageable != null && Damageable.GetCharacterData(out var c) ? c.CurrentCrisisLevel : (sbyte)-1;
- private void SubscribeEvents()
- {
- if (Damageable != null && !EventAdded)
- {
- Damageable.BattleModeChangeEventHandler += ModeChangeEvent;
- Damageable.BattleModeChangeEventHandler += ItemPool.ModeChangeEvent;
- Damageable.BattleModeChangeEventHandler += MagPool.ModeChangeEvent;
- EventAdded = true;
- }
- }
- private void UnsubscribeEvents()
- {
- if (Damageable != null && EventAdded)
- {
- Damageable.BattleModeChangeEventHandler -= ModeChangeEvent;
- Damageable.BattleModeChangeEventHandler -= ItemPool.ModeChangeEvent;
- Damageable.BattleModeChangeEventHandler -= MagPool.ModeChangeEvent;
- EventAdded = false;
- }
- }
- #endregion Methods
- ~Commands()
- {
- Dispose(false);
- }
- }
- }
|