PKHeX/PKHeX.WinForms/Subforms/Save Editors/SAV_Wondercard.cs

614 lines
22 KiB
C#
Raw Normal View History

2014-06-28 21:22:05 +00:00
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
2014-06-28 21:22:05 +00:00
using System.Windows.Forms;
using PKHeX.Core;
2014-06-28 21:22:05 +00:00
namespace PKHeX.WinForms
2014-06-28 21:22:05 +00:00
{
public partial class SAV_Wondercard : Form
{
private readonly SaveFile Origin;
private readonly SaveFile SAV;
public SAV_Wondercard(SaveFile sav, MysteryGift g = null)
2014-06-28 21:22:05 +00:00
{
SAV = (Origin = sav).Clone();
2014-06-28 21:22:05 +00:00
InitializeComponent();
WinFormsUtil.TranslateInterface(this, Main.CurrentLanguage);
mga = SAV.GiftAlbum;
switch (SAV.Generation)
{
case 4:
pba = PopulateViewGiftsG4().ToArray();
break;
case 5:
case 6:
case 7:
pba = PopulateViewGiftsG567().ToArray();
break;
default:
throw new ArgumentException("Game not supported.");
}
foreach (PictureBox pb in pba)
{
pb.AllowDrop = true;
pb.DragDrop += BoxSlot_DragDrop;
pb.DragEnter += BoxSlot_DragEnter;
pb.MouseDown += BoxSlot_MouseDown;
pb.ContextMenuStrip = mnuVSD;
}
SetGiftBoxes();
GetReceivedFlags();
2014-06-28 21:22:05 +00:00
if (LB_Received.Items.Count > 0)
2014-12-10 23:24:34 +00:00
LB_Received.SelectedIndex = 0;
DragEnter += Main_DragEnter;
DragDrop += Main_DragDrop;
2015-04-01 00:58:23 +00:00
if (g == null)
ClickView(pba[0], null);
else
ViewGiftData(g);
2014-06-28 21:22:05 +00:00
}
private MysteryGiftAlbum mga;
private MysteryGift mg;
private readonly PictureBox[] pba;
2014-06-28 21:22:05 +00:00
// Repopulation Functions
private void SetBackground(int index, Image bg)
{
for (int i = 0; i < mga.Gifts.Length; i++)
pba[i].BackgroundImage = index == i ? bg : null;
}
private void SetGiftBoxes()
2014-06-28 21:22:05 +00:00
{
for (int i = 0; i < mga.Gifts.Length; i++)
2014-06-28 21:22:05 +00:00
{
MysteryGift m = mga.Gifts[i];
pba[i].Image = m.Sprite(SAV);
2014-06-28 21:22:05 +00:00
}
}
private void ViewGiftData(MysteryGift g)
2014-06-28 21:22:05 +00:00
{
2014-12-11 06:50:40 +00:00
try
2014-06-28 21:22:05 +00:00
{
// only check if the form is visible (not opening)
if (Visible && g.GiftUsed && DialogResult.Yes ==
WinFormsUtil.Prompt(MessageBoxButtons.YesNo,
"Wonder Card is marked as USED and will not be able to be picked up in-game.",
2015-09-13 04:32:30 +00:00
"Do you want to remove the USED flag so that it is UNUSED?"))
g.GiftUsed = false;
RTB.Text = GetDescription(g, SAV);
PB_Preview.Image = g.Sprite(SAV);
mg = g;
2014-06-28 21:22:05 +00:00
}
catch (Exception e)
{
WinFormsUtil.Error("Loading of data failed... is this really a Wonder Card?", e);
RTB.Clear();
2014-06-28 21:22:05 +00:00
}
}
private void GetReceivedFlags()
2014-06-28 21:22:05 +00:00
{
LB_Received.Items.Clear();
for (int i = 1; i < mga.Flags.Length; i++)
if (mga.Flags[i])
2014-06-28 21:22:05 +00:00
LB_Received.Items.Add(i.ToString("0000"));
if (LB_Received.Items.Count > 0)
LB_Received.SelectedIndex = 0;
2014-06-28 21:22:05 +00:00
}
private void SetCardID(int cardID)
{
if (cardID <= 0 || cardID >= 0x100 * 8) return;
2014-06-28 21:22:05 +00:00
string card = cardID.ToString("0000");
if (!LB_Received.Items.Contains(card))
LB_Received.Items.Add(card);
LB_Received.SelectedIndex = LB_Received.Items.IndexOf(card);
}
// Mystery Gift IO (.file<->window)
2014-06-28 21:22:05 +00:00
private void B_Import_Click(object sender, EventArgs e)
{
OpenFileDialog import = new OpenFileDialog {Filter = WinFormsUtil.GetMysterGiftFilter(SAV.Generation)};
if (import.ShowDialog() != DialogResult.OK) return;
string path = import.FileName;
MysteryGift g = MysteryGift.GetMysteryGift(File.ReadAllBytes(path), Path.GetExtension(path));
if (g == null)
2014-06-28 21:22:05 +00:00
{
WinFormsUtil.Error("File is not a Mystery Gift:", path);
return;
2014-06-28 21:22:05 +00:00
}
ViewGiftData(g);
2014-06-28 21:22:05 +00:00
}
private void B_Output_Click(object sender, EventArgs e)
{
WinFormsUtil.SaveMGDialog(mg);
2014-06-28 21:22:05 +00:00
}
private static int GetLastUnfilledByType(MysteryGift Gift, MysteryGiftAlbum Album)
{
for (int i = 0; i < Album.Gifts.Length; i++)
{
if (!Album.Gifts[i].Empty)
continue;
if (Album.Gifts[i].Type != Gift.Type)
continue;
return i;
}
return -1;
}
// Mystery Gift RW (window<->sav)
private void ClickView(object sender, EventArgs e)
2014-06-28 21:22:05 +00:00
{
2016-02-01 07:15:54 +00:00
sender = ((sender as ToolStripItem)?.Owner as ContextMenuStrip)?.SourceControl ?? sender as PictureBox;
int index = Array.IndexOf(pba, sender);
SetBackground(index, Properties.Resources.slotView);
ViewGiftData(mga.Gifts[index]);
2014-06-28 21:22:05 +00:00
}
private void ClickSet(object sender, EventArgs e)
2014-06-28 21:22:05 +00:00
{
if (!IsSpecialWonderCard(mg))
return;
2016-02-01 07:15:54 +00:00
sender = ((sender as ToolStripItem)?.Owner as ContextMenuStrip)?.SourceControl ?? sender as PictureBox;
int index = Array.IndexOf(pba, sender);
// Hijack to the latest unfilled slot if index creates interstitial empty slots.
int lastUnfilled = GetLastUnfilledByType(mg, mga);
if (lastUnfilled > -1 && lastUnfilled < index)
index = lastUnfilled;
if (mg is PCD && mga.Gifts[index] is PGT)
mg = (mg as PCD).Gift;
else if (mg.Type != mga.Gifts[index].Type)
{
WinFormsUtil.Alert("Can't set slot here.", $"{mg.Type} != {mga.Gifts[index].Type}");
return;
}
SetBackground(index, Properties.Resources.slotSet);
mga.Gifts[index] = mg.Clone();
SetGiftBoxes();
SetCardID(mg.CardID);
2014-06-28 21:22:05 +00:00
}
private void ClickDelete(object sender, EventArgs e)
2014-06-28 21:22:05 +00:00
{
2016-02-01 07:15:54 +00:00
sender = ((sender as ToolStripItem)?.Owner as ContextMenuStrip)?.SourceControl ?? sender as PictureBox;
int index = Array.IndexOf(pba, sender);
mga.Gifts[index].Data = new byte[mga.Gifts[index].Data.Length];
// Shuffle blank card down
int i = index;
while (i < mga.Gifts.Length - 1)
{
if (mga.Gifts[i+1].Empty)
break;
if (mga.Gifts[i+1].Type != mga.Gifts[i].Type)
break;
i++;
var mg1 = mga.Gifts[i];
var mg2 = mga.Gifts[i-1];
mga.Gifts[i-1] = mg1;
mga.Gifts[i] = mg2;
}
SetBackground(i, Properties.Resources.slotDel);
SetGiftBoxes();
2014-06-28 21:22:05 +00:00
}
// Close Window
private void B_Cancel_Click(object sender, EventArgs e)
{
Close();
}
private void B_Save_Click(object sender, EventArgs e)
{
// Make sure all of the Received Flags are flipped!
bool[] flags = new bool[mga.Flags.Length];
foreach (var o in LB_Received.Items)
flags[Util.ToUInt32(o.ToString())] = true;
2014-06-28 21:22:05 +00:00
mga.Flags = flags;
SAV.GiftAlbum = mga;
Origin.SetData(SAV.Data, 0);
2014-06-28 21:22:05 +00:00
Close();
}
// Delete Received Flag
private void ClearRecievedFlag(object sender, EventArgs e)
2014-06-28 21:22:05 +00:00
{
2016-02-01 07:15:54 +00:00
if (LB_Received.SelectedIndex < 0) return;
if (LB_Received.Items.Count > 0)
LB_Received.Items.Remove(LB_Received.Items[LB_Received.SelectedIndex]);
if (LB_Received.Items.Count > 0)
LB_Received.SelectedIndex = 0;
2014-06-28 21:22:05 +00:00
}
2014-12-10 23:24:34 +00:00
// Drag & Drop Wonder Cards
private static void Main_DragEnter(object sender, DragEventArgs e)
2014-12-10 23:24:34 +00:00
{
if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy;
}
private void Main_DragDrop(object sender, DragEventArgs e)
2014-12-10 23:24:34 +00:00
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
2015-01-31 23:59:23 +00:00
// Check for multiple wondercards
if (Directory.Exists(files[0]))
files = Directory.GetFiles(files[0], "*", SearchOption.AllDirectories);
if (files.Length == 1 && !Directory.Exists(files[0]))
2014-12-10 23:24:34 +00:00
{
2015-01-31 23:59:23 +00:00
string path = files[0]; // open first D&D
long len = new FileInfo(path).Length;
if (len > 0x1000) // arbitrary
2015-01-31 23:59:23 +00:00
{
WinFormsUtil.Alert("File is not a Mystery Gift.", path);
2015-01-31 23:59:23 +00:00
return;
}
MysteryGift g = MysteryGift.GetMysteryGift(File.ReadAllBytes(path), Path.GetExtension(path));
if (g == null)
{
WinFormsUtil.Error("File is not a Mystery Gift:", path);
return;
}
ViewGiftData(g);
return;
}
SetGiftBoxes();
2014-12-10 23:24:34 +00:00
}
private bool IsSpecialWonderCard(MysteryGift g)
{
if (SAV.Generation != 6)
return true;
if (g is WC6)
{
if (g.CardID == 2048 && g.ItemID == 726) // Eon Ticket (OR/AS)
{
if (!SAV.ORAS || ((SAV6)SAV).EonTicket < 0)
goto reject;
BitConverter.GetBytes(WC6.EonTicketConst).CopyTo(SAV.Data, ((SAV6)SAV).EonTicket);
}
}
return true;
reject: WinFormsUtil.Alert("Unable to insert the Mystery Gift.", "Does this Mystery Gift really belong to this game?");
return false;
}
private void ClickQR(object sender, EventArgs e)
{
if (ModifierKeys == Keys.Alt)
ImportQRToView();
else
ExportQRFromView();
}
private void ExportQRFromView()
{
if (mg.Data.SequenceEqual(new byte[mg.Data.Length]))
{
WinFormsUtil.Alert("No wondercard data found in loaded slot!");
return;
}
if (SAV.Generation == 6 && mg.ItemID == 726 && mg.IsItem)
{
WinFormsUtil.Alert("Eon Ticket Wonder Cards will not function properly", "Inject to the save file instead.");
return;
}
const string server = "http://lunarcookies.github.io/wc.html#";
Image qr = QR.GetQRImage(mg.Data, server);
if (qr == null)
return;
string desc = $"({mg.Type}) {GetDescription(mg, SAV)}";
new QR(qr, PB_Preview.Image, null, desc + "PKHeX Wonder Card @ ProjectPokemon.org").ShowDialog();
}
private void ImportQRToView()
{
byte[] data = QR.GetQRData();
if (data == null)
return;
string[] types = mga.Gifts.Select(g => g.Type).Distinct().ToArray();
MysteryGift gift = MysteryGift.GetMysteryGift(data);
string giftType = gift.Type;
if (mga.Gifts.All(card => card.Data.Length != data.Length))
WinFormsUtil.Alert("Decoded data not valid for loaded save file.", $"QR Data Size: 0x{data.Length:X}");
else if (types.All(type => type != giftType))
WinFormsUtil.Alert("Gift type is not compatible with the save file.",
$"QR Gift Type: {gift.Type}" + Environment.NewLine + $"Expected Types: {string.Join(", ", types)}");
else if (gift.Species > SAV.MaxSpeciesID || gift.Moves.Any(move => move > SAV.MaxMoveID) ||
gift.HeldItem > SAV.MaxItemID)
WinFormsUtil.Alert("Gift Details are not compatible with the save file.");
else
ViewGiftData(gift);
}
private void BoxSlot_MouseDown(object sender, MouseEventArgs e)
{
switch (ModifierKeys)
{
case Keys.Control: ClickView(sender, e); return;
case Keys.Shift: ClickSet(sender, e); return;
case Keys.Alt: ClickDelete(sender, e); return;
}
PictureBox pb = sender as PictureBox;
if (pb?.Image == null)
return;
if (e.Button != MouseButtons.Left || e.Clicks != 1) return;
2016-02-01 07:15:54 +00:00
int index = Array.IndexOf(pba, sender);
2015-12-19 06:17:01 +00:00
wc_slot = index;
// Create Temp File to Drag
Cursor.Current = Cursors.Hand;
// Prepare Data
MysteryGift card = mga.Gifts[index];
string filename = Util.CleanFileName($"{card.CardID:0000} - {card.CardTitle}.{card.Extension}");
// Make File
string newfile = Path.Combine(Path.GetTempPath(), Util.CleanFileName(filename));
try
{
File.WriteAllBytes(newfile, card.Data);
DoDragDrop(new DataObject(DataFormats.FileDrop, new[] { newfile }), DragDropEffects.Move);
}
catch (Exception x)
{ WinFormsUtil.Error("Drag & Drop Error", x); }
File.Delete(newfile);
2015-12-19 06:17:01 +00:00
wc_slot = -1;
}
private void BoxSlot_DragDrop(object sender, DragEventArgs e)
{
2016-02-01 07:15:54 +00:00
int index = Array.IndexOf(pba, sender);
// Hijack to the latest unfilled slot if index creates interstitial empty slots.
int lastUnfilled = GetLastUnfilledByType(mg, mga);
if (lastUnfilled > -1 && lastUnfilled < index && mga.Gifts[lastUnfilled].Type == mga.Gifts[index].Type)
index = lastUnfilled;
if (wc_slot == -1) // dropped
2015-12-19 06:17:01 +00:00
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
if (files.Length < 1)
2015-12-19 06:17:01 +00:00
return;
if (PCD.Size < (int)new FileInfo(files[0]).Length)
{ WinFormsUtil.Alert("Data size invalid.", files[0]); return; }
byte[] data = File.ReadAllBytes(files[0]);
MysteryGift gift = MysteryGift.GetMysteryGift(data, new FileInfo(files[0]).Extension);
if (gift is PCD && mga.Gifts[index] is PGT)
gift = (gift as PCD).Gift;
else if (gift.Type != mga.Gifts[index].Type)
{
WinFormsUtil.Alert("Can't set slot here.", $"{gift.Type} != {mga.Gifts[index].Type}");
return;
}
SetBackground(index, Properties.Resources.slotSet);
mga.Gifts[index] = gift.Clone();
SetCardID(mga.Gifts[index].CardID);
ViewGiftData(mga.Gifts[index]);
2015-12-19 06:17:01 +00:00
}
else // Swap Data
{
MysteryGift s1 = mga.Gifts[index];
MysteryGift s2 = mga.Gifts[wc_slot];
if (s2 is PCD && s1 is PGT)
{
// set the PGT to the PGT slot instead
ViewGiftData(s2);
ClickSet(pba[index], null);
{ WinFormsUtil.Alert($"Set {s2.Type} gift to {s1.Type} slot."); return; }
}
if (s1.Type != s2.Type)
{ WinFormsUtil.Alert($"Can't swap {s2.Type} with {s1.Type}."); return; }
mga.Gifts[wc_slot] = s1;
mga.Gifts[index] = s2;
if (mga.Gifts[wc_slot].Empty) // empty slot created, slide down
{
int i = wc_slot;
while (i < index)
{
if (mga.Gifts[i + 1].Empty)
break;
if (mga.Gifts[i + 1].Type != mga.Gifts[i].Type)
break;
i++;
var mg1 = mga.Gifts[i];
var mg2 = mga.Gifts[i - 1];
mga.Gifts[i - 1] = mg1;
mga.Gifts[i] = mg2;
}
index = i-1;
}
2015-12-19 06:17:01 +00:00
}
SetBackground(index, Properties.Resources.slotView);
SetGiftBoxes();
}
private static void BoxSlot_DragEnter(object sender, DragEventArgs e)
{
if (e.AllowedEffect == (DragDropEffects.Copy | DragDropEffects.Link)) // external file
e.Effect = DragDropEffects.Copy;
else if (e.Data != null) // within
e.Effect = DragDropEffects.Move;
}
2015-12-19 06:17:01 +00:00
private int wc_slot = -1;
private static string GetDescription(MysteryGift gift, SaveFile SAV)
{
if (gift.Empty)
return "Empty Slot. No data!";
string s = gift.CardHeader + Environment.NewLine;
if (gift.IsItem)
{
s += $"Item: {GameInfo.Strings.itemlist[gift.ItemID]} (Quantity: {gift.Quantity})" + Environment.NewLine;
if (gift is WC7)
{
var ind = 1;
var wc7 = (WC7) gift;
while (wc7.GetItem(ind) != 0)
{
s += $"Item: {GameInfo.Strings.itemlist[wc7.GetItem(ind)]} (Quantity: {wc7.GetQuantity(ind)})" + Environment.NewLine;
ind++;
}
}
}
2017-01-05 22:45:53 +00:00
else if (gift.IsPokémon)
{
PKM pk = gift.ConvertToPKM(SAV);
try
{
s += $"{GameInfo.Strings.specieslist[pk.Species]} @ {GameInfo.Strings.itemlist[pk.HeldItem]} --- ";
s += (pk.IsEgg ? GameInfo.Strings.eggname : $"{pk.OT_Name} - {pk.TID:00000}/{pk.SID:00000}") + Environment.NewLine;
s += $"{GameInfo.Strings.movelist[pk.Move1]} / {GameInfo.Strings.movelist[pk.Move2]} / {GameInfo.Strings.movelist[pk.Move3]} / {GameInfo.Strings.movelist[pk.Move4]}" + Environment.NewLine;
if (gift is WC7)
{
var addItem = ((WC7) gift).AdditionalItem;
if (addItem != 0)
2017-01-27 17:09:28 +00:00
s += $"+ {GameInfo.Strings.itemlist[addItem]}" + Environment.NewLine;
}
}
2017-01-05 22:45:53 +00:00
catch { s += "Unable to create gift description." + Environment.NewLine; }
}
2017-01-27 17:09:28 +00:00
else if (gift.IsBP)
{
s += "BP: " + gift.BP + Environment.NewLine;
}
else if (gift.IsBean)
{
s += "Bean ID: " + gift.Bean + Environment.NewLine + "Quantity: " + gift.Quantity + Environment.NewLine;
}
2017-01-05 22:45:53 +00:00
else { s += "Unknown Wonder Card Type!" + Environment.NewLine; }
if (gift is WC7)
{
var wc7 = (WC7) gift;
s += $"Repeatable: {wc7.GiftRepeatable}" + Environment.NewLine;
s += $"Collected: {wc7.GiftUsed}" + Environment.NewLine;
s += $"Once Per Day: {wc7.GiftOncePerDay}" + Environment.NewLine;
}
return s;
}
// UI Generation
private List<PictureBox> PopulateViewGiftsG4()
{
List<PictureBox> pb = new List<PictureBox>();
// Row 1
var f1 = GetFlowLayoutPanel();
f1.Controls.Add(GetLabel("PGT 1-6"));
for (int i = 0; i < 6; i++)
{
var p = GetPictureBox();
f1.Controls.Add(p);
pb.Add(p);
}
// Row 2
var f2 = GetFlowLayoutPanel();
f2.Controls.Add(GetLabel("PGT 7-8"));
for (int i = 6; i < 8; i++)
{
var p = GetPictureBox();
f2.Controls.Add(p);
pb.Add(p);
}
// Row 3
var f3 = GetFlowLayoutPanel();
f3.Margin = new Padding(0, f3.Height, 0, 0);
f3.Controls.Add(GetLabel("PCD 1-3"));
for (int i = 8; i < 11; i++)
{
var p = GetPictureBox();
f3.Controls.Add(p);
pb.Add(p);
}
FLP_Gifts.Controls.Add(f1);
FLP_Gifts.Controls.Add(f2);
FLP_Gifts.Controls.Add(f3);
return pb;
}
private List<PictureBox> PopulateViewGiftsG567()
{
List<PictureBox> pb = new List<PictureBox>();
for (int i = 0; i < mga.Gifts.Length / 6; i++)
{
var flp = GetFlowLayoutPanel();
flp.Controls.Add(GetLabel($"{i * 6 + 1}-{i * 6 + 6}"));
for (int j = 0; j < 6; j++)
{
var p = GetPictureBox();
flp.Controls.Add(p);
pb.Add(p);
}
FLP_Gifts.Controls.Add(flp);
}
return pb;
}
private static FlowLayoutPanel GetFlowLayoutPanel()
{
return new FlowLayoutPanel
{
Width = 305,
Height = 34,
Padding = new Padding(0),
Margin = new Padding(0),
};
}
private static Label GetLabel(string text)
{
return new Label
{
Size = new Size(40, 34),
AutoSize = false,
TextAlign = ContentAlignment.MiddleRight,
Text = text,
Padding = new Padding(0),
Margin = new Padding(0),
};
}
private static PictureBox GetPictureBox()
{
return new PictureBox
{
Size = new Size(42, 32),
SizeMode = PictureBoxSizeMode.CenterImage,
BorderStyle = BorderStyle.FixedSingle,
BackColor = Color.Transparent,
Padding = new Padding(0),
Margin = new Padding(1),
};
}
}
}