Extract some AffixedRibbon logic

const now reused across entire sln
pkm editor GUI no longer crashes on hover of out of range affixed ribbon
pkm editor GUI now indicates the quantity of available affixed ribbons on hover (does not indicate if 1 and already affixed).
This commit is contained in:
Kurt 2024-08-19 21:11:08 -05:00
parent 27b552db13
commit 04466ac209
9 changed files with 31 additions and 19 deletions

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace PKHeX.Core;
@ -35,12 +36,17 @@ public static class RibbonStrings
/// Returns the Ribbon Display Name for the corresponding <see cref="PKM"/> ribbon property name.
/// </summary>
/// <param name="propertyName">Ribbon property name</param>
/// <param name="result">Ribbon localized name</param>
/// <returns>True if exists</returns>
public static bool GetNameSafe(string propertyName, [NotNullWhen(true)] out string? result) => RibbonNames.TryGetValue(propertyName, out result);
/// <returns>Ribbon display name</returns>
/// <inheritdoc cref="GetNameSafe"/>
public static string GetName(string propertyName)
{
// Throw an exception with the requested property name as the message, rather than an ambiguous "key not present" message.
// We should ALWAYS have the key present as the input arguments are not user-defined, rather, they are from PKM property names.
if (!RibbonNames.TryGetValue(propertyName, out var value))
if (!GetNameSafe(propertyName, out var value))
throw new KeyNotFoundException(propertyName);
return value;
}

View file

@ -33,7 +33,7 @@ public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBat
var mem = Data.AsMemory(HomeCrypto.SIZE_1HEADER + 2);
var core = mem[..CoreDataSize];
Core = new GameDataCore(core) { AffixedRibbon = -1 };
Core = new GameDataCore(core) { AffixedRibbon = PKHeX.Core.AffixedRibbon.None };
}
private void ReadGameData1(Memory<byte> data)

View file

@ -33,7 +33,7 @@ public sealed class PA8 : PKM, ISanityChecksum,
public IPermitRecord Permit => PersonalInfo;
public override EntityContext Context => EntityContext.Gen8a;
public PA8() : base(PokeCrypto.SIZE_8APARTY) => AffixedRibbon = -1; // 00 would make it show Kalos Champion :)
public PA8() : base(PokeCrypto.SIZE_8APARTY) => AffixedRibbon = Core.AffixedRibbon.None;
public PA8(byte[] data) : base(DecryptParty(data)) { }
public override int SIZE_PARTY => PokeCrypto.SIZE_8APARTY;

View file

@ -32,7 +32,7 @@ public sealed class PB8 : G8PKM
public PB8()
{
EggLocation = MetLocation = Locations.Default8bNone;
AffixedRibbon = -1; // 00 would make it show Kalos Champion :)
AffixedRibbon = Core.AffixedRibbon.None;
}
public PB8(byte[] data) : base(data) { }

View file

@ -30,7 +30,7 @@ public sealed class PK8 : G8PKM, IHandlerUpdate
public override IPermitRecord Permit => PersonalInfo;
public override EntityContext Context => EntityContext.Gen8;
public PK8() => AffixedRibbon = -1; // 00 would make it show Kalos Champion :)
public PK8() => AffixedRibbon = Core.AffixedRibbon.None;
public PK8(byte[] data) : base(data) { }
public override PK8 Clone() => new((byte[])Data.Clone());

View file

@ -30,9 +30,8 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, ITechRecord, IObedien
public PK9() : base(PokeCrypto.SIZE_9PARTY)
{
// 00 would make it show Kalos Champion :)
AffixedRibbon = -1;
TeraTypeOverride = (MoveType)19;
AffixedRibbon = PKHeX.Core.AffixedRibbon.None;
TeraTypeOverride = (MoveType)TeraTypeUtil.OverrideNone;
}
public PK9(byte[] data) : base(DecryptParty(data)) { }

View file

@ -1,4 +1,4 @@
namespace PKHeX.Core;
namespace PKHeX.Core;
/// <summary>
/// Specifies that a single ribbon index is prominently selected.
@ -10,3 +10,9 @@ public interface IRibbonSetAffixed
{
sbyte AffixedRibbon { get; set; }
}
public static class AffixedRibbon
{
public const sbyte None = -1;
public const sbyte Max = (sbyte)RibbonIndex.MAX_COUNT - 1;
}

View file

@ -1828,22 +1828,25 @@ public sealed partial class PKMEditor : UserControl, IMainEditor
if (pk is IRibbonSetAffixed a)
{
var affixed = a.AffixedRibbon;
if (affixed != -1)
if (affixed != AffixedRibbon.None)
{
PB_Affixed.Image = RibbonSpriteUtil.GetRibbonSprite((RibbonIndex)affixed);
PB_Affixed.Visible = true;
// Update the tooltip with the ribbon name.
var name = RibbonStrings.GetName($"Ribbon{(RibbonIndex)affixed}");
var name = RibbonStrings.GetNameSafe($"Ribbon{(RibbonIndex)affixed}", out var result) ? result : affixed.ToString();
if (pk is IRibbonSetMarks { RibbonMarkCount: > 1 } y)
name += Environment.NewLine + GetRibbonAffixCount(y);
AffixedTip.SetToolTip(PB_Affixed, name);
return;
}
if (pk is IRibbonSetMarks { RibbonMarkCount: not 0 })
if (pk is IRibbonSetMarks { RibbonMarkCount: not 0 } x)
{
PB_Affixed.Image = Properties.Resources.ribbon_affix_none;
PB_Affixed.Visible = true;
AffixedTip.SetToolTip(PB_Affixed, "Ribbons / Marks available to affix.");
AffixedTip.SetToolTip(PB_Affixed, GetRibbonAffixCount(x));
return;
}
static string GetRibbonAffixCount(IRibbonSetMarks x) => $"{x.RibbonMarkCount} available to affix.";
}
PB_Affixed.Visible = false;
}

View file

@ -19,8 +19,6 @@ public partial class RibbonEditor : Form
private const string PrefixCHK = "CHK_";
private const string PrefixPB = "PB_";
private const int AffixedNone = -1;
private bool EnableBackgroundChange;
private Control? LastToggledOn;
@ -52,12 +50,12 @@ public partial class RibbonEditor : Form
return;
}
const int count = (int)RibbonIndex.MAX_COUNT;
const int count = AffixedRibbon.Max;
static string GetRibbonPropertyName(int z) => RibbonStrings.GetName($"Ribbon{(RibbonIndex)z}");
static ComboItem GetComboItem(int ribbonIndex) => new(GetRibbonPropertyName(ribbonIndex), ribbonIndex);
var none = GameInfo.GetStrings(Main.CurrentLanguage).Move[0];
var ds = new List<ComboItem>(1 + count) { new(none, AffixedNone) };
var ds = new List<ComboItem>(1 + count) { new(none, AffixedRibbon.None) };
var list = Enumerable.Range(0, count).Select(GetComboItem).OrderBy(z => z.Text);
ds.AddRange(list);
@ -292,12 +290,12 @@ public partial class RibbonEditor : Form
{
RibbonApplicator.RemoveAllValidRibbons(Entity);
if (Entity is IRibbonSetAffixed affixed)
affixed.AffixedRibbon = AffixedNone;
affixed.AffixedRibbon = AffixedRibbon.None;
Close();
return;
}
CB_Affixed.SelectedValue = AffixedNone;
CB_Affixed.SelectedValue = (int)AffixedRibbon.None;
foreach (var c in TLP_Ribbons.Controls)
{
if (c is CheckBox chk)