mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-23 12:33:06 +00:00
Misc fixes/improvements
Reduce memory usage for evo method banlist (static banlist references) Fix gen6 mega evo flag truncation simplify QR encode/decode logic a little Don't apply transparency if transparency is already 100% (skip the loop) Add gen5 wild pid/tid-sid correlation check Fix validation value reset (loading gen3-4 pkm without looking at met tab causes the met location to get reset); fixed by prematurely validating before setting the value Fix gen3 pkm with gen4 contest ribbons in gen4/5 getting flagged incorrectly
This commit is contained in:
parent
f3382bbd60
commit
9864d84704
7 changed files with 100 additions and 65 deletions
|
@ -85,10 +85,14 @@ namespace PKHeX.Core
|
|||
case EncounterStatic s:
|
||||
if (s.Shiny != null && (bool)s.Shiny ^ pkm.IsShiny)
|
||||
AddLine(Severity.Invalid, V209, CheckIdentifier.Shiny);
|
||||
if (pkm.GenNumber == 5 && !s.Gift && !s.Roaming && s.Ability != 4)
|
||||
VerifyG5PID_IDCorrelation();
|
||||
break;
|
||||
case EncounterSlot w:
|
||||
if (pkm.IsShiny && w.Type == SlotType.HiddenGrotto)
|
||||
AddLine(Severity.Invalid, V221, CheckIdentifier.Shiny);
|
||||
if (pkm.GenNumber == 5 && pkm.AbilityNumber != 4)
|
||||
VerifyG5PID_IDCorrelation();
|
||||
break;
|
||||
case PCD d: // fixed PID
|
||||
if (d.Gift.PK.PID != 1 && pkm.EncryptionConstant != d.Gift.PK.PID)
|
||||
|
@ -96,6 +100,13 @@ namespace PKHeX.Core
|
|||
break;
|
||||
}
|
||||
}
|
||||
private void VerifyG5PID_IDCorrelation()
|
||||
{
|
||||
var pid = pkm.EncryptionConstant;
|
||||
var result = (pid & 1) ^ (pid >> 31) ^ (pkm.TID & 1) ^ (pkm.SID & 1);
|
||||
if (result != 0)
|
||||
AddLine(Severity.Invalid, V411, CheckIdentifier.PID);
|
||||
}
|
||||
private void VerifyECPIDWurmple()
|
||||
{
|
||||
uint evoVal = PKX.GetWurmpleEvoVal(pkm.EncryptionConstant);
|
||||
|
@ -783,7 +794,7 @@ namespace PKHeX.Core
|
|||
var c3 = u4.RibbonBitsContest3(); var c3n = u4.RibbonNamesContest3();
|
||||
var c4 = u4.RibbonBitsContest4(); var c4n = u4.RibbonNamesContest4();
|
||||
var iter3 = gen == 3 ? getMissingContestRibbons(c3, c3n) : GetRibbonMessageNone(c3, c3n);
|
||||
var iter4 = gen == 4 && IsAllowedInContest4(pkm.Species) ? getMissingContestRibbons(c4, c4n) : GetRibbonMessageNone(c4, c4n);
|
||||
var iter4 = (gen == 3 || gen == 4) && IsAllowedInContest4(pkm.Species) ? getMissingContestRibbons(c4, c4n) : GetRibbonMessageNone(c4, c4n);
|
||||
foreach (var z in iter3.Concat(iter4))
|
||||
yield return z;
|
||||
|
||||
|
|
|
@ -165,15 +165,15 @@ namespace PKHeX.Core
|
|||
var evo1 = raichu1.Chain[0].StageEntryMethods[0].Copy();
|
||||
Lineage[26].Chain.Add(new EvolutionStage { StageEntryMethods = new List<EvolutionMethod> { evo1 } });
|
||||
var evo2 = raichu1.Chain[1].StageEntryMethods[0].Copy();
|
||||
evo2.Form = -1; evo2.Banlist = new[] { GameVersion.SN, GameVersion.MN };
|
||||
evo2.Form = -1; evo2.Banlist = EvolutionMethod.BanSM;
|
||||
Lineage[26].Chain.Add(new EvolutionStage { StageEntryMethods = new List<EvolutionMethod> { evo2 } });
|
||||
|
||||
var exegg = Lineage[Personal.GetFormeIndex(103, 1)].Chain[0].StageEntryMethods[0].Copy();
|
||||
exegg.Form = -1; exegg.Banlist = new[] { GameVersion.SN, GameVersion.MN }; exegg.Method = 8; // No night required (doesn't matter)
|
||||
exegg.Form = -1; exegg.Banlist = EvolutionMethod.BanSM; exegg.Method = 8; // No night required (doesn't matter)
|
||||
Lineage[103].Chain.Add(new EvolutionStage { StageEntryMethods = new List<EvolutionMethod> { exegg } });
|
||||
|
||||
var marowak = Lineage[Personal.GetFormeIndex(105, 1)].Chain[0].StageEntryMethods[0].Copy();
|
||||
marowak.Form = -1; marowak.Banlist = new[] {GameVersion.SN, GameVersion.MN};
|
||||
marowak.Form = -1; marowak.Banlist = EvolutionMethod.BanSM;
|
||||
Lineage[105].Chain.Add(new EvolutionStage { StageEntryMethods = new List<EvolutionMethod> { marowak } });
|
||||
}
|
||||
|
||||
|
@ -512,8 +512,11 @@ namespace PKHeX.Core
|
|||
public int Level;
|
||||
|
||||
public bool RequiresLevelUp;
|
||||
public static readonly int[] TradeMethods = {5, 6, 7};
|
||||
public GameVersion[] Banlist = new GameVersion[0];
|
||||
|
||||
internal static readonly int[] TradeMethods = {5, 6, 7};
|
||||
private static readonly IReadOnlyCollection<GameVersion> NoBanlist = new GameVersion[0];
|
||||
internal static readonly IReadOnlyCollection<GameVersion> BanSM = new[] {GameVersion.SN, GameVersion.MN};
|
||||
internal IReadOnlyCollection<GameVersion> Banlist = NoBanlist;
|
||||
|
||||
public bool Valid(PKM pkm, int lvl, bool skipChecks)
|
||||
{
|
||||
|
|
|
@ -431,8 +431,8 @@ namespace PKHeX.Core
|
|||
}
|
||||
public bool IsMegaEvolutionUnlocked
|
||||
{
|
||||
get => Data[TrainerCard + 0x14A] == 1;
|
||||
set => Data[TrainerCard + 0x14A] = (byte)(value ? 1 : 0);
|
||||
get => (Data[TrainerCard + 0x14A] & 0x01) != 0;
|
||||
set => Data[TrainerCard + 0x14A] = (byte)((Data[TrainerCard + 0x14A] & 0xFE) | (value ? 1 : 0)); // in battle
|
||||
}
|
||||
|
||||
public int M
|
||||
|
|
|
@ -1305,8 +1305,8 @@ namespace PKHeX.Core
|
|||
}
|
||||
public bool MegaUnlocked
|
||||
{
|
||||
get => (Data[0x1278] & 0x01) != 0;
|
||||
set => Data[0x1278] = (byte)((Data[0x1278] & 0xFE) | (value ? 1 : 0)); // in battle
|
||||
get => (Data[TrainerCard + 0x78] & 0x01) != 0;
|
||||
set => Data[TrainerCard + 0x78] = (byte)((Data[TrainerCard + 0x78] & 0xFE) | (value ? 1 : 0)); // in battle
|
||||
// Data[0x1F22] = (byte)((Data[0x1F22] & 0xFE) | (value ? 1 : 0)); // event
|
||||
}
|
||||
|
||||
|
|
|
@ -423,19 +423,27 @@ namespace PKHeX.WinForms.Controls
|
|||
PB_MarkVC.Image = ImageUtil.ChangeOpacity(PB_MarkVC.InitialImage, getOpacity(pkm.VC));
|
||||
PB_MarkHorohoro.Image = ImageUtil.ChangeOpacity(PB_MarkHorohoro.InitialImage, getOpacity(pkm.Horohoro));
|
||||
|
||||
var markings = pkm.Markings;
|
||||
for (int i = 0; i < pba.Length; i++)
|
||||
if (GetMarkingColor(markings[i], out Color c))
|
||||
pba[i].Image = ImageUtil.ChangeAllColorTo(pba[i].Image, c);
|
||||
}
|
||||
private static bool GetMarkingColor(int markval, out Color c)
|
||||
{
|
||||
switch (markval)
|
||||
{
|
||||
switch (pkm.Markings[i])
|
||||
{
|
||||
case 1:
|
||||
pba[i].Image = ImageUtil.ChangeAllColorTo(pba[i].Image, Color.FromArgb(000, 191, 255));
|
||||
break;
|
||||
case 2:
|
||||
pba[i].Image = ImageUtil.ChangeAllColorTo(pba[i].Image, Color.FromArgb(255, 117, 179));
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
c = Color.FromArgb(000, 191, 255);
|
||||
return true;
|
||||
case 2:
|
||||
c = Color.FromArgb(255, 117, 179);
|
||||
return true;
|
||||
default:
|
||||
c = Color.Black;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGender()
|
||||
{
|
||||
int cg = PKX.GetGender(Label_Gender.Text);
|
||||
|
@ -1281,22 +1289,26 @@ namespace PKHeX.WinForms.Controls
|
|||
CB_MetLocation.ValueMember = "Value";
|
||||
CB_MetLocation.DataSource = new BindingSource(met_list, null);
|
||||
|
||||
int metLoc = 0; // transporter or pal park for past gen pkm
|
||||
switch (newTrack)
|
||||
if (fieldsLoaded)
|
||||
{
|
||||
case GameVersion.GO: metLoc = 30012; break;
|
||||
case GameVersion.RBY: metLoc = 30013; break;
|
||||
int metLoc = 0; // transporter or pal park for past gen pkm
|
||||
switch (newTrack)
|
||||
{
|
||||
case GameVersion.GO: metLoc = 30012; break;
|
||||
case GameVersion.RBY: metLoc = 30013; break;
|
||||
}
|
||||
if (metLoc != 0)
|
||||
CB_MetLocation.SelectedValue = metLoc;
|
||||
else
|
||||
CB_MetLocation.SelectedIndex = metLoc;
|
||||
}
|
||||
if (metLoc != 0)
|
||||
CB_MetLocation.SelectedValue = metLoc;
|
||||
else
|
||||
CB_MetLocation.SelectedIndex = metLoc;
|
||||
|
||||
var egg_list = GameInfo.GetLocationList(Version, pkm.Format, egg: true);
|
||||
CB_EggLocation.DisplayMember = "Text";
|
||||
CB_EggLocation.ValueMember = "Value";
|
||||
CB_EggLocation.DataSource = new BindingSource(egg_list, null);
|
||||
CB_EggLocation.SelectedIndex = CHK_AsEgg.Checked ? 1 : 0; // daycare : none
|
||||
if (fieldsLoaded)
|
||||
CB_EggLocation.SelectedIndex = CHK_AsEgg.Checked ? 1 : 0; // daycare : none
|
||||
|
||||
origintrack = newTrack;
|
||||
|
||||
|
@ -1305,6 +1317,9 @@ namespace PKHeX.WinForms.Controls
|
|||
if (Version == GameVersion.CXD && pkm.Format == 3)
|
||||
width = 2 * width;
|
||||
CB_MetLocation.DropDownWidth = width;
|
||||
|
||||
if (!fieldsLoaded)
|
||||
ValidateChildren(); // prevent value resetting when finishing load routine
|
||||
}
|
||||
|
||||
// Visibility logic for Gen 4 encounter type; only show for Gen 4 Pokemon.
|
||||
|
@ -1726,7 +1741,7 @@ namespace PKHeX.WinForms.Controls
|
|||
{
|
||||
if (e.Index < 0) return;
|
||||
|
||||
var i = (ComboItem)(sender as ComboBox).Items[e.Index];
|
||||
var i = (ComboItem)((ComboBox)sender).Items[e.Index];
|
||||
var moves = Legality.AllSuggestedMovesAndRelearn;
|
||||
bool vm = moves != null && moves.Contains(i.Value) && !HaX;
|
||||
|
||||
|
|
|
@ -79,52 +79,61 @@ namespace PKHeX.WinForms
|
|||
// QR Utility
|
||||
private const string QR6PathBad = "null/#"; // prefix to prevent URL from loading
|
||||
private const string QR6Path = @"http://lunarcookies.github.io/b1s1.html#";
|
||||
private const string DecodeAPI = "http://api.qrserver.com/v1/read-qr-code/?fileurl=";
|
||||
private const int QRSize = 365;
|
||||
private static readonly string EncodeAPI = $"http://chart.apis.google.com/chart?chs={QRSize}x{QRSize}&cht=qr&chl=";
|
||||
|
||||
internal static byte[] GetQRData(string address)
|
||||
{
|
||||
// Fetch data from QR code...
|
||||
try { if (address.Length < 4 || address.Substring(0, 3) != "htt") { WinFormsUtil.Alert("Clipboard text is not a valid URL:", address); return null; } }
|
||||
try { if (address.Length < 4 || !address.StartsWith("http")) { WinFormsUtil.Alert("Clipboard text is not a valid URL:", address); return null; } }
|
||||
catch { WinFormsUtil.Alert("Clipboard text is not a valid URL:", address); return null; }
|
||||
string webURL = "http://api.qrserver.com/v1/read-qr-code/?fileurl=" + HttpUtility.UrlEncode(address);
|
||||
string webURL = DecodeAPI + HttpUtility.UrlEncode(address);
|
||||
string data;
|
||||
try
|
||||
{
|
||||
string data = NetUtil.GetStringFromURL(webURL);
|
||||
data = NetUtil.GetStringFromURL(webURL);
|
||||
if (data.Contains("could not find")) { WinFormsUtil.Alert("Reader could not find QR data in the image."); return null; }
|
||||
if (data.Contains("filetype not supported")) { WinFormsUtil.Alert("Input URL is not valid. Double check that it is an image (jpg/png).", address); return null; }
|
||||
// Quickly convert the json response to a data string
|
||||
const string cap = "\",\"error\":null}]}]";
|
||||
const string intro = "[{\"type\":\"qrcode\",\"symbol\":[{\"seq\":0,\"data\":\"";
|
||||
if (!data.StartsWith(intro))
|
||||
throw new FormatException();
|
||||
|
||||
string pkstr = data.Substring(intro.Length);
|
||||
if (pkstr.Contains("nQR-Code:")) // Remove multiple QR codes in same image
|
||||
pkstr = pkstr.Substring(0, pkstr.IndexOf("nQR-Code:", StringComparison.Ordinal));
|
||||
pkstr = pkstr.Substring(0, pkstr.IndexOf(cap, StringComparison.Ordinal)); // Trim outro
|
||||
try
|
||||
{
|
||||
if (!pkstr.StartsWith("http") && !pkstr.StartsWith(QR6PathBad)) // G7
|
||||
{
|
||||
string fstr = Regex.Unescape(pkstr);
|
||||
byte[] raw = Encoding.Unicode.GetBytes(fstr);
|
||||
// Remove 00 interstitials and retrieve from offset 0x30, take PK7 Stored Size (always)
|
||||
return raw.ToList().Where((c, i) => i % 2 == 0).Skip(0x30).Take(0xE8).ToArray();
|
||||
}
|
||||
// All except G7
|
||||
pkstr = pkstr.Substring(pkstr.IndexOf("#", StringComparison.Ordinal) + 1); // Trim URL
|
||||
pkstr = pkstr.Replace("\\", ""); // Rectify response
|
||||
|
||||
return Convert.FromBase64String(pkstr);
|
||||
}
|
||||
catch { WinFormsUtil.Alert("QR string to Data failed."); return null; }
|
||||
}
|
||||
catch { WinFormsUtil.Alert("Unable to connect to the internet to decode QR code."); return null; }
|
||||
|
||||
// Quickly convert the json response to a data string
|
||||
try { return DecodeQRJson(data); }
|
||||
catch (Exception e) { WinFormsUtil.Alert("QR string to Data failed.", e.Message); return null; }
|
||||
}
|
||||
private static byte[] DecodeQRJson(string data)
|
||||
{
|
||||
const string cap = "\",\"error\":null}]}]";
|
||||
const string intro = "[{\"type\":\"qrcode\",\"symbol\":[{\"seq\":0,\"data\":\"";
|
||||
const string qrcode = "nQR-Code:";
|
||||
if (!data.StartsWith(intro))
|
||||
throw new FormatException();
|
||||
|
||||
string pkstr = data.Substring(intro.Length);
|
||||
if (pkstr.Contains(qrcode)) // Remove multiple QR codes in same image
|
||||
pkstr = pkstr.Substring(0, pkstr.IndexOf(qrcode, StringComparison.Ordinal));
|
||||
pkstr = pkstr.Substring(0, pkstr.IndexOf(cap, StringComparison.Ordinal)); // Trim outro
|
||||
|
||||
if (!pkstr.StartsWith("http") && !pkstr.StartsWith(QR6PathBad)) // G7
|
||||
{
|
||||
string fstr = Regex.Unescape(pkstr);
|
||||
byte[] raw = Encoding.Unicode.GetBytes(fstr);
|
||||
// Remove 00 interstitials and retrieve from offset 0x30, take PK7 Stored Size (always)
|
||||
return raw.ToList().Where((c, i) => i % 2 == 0).Skip(0x30).Take(0xE8).ToArray();
|
||||
}
|
||||
// All except G7
|
||||
pkstr = pkstr.Substring(pkstr.IndexOf("#", StringComparison.Ordinal) + 1); // Trim URL
|
||||
pkstr = pkstr.Replace("\\", ""); // Rectify response
|
||||
|
||||
return Convert.FromBase64String(pkstr);
|
||||
}
|
||||
|
||||
internal static Image GetQRImage(byte[] data, string server)
|
||||
{
|
||||
string qrdata = Convert.ToBase64String(data);
|
||||
string message = server + qrdata;
|
||||
string webURL = "http://chart.apis.google.com/chart?chs=365x365&cht=qr&chl=" + HttpUtility.UrlEncode(message);
|
||||
string webURL = EncodeAPI + HttpUtility.UrlEncode(message);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -159,12 +168,9 @@ namespace PKHeX.WinForms
|
|||
public static Image GenerateQRCode7(PK7 pk7, int box = 0, int slot = 0, int num_copies = 1)
|
||||
{
|
||||
byte[] data = QR7.GenerateQRData(pk7, box, slot, num_copies);
|
||||
using (var generator = new QRCodeGenerator())
|
||||
using (var qr_data = generator.CreateQRCode(data))
|
||||
using (var qr_code = new QRCode(qr_data))
|
||||
return qr_code.GetGraphic(4);
|
||||
return GenerateQRCode(data, ppm: 4);
|
||||
}
|
||||
public static Image GenerateQRCode(byte[] data, int ppm = 4)
|
||||
private static Image GenerateQRCode(byte[] data, int ppm = 4)
|
||||
{
|
||||
using (var generator = new QRCodeGenerator())
|
||||
using (var qr_data = generator.CreateQRCode(data))
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace PKHeX.WinForms
|
|||
using (Graphics gr = Graphics.FromImage(img))
|
||||
{
|
||||
gr.DrawImage(baseLayer, new Point(0, 0));
|
||||
Bitmap o = ChangeOpacity(overLayer, trans);
|
||||
Image o = trans == 1f ? overLayer : ChangeOpacity(overLayer, trans);
|
||||
gr.DrawImage(o, new Rectangle(x, y, overLayer.Width, overLayer.Height));
|
||||
}
|
||||
return img;
|
||||
|
|
Loading…
Reference in a new issue