mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-10 14:44:24 +00:00
Reimplement applied Markings individual get/set
Closes #4156 Extracts to an interface, varied implementations in the appropriate PKM classes. No longer an abstract property inherited from the base `PKM` class.
This commit is contained in:
parent
c66fc2f3bf
commit
0ca20ff096
26 changed files with 322 additions and 154 deletions
|
@ -1,9 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Logic for modifying the <see cref="PKM.MarkValue"/>.
|
/// Logic for modifying the <see cref="IAppliedMarkings"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class MarkingApplicator
|
public static class MarkingApplicator
|
||||||
{
|
{
|
||||||
|
@ -14,21 +14,40 @@ public static class MarkingApplicator
|
||||||
public static Func<PKM, Func<int, int, int>> MarkingMethod { get; set; } = FlagHighLow;
|
public static Func<PKM, Func<int, int, int>> MarkingMethod { get; set; } = FlagHighLow;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the <see cref="PKM.MarkValue"/> to indicate flawless (or near-flawless) <see cref="PKM.IVs"/>.
|
/// Sets the applied Markings to indicate flawless (or near-flawless) <see cref="PKM.IVs"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pk">Pokémon to modify.</param>
|
/// <param name="pk">Pokémon to modify.</param>
|
||||||
public static void SetMarkings(this PKM pk)
|
public static void SetMarkings(this PKM pk)
|
||||||
{
|
{
|
||||||
if (pk.MarkingCount < 6)
|
if (pk is not IAppliedMarkings { MarkingCount: 6 })
|
||||||
return; // insufficient marking indexes
|
return; // insufficient marking indexes
|
||||||
|
|
||||||
|
if (pk is IAppliedMarkings<MarkingColor> c)
|
||||||
|
SetMarkings(c, pk);
|
||||||
|
else if (pk is IAppliedMarkings<bool> b)
|
||||||
|
SetMarkings(b, pk);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetMarkings(this IAppliedMarkings<bool> mark, PKM pk)
|
||||||
|
{
|
||||||
var method = MarkingMethod(pk);
|
var method = MarkingMethod(pk);
|
||||||
pk.SetMarking(0, method(pk.IV_HP , 0));
|
mark.SetMarking(0, method(pk.IV_HP , 0) == 1);
|
||||||
pk.SetMarking(1, method(pk.IV_ATK, 1));
|
mark.SetMarking(1, method(pk.IV_ATK, 1) == 1);
|
||||||
pk.SetMarking(2, method(pk.IV_DEF, 2));
|
mark.SetMarking(2, method(pk.IV_DEF, 2) == 1);
|
||||||
pk.SetMarking(3, method(pk.IV_SPA, 3));
|
mark.SetMarking(3, method(pk.IV_SPA, 3) == 1);
|
||||||
pk.SetMarking(4, method(pk.IV_SPD, 4));
|
mark.SetMarking(4, method(pk.IV_SPD, 4) == 1);
|
||||||
pk.SetMarking(5, method(pk.IV_SPE, 5));
|
mark.SetMarking(5, method(pk.IV_SPE, 5) == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetMarkings(this IAppliedMarkings<MarkingColor> mark, PKM pk)
|
||||||
|
{
|
||||||
|
var method = MarkingMethod(pk);
|
||||||
|
mark.SetMarking(0, (MarkingColor)method(pk.IV_HP, 0));
|
||||||
|
mark.SetMarking(1, (MarkingColor)method(pk.IV_ATK, 1));
|
||||||
|
mark.SetMarking(2, (MarkingColor)method(pk.IV_DEF, 2));
|
||||||
|
mark.SetMarking(3, (MarkingColor)method(pk.IV_SPA, 3));
|
||||||
|
mark.SetMarking(4, (MarkingColor)method(pk.IV_SPD, 4));
|
||||||
|
mark.SetMarking(5, (MarkingColor)method(pk.IV_SPE, 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -37,18 +56,19 @@ public static class MarkingApplicator
|
||||||
/// <param name="pk">Pokémon to modify.</param>
|
/// <param name="pk">Pokémon to modify.</param>
|
||||||
/// <param name="index">Marking index to toggle</param>
|
/// <param name="index">Marking index to toggle</param>
|
||||||
/// <returns>Current marking value</returns>
|
/// <returns>Current marking value</returns>
|
||||||
public static int ToggleMarking(this PKM pk, int index)
|
public static void ToggleMarking(this PKM pk, int index)
|
||||||
{
|
{
|
||||||
var marking = pk.GetMarking(index);
|
if (pk is IAppliedMarkings<MarkingColor> c)
|
||||||
var revised = NextMarking(pk.Format, marking);
|
c.SetMarking(index, c.GetMarking(index).Next());
|
||||||
pk.SetMarking(index, revised);
|
else if (pk is IAppliedMarkings<bool> b)
|
||||||
return revised;
|
b.SetMarking(index, !b.GetMarking(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int NextMarking(int format, int marking) => format switch
|
private static MarkingColor Next(this MarkingColor value) => value switch
|
||||||
{
|
{
|
||||||
<= 6 => marking ^ 1, // toggle : 0 (off) | 1 (on)
|
MarkingColor.Blue => MarkingColor.Pink,
|
||||||
_ => (marking + 1) % 3, // cycle 0->1->2->0... : 0 (none) | 1 (blue) | 2 (pink)
|
MarkingColor.Pink => MarkingColor.None,
|
||||||
|
_ => MarkingColor.Blue,
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Func<int, int, int> FlagHighLow(PKM pk)
|
private static Func<int, int, int> FlagHighLow(PKM pk)
|
||||||
|
|
|
@ -66,7 +66,6 @@ public class EntitySummary : IFatefulEncounterReadOnly // do NOT seal, allow inh
|
||||||
public int Smart => pk is IContestStatsReadOnly s ? s.CNT_Smart : 0;
|
public int Smart => pk is IContestStatsReadOnly s ? s.CNT_Smart : 0;
|
||||||
public int Tough => pk is IContestStatsReadOnly s ? s.CNT_Tough : 0;
|
public int Tough => pk is IContestStatsReadOnly s ? s.CNT_Tough : 0;
|
||||||
public int Sheen => pk is IContestStatsReadOnly s ? s.CNT_Sheen : 0;
|
public int Sheen => pk is IContestStatsReadOnly s ? s.CNT_Sheen : 0;
|
||||||
public int Markings => pk.MarkValue;
|
|
||||||
|
|
||||||
public string NotOT => pk.Format > 5 ? pk.HT_Name : "N/A";
|
public string NotOT => pk.Format > 5 ? pk.HT_Name : "N/A";
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ using static PKHeX.Core.CheckIdentifier;
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Verifies the <see cref="PKM.MarkValue"/>.
|
/// Verifies the <see cref="IAppliedMarkings"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class MarkingVerifier : Verifier
|
public sealed class MarkingVerifier : Verifier
|
||||||
{
|
{
|
||||||
|
@ -26,26 +26,14 @@ public sealed class MarkingVerifier : Verifier
|
||||||
|
|
||||||
private void VerifyMarkValue(LegalityAnalysis data, PKM pk)
|
private void VerifyMarkValue(LegalityAnalysis data, PKM pk)
|
||||||
{
|
{
|
||||||
var mv = pk.MarkValue;
|
|
||||||
if (mv == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Eggs can have markings applied.
|
// Eggs can have markings applied.
|
||||||
//if (pk.IsEgg)
|
switch (pk)
|
||||||
//{
|
|
||||||
// data.AddLine(GetInvalid(LMarkValueShouldBeZero));
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
switch (pk.Format)
|
|
||||||
{
|
{
|
||||||
case <= 2:
|
case IAppliedMarkings3 m4:
|
||||||
|
VerifyMarkValueSingle(data, m4, m4.MarkingValue);
|
||||||
return;
|
return;
|
||||||
case <= 6:
|
case IAppliedMarkings7 m7:
|
||||||
VerifyMarkValueSingle(data, pk, mv);
|
VerifyMarkValueDual(data, m7, m7.MarkingValue);
|
||||||
return;
|
|
||||||
default:
|
|
||||||
VerifyMarkValueDual(data, pk, mv);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,8 +42,10 @@ public sealed class MarkingVerifier : Verifier
|
||||||
private const int Single6 = 0b_111111;
|
private const int Single6 = 0b_111111;
|
||||||
private const int Dual6 = 0b_1111_1111_1111;
|
private const int Dual6 = 0b_1111_1111_1111;
|
||||||
|
|
||||||
private void VerifyMarkValueDual(LegalityAnalysis data, PKM pk, int mv)
|
private void VerifyMarkValueDual(LegalityAnalysis data, IAppliedMarkings7 pk, ushort mv)
|
||||||
{
|
{
|
||||||
|
if (mv == 0)
|
||||||
|
return;
|
||||||
if (mv > Dual6)
|
if (mv > Dual6)
|
||||||
data.AddLine(GetInvalid(LMarkValueUnusedBitsPresent));
|
data.AddLine(GetInvalid(LMarkValueUnusedBitsPresent));
|
||||||
|
|
||||||
|
@ -63,20 +53,22 @@ public sealed class MarkingVerifier : Verifier
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var value = pk.GetMarking(i);
|
var value = pk.GetMarking(i);
|
||||||
if (value is not (0 or 1 or 2))
|
if (value is not (0 or MarkingColor.Blue or MarkingColor.Pink))
|
||||||
data.AddLine(GetInvalid(string.Format(LMarkValueOutOfRange_0, i)));
|
data.AddLine(GetInvalid(string.Format(LMarkValueOutOfRange_0, i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void VerifyMarkValueSingle(LegalityAnalysis data, PKM pk, int mv)
|
private void VerifyMarkValueSingle(LegalityAnalysis data, IAppliedMarkings3 pk, byte mv)
|
||||||
{
|
{
|
||||||
|
if (mv == 0)
|
||||||
|
return;
|
||||||
if (!IsMarkValueValid3456(pk, mv))
|
if (!IsMarkValueValid3456(pk, mv))
|
||||||
data.AddLine(GetInvalid(LMarkValueUnusedBitsPresent));
|
data.AddLine(GetInvalid(LMarkValueUnusedBitsPresent));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsMarkValueValid3456(PKM pk, int value)
|
private static bool IsMarkValueValid3456(IAppliedMarkings3 pk, int value)
|
||||||
{
|
{
|
||||||
var max = pk.Format is 3 ? Single4 : Single6;
|
var max = pk is IAppliedMarkings4 ? Single6 : Single4;
|
||||||
return value <= max;
|
return value <= max;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ public sealed class BK4 : G4PKM
|
||||||
|
|
||||||
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||||
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
||||||
public override int MarkValue { get => Data[0x16]; set => Data[0x16] = (byte)value; }
|
public override byte MarkingValue { get => Data[0x16]; set => Data[0x16] = value; }
|
||||||
public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
||||||
public override int EV_HP { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
public override int EV_HP { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
||||||
public override int EV_ATK { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
public override int EV_ATK { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
||||||
|
|
|
@ -174,7 +174,7 @@ public sealed class CK3(byte[] Data) : G3PKM(Data), IShadowCapture
|
||||||
public override bool AbilityBit { get => Data[0xCC] == 1; set => Data[0xCC] = value ? (byte)1 : (byte)0; }
|
public override bool AbilityBit { get => Data[0xCC] == 1; set => Data[0xCC] = value ? (byte)1 : (byte)0; }
|
||||||
public override bool Valid { get => Data[0xCD] == 0; set => Data[0xCD] = !value ? (byte)1 : (byte)0; }
|
public override bool Valid { get => Data[0xCD] == 0; set => Data[0xCD] = !value ? (byte)1 : (byte)0; }
|
||||||
|
|
||||||
public override int MarkValue { get => SwapBits(Data[0xCF], 1, 2); set => Data[0xCF] = (byte)SwapBits(value, 1, 2); }
|
public override byte MarkingValue { get => (byte)SwapBits(Data[0xCF], 1, 2); set => Data[0xCF] = (byte)SwapBits(value, 1, 2); }
|
||||||
public override int PKRS_Days { get => Math.Max((sbyte)Data[0xD0], (sbyte)0); set => Data[0xD0] = (byte)(value == 0 ? 0xFF : value & 0xF); }
|
public override int PKRS_Days { get => Math.Max((sbyte)Data[0xD0], (sbyte)0); set => Data[0xD0] = (byte)(value == 0 ? 0xFF : value & 0xF); }
|
||||||
|
|
||||||
public int PartySlot { get => Data[0xD7]; set => Data[0xD7] = (byte)value; } // or not; only really used while in party?
|
public int PartySlot { get => Data[0xD7]; set => Data[0xD7] = (byte)value; } // or not; only really used while in party?
|
||||||
|
|
|
@ -10,7 +10,8 @@ namespace PKHeX.Core;
|
||||||
public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature, IFatefulEncounter, IContestStats, IScaledSize, ITrainerMemories, IHandlerLanguage, IBattleVersion, IHyperTrain, IFormArgument, IFavorite,
|
public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature, IFatefulEncounter, IContestStats, IScaledSize, ITrainerMemories, IHandlerLanguage, IBattleVersion, IHyperTrain, IFormArgument, IFavorite,
|
||||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7,
|
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7,
|
||||||
IRibbonSetCommon8, IRibbonSetMark8,
|
IRibbonSetCommon8, IRibbonSetMark8,
|
||||||
IRibbonSetCommon9, IRibbonSetMark9
|
IRibbonSetCommon9, IRibbonSetMark9,
|
||||||
|
IAppliedMarkings7
|
||||||
{
|
{
|
||||||
// Internal Attributes set on creation
|
// Internal Attributes set on creation
|
||||||
private readonly Memory<byte> Buffer; // Raw Storage
|
private readonly Memory<byte> Buffer; // Raw Storage
|
||||||
|
@ -39,7 +40,7 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature
|
||||||
public ushort SID16 { get => ReadUInt16LittleEndian(Data[0x11..]); set => WriteUInt16LittleEndian(Data[0x11..], value); }
|
public ushort SID16 { get => ReadUInt16LittleEndian(Data[0x11..]); set => WriteUInt16LittleEndian(Data[0x11..], value); }
|
||||||
public uint EXP { get => ReadUInt32LittleEndian(Data[0x13..]); set => WriteUInt32LittleEndian(Data[0x13..], value); }
|
public uint EXP { get => ReadUInt32LittleEndian(Data[0x13..]); set => WriteUInt32LittleEndian(Data[0x13..], value); }
|
||||||
public bool IsFavorite { get => Data[0x17] != 0; set => Data[0x17] = (byte)(value ? 1 : 0); }
|
public bool IsFavorite { get => Data[0x17] != 0; set => Data[0x17] = (byte)(value ? 1 : 0); }
|
||||||
public int MarkValue { get => ReadUInt16LittleEndian(Data[0x18..]); set => WriteUInt16LittleEndian(Data[0x18..], (ushort)value); }
|
public ushort MarkingValue { get => ReadUInt16LittleEndian(Data[0x18..]); set => WriteUInt16LittleEndian(Data[0x18..], value); }
|
||||||
public uint PID { get => ReadUInt32LittleEndian(Data[0x1A..]); set => WriteUInt32LittleEndian(Data[0x1A..], value); }
|
public uint PID { get => ReadUInt32LittleEndian(Data[0x1A..]); set => WriteUInt32LittleEndian(Data[0x1A..], value); }
|
||||||
public int Nature { get => Data[0x1E]; set => Data[0x1E] = (byte)value; }
|
public int Nature { get => Data[0x1E]; set => Data[0x1E] = (byte)value; }
|
||||||
public int StatNature { get => Data[0x1F]; set => Data[0x1F] = (byte)value; }
|
public int StatNature { get => Data[0x1F]; set => Data[0x1F] = (byte)value; }
|
||||||
|
@ -296,25 +297,32 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature
|
||||||
|
|
||||||
public int HeldItem { get => ReadUInt16LittleEndian(Data[0xC2..]); set => WriteUInt16LittleEndian(Data[0xC2..], (ushort)value); }
|
public int HeldItem { get => ReadUInt16LittleEndian(Data[0xC2..]); set => WriteUInt16LittleEndian(Data[0xC2..], (ushort)value); }
|
||||||
|
|
||||||
public int MarkingCount => 6;
|
|
||||||
|
|
||||||
public TrainerIDFormat TrainerIDDisplayFormat => ((GameVersion)Version).GetGeneration() >= 7 ? TrainerIDFormat.SixDigit : TrainerIDFormat.SixteenBit;
|
public TrainerIDFormat TrainerIDDisplayFormat => ((GameVersion)Version).GetGeneration() >= 7 ? TrainerIDFormat.SixDigit : TrainerIDFormat.SixteenBit;
|
||||||
|
|
||||||
public int GetMarking(int index)
|
public int MarkingCount => 6;
|
||||||
|
|
||||||
|
public MarkingColor GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> (index * 2)) & 3;
|
return (MarkingColor)((MarkingValue >> (index * 2)) & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetMarking(int index, int value)
|
public void SetMarking(int index, MarkingColor value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var shift = index * 2;
|
var shift = index * 2;
|
||||||
MarkValue = (MarkValue & ~(0b11 << shift)) | ((value & 3) << shift);
|
MarkingValue = (ushort)((MarkingValue & ~(0b11 << shift)) | (((byte)value & 3) << shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MarkingColor MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public MarkingColor MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public MarkingColor MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public MarkingColor MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public MarkingColor MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public MarkingColor MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
public void CopyFrom(PKM pk)
|
public void CopyFrom(PKM pk)
|
||||||
{
|
{
|
||||||
EncryptionConstant = pk.EncryptionConstant;
|
EncryptionConstant = pk.EncryptionConstant;
|
||||||
|
@ -325,7 +333,7 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature
|
||||||
TID16 = pk.TID16;
|
TID16 = pk.TID16;
|
||||||
SID16 = pk.SID16;
|
SID16 = pk.SID16;
|
||||||
EXP = pk.EXP;
|
EXP = pk.EXP;
|
||||||
MarkValue = pk.MarkValue;
|
MarkingValue = pk is IAppliedMarkings7 m7 ? m7.MarkingValue : (ushort)0;
|
||||||
Nature = pk.Nature;
|
Nature = pk.Nature;
|
||||||
StatNature = pk.StatNature;
|
StatNature = pk.StatNature;
|
||||||
FatefulEncounter = pk.FatefulEncounter;
|
FatefulEncounter = pk.FatefulEncounter;
|
||||||
|
@ -382,7 +390,8 @@ public sealed class GameDataCore : IHomeTrack, ISpeciesForm, ITrainerID, INature
|
||||||
pk.TID16 = TID16;
|
pk.TID16 = TID16;
|
||||||
pk.SID16 = SID16;
|
pk.SID16 = SID16;
|
||||||
pk.EXP = EXP;
|
pk.EXP = EXP;
|
||||||
pk.MarkValue = MarkValue;
|
if (pk is IAppliedMarkings7 m7)
|
||||||
|
m7.MarkingValue = MarkingValue;
|
||||||
pk.Nature = Nature;
|
pk.Nature = Nature;
|
||||||
pk.StatNature = StatNature;
|
pk.StatNature = StatNature;
|
||||||
pk.FatefulEncounter = FatefulEncounter;
|
pk.FatefulEncounter = FatefulEncounter;
|
||||||
|
|
|
@ -112,7 +112,7 @@ public sealed class GameDataPK8 : HomeOptional1, IGameDataSide<PK8>, IGigantamax
|
||||||
AbilityNumber = (byte)pk.AbilityNumber;
|
AbilityNumber = (byte)pk.AbilityNumber;
|
||||||
Ability = (ushort)pk.Ability;
|
Ability = (ushort)pk.Ability;
|
||||||
|
|
||||||
pkh.MarkValue &= 0b1111_1111_1111;
|
pkh.MarkingValue &= 0b1111_1111_1111;
|
||||||
if (!pk.IsNicknamed)
|
if (!pk.IsNicknamed)
|
||||||
pkh.Nickname = SpeciesName.GetSpeciesNameGeneration(pk.Species, pk.Language, 8);
|
pkh.Nickname = SpeciesName.GetSpeciesNameGeneration(pk.Species, pk.Language, 8);
|
||||||
if (FormInfo.IsTotemForm(pk.Species, pk.Form))
|
if (FormInfo.IsTotemForm(pk.Species, pk.Form))
|
||||||
|
|
|
@ -5,7 +5,8 @@ using static PKHeX.Core.GameVersion;
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary> Pokémon HOME <see cref="PKM"/> format. </summary>
|
/// <summary> Pokémon HOME <see cref="PKM"/> format. </summary>
|
||||||
public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IRibbonSetAffixed, IContestStats, IScaledSize, IRibbonSetRibbons, IRibbonSetMarks
|
public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IRibbonSetAffixed, IContestStats, IScaledSize,
|
||||||
|
IRibbonSetRibbons, IRibbonSetMarks, IAppliedMarkings7
|
||||||
{
|
{
|
||||||
public readonly GameDataCore Core;
|
public readonly GameDataCore Core;
|
||||||
public GameDataPB7? DataPB7 { get; private set; }
|
public GameDataPB7? DataPB7 { get; private set; }
|
||||||
|
@ -93,7 +94,7 @@ public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBat
|
||||||
public override ushort SID16 { get => Core.SID16; set => Core.SID16 = value; }
|
public override ushort SID16 { get => Core.SID16; set => Core.SID16 = value; }
|
||||||
public override uint EXP { get => Core.EXP; set => Core.EXP = value; }
|
public override uint EXP { get => Core.EXP; set => Core.EXP = value; }
|
||||||
public bool Favorite { get => Core.IsFavorite; set => Core.IsFavorite = value; }
|
public bool Favorite { get => Core.IsFavorite; set => Core.IsFavorite = value; }
|
||||||
public override int MarkValue { get => Core.MarkValue; set => Core.MarkValue = value; }
|
public ushort MarkingValue { get => Core.MarkingValue; set => Core.MarkingValue = value; }
|
||||||
public override uint PID { get => Core.PID; set => Core.PID = value; }
|
public override uint PID { get => Core.PID; set => Core.PID = value; }
|
||||||
public override int Nature { get => Core.Nature; set => Core.Nature = value; }
|
public override int Nature { get => Core.Nature; set => Core.Nature = value; }
|
||||||
public override int StatNature { get => Core.StatNature; set => Core.StatNature = value; }
|
public override int StatNature { get => Core.StatNature; set => Core.StatNature = value; }
|
||||||
|
@ -167,12 +168,19 @@ public sealed class PKH : PKM, IHandlerLanguage, IFormArgument, IHomeTrack, IBat
|
||||||
public override string OT_Name { get => Core.OT_Name; set => Core.OT_Name = value; }
|
public override string OT_Name { get => Core.OT_Name; set => Core.OT_Name = value; }
|
||||||
public override string HT_Name { get => Core.HT_Name; set => Core.HT_Name = value; }
|
public override string HT_Name { get => Core.HT_Name; set => Core.HT_Name = value; }
|
||||||
|
|
||||||
public override int MarkingCount => Core.MarkingCount;
|
public int MarkingCount => Core.MarkingCount;
|
||||||
public int RibbonCount => Core.RibbonCount;
|
public int RibbonCount => Core.RibbonCount;
|
||||||
public int MarkCount => Core.MarkCount;
|
public int MarkCount => Core.MarkCount;
|
||||||
public int RibbonMarkCount => Core.RibbonMarkCount;
|
public int RibbonMarkCount => Core.RibbonMarkCount;
|
||||||
public override int GetMarking(int index) => Core.GetMarking(index);
|
public MarkingColor GetMarking(int index) => Core.GetMarking(index);
|
||||||
public override void SetMarking(int index, int value) => Core.SetMarking(index, value);
|
public void SetMarking(int index, MarkingColor value) => Core.SetMarking(index, value);
|
||||||
|
|
||||||
|
public MarkingColor MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public MarkingColor MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public MarkingColor MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public MarkingColor MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public MarkingColor MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public MarkingColor MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
90
PKHeX.Core/PKM/Interfaces/IAppliedMarkings.cs
Normal file
90
PKHeX.Core/PKM/Interfaces/IAppliedMarkings.cs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates if the object is capable of being marked by the player with simple shapes.
|
||||||
|
/// </summary>
|
||||||
|
public interface IAppliedMarkings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Count of unique markings that can be applied to the object.
|
||||||
|
/// </summary>
|
||||||
|
int MarkingCount { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IAppliedMarkings<T> : IAppliedMarkings where T : unmanaged
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the marking value at the given index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index">Index of the marking to get.</param>
|
||||||
|
/// <returns>Marking value at the given index.</returns>
|
||||||
|
T GetMarking(int index);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets the marking value at the given index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index">Index of the marking to set.</param>
|
||||||
|
/// <param name="value">Value to set the marking to.</param>
|
||||||
|
void SetMarking(int index, T value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generation 3 Markings
|
||||||
|
/// </summary>
|
||||||
|
public interface IAppliedMarkings3 : IAppliedMarkings<bool>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Backing value for the packed bits.
|
||||||
|
/// </summary>
|
||||||
|
byte MarkingValue { get; set; }
|
||||||
|
|
||||||
|
bool MarkingCircle { get; set; }
|
||||||
|
bool MarkingTriangle { get; set; } // In generation 3, this is marking index 2
|
||||||
|
bool MarkingSquare { get; set; } // In generation 3, this is marking index 1
|
||||||
|
bool MarkingHeart { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generation 4-6 Markings
|
||||||
|
/// </summary>
|
||||||
|
public interface IAppliedMarkings4 : IAppliedMarkings3
|
||||||
|
{
|
||||||
|
bool MarkingStar { get; set; }
|
||||||
|
bool MarkingDiamond { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generation 7+ Markings
|
||||||
|
/// </summary>
|
||||||
|
public interface IAppliedMarkings7 : IAppliedMarkings<MarkingColor>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Backing value for the packed bits.
|
||||||
|
/// </summary>
|
||||||
|
ushort MarkingValue { get; set; }
|
||||||
|
|
||||||
|
MarkingColor MarkingCircle { get; set; }
|
||||||
|
MarkingColor MarkingTriangle { get; set; }
|
||||||
|
MarkingColor MarkingSquare { get; set; }
|
||||||
|
MarkingColor MarkingHeart { get; set; }
|
||||||
|
MarkingColor MarkingStar { get; set; }
|
||||||
|
MarkingColor MarkingDiamond { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MarkingColor : byte
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Not marked.
|
||||||
|
/// </summary>
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Blue marking.
|
||||||
|
/// </summary>
|
||||||
|
Blue = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pink marking.
|
||||||
|
/// </summary>
|
||||||
|
Pink = 2,
|
||||||
|
}
|
|
@ -130,7 +130,7 @@ public sealed class PA8 : PKM, ISanityChecksum,
|
||||||
public bool IsAlpha { get => (Data[0x16] & 32) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~32) | ((value ? 1 : 0) << 5)); }
|
public bool IsAlpha { get => (Data[0x16] & 32) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~32) | ((value ? 1 : 0) << 5)); }
|
||||||
public bool IsNoble { get => (Data[0x16] & 64) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~64) | ((value ? 1 : 0) << 6)); }
|
public bool IsNoble { get => (Data[0x16] & 64) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~64) | ((value ? 1 : 0) << 6)); }
|
||||||
// 0x17 alignment unused
|
// 0x17 alignment unused
|
||||||
public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), (ushort)value); }
|
public ushort MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), value); }
|
||||||
// 0x1A alignment unused
|
// 0x1A alignment unused
|
||||||
// 0x1B alignment unused
|
// 0x1B alignment unused
|
||||||
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); }
|
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); }
|
||||||
|
@ -540,21 +540,21 @@ public sealed class PA8 : PKM, ISanityChecksum,
|
||||||
return NatureAmp.AmplifyStat(nature, statIndex, initial);
|
return NatureAmp.AmplifyStat(nature, statIndex, initial);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int MarkingCount => 6;
|
public int MarkingCount => 6;
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public MarkingColor GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> (index * 2)) & 3;
|
return (MarkingColor)((MarkValue >> (index * 2)) & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, MarkingColor value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var shift = index * 2;
|
var shift = index * 2;
|
||||||
MarkValue = (MarkValue & ~(0b11 << shift)) | ((value & 3) << shift);
|
MarkValue = (ushort)((MarkValue & ~(0b11 << shift)) | (((byte)value & 3) << shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool GetRibbon(int index) => FlagUtil.GetFlag(Data, GetRibbonByte(index), index & 7);
|
public bool GetRibbon(int index) => FlagUtil.GetFlag(Data, GetRibbonByte(index), index & 7);
|
||||||
|
|
|
@ -5,7 +5,7 @@ using static System.Buffers.Binary.BinaryPrimitives;
|
||||||
namespace PKHeX.Core;
|
namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary> Generation 7 <see cref="PKM"/> format used for <see cref="GameVersion.GG"/>. </summary>
|
/// <summary> Generation 7 <see cref="PKM"/> format used for <see cref="GameVersion.GG"/>. </summary>
|
||||||
public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, ICombatPower, IFavorite, IFormArgument
|
public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, ICombatPower, IFavorite, IFormArgument, IAppliedMarkings7
|
||||||
{
|
{
|
||||||
public override ReadOnlySpan<ushort> ExtraBytes =>
|
public override ReadOnlySpan<ushort> ExtraBytes =>
|
||||||
[
|
[
|
||||||
|
@ -98,7 +98,7 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb
|
||||||
public override int Ability { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
public override int Ability { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||||
public override int AbilityNumber { get => Data[0x15] & 7; set => Data[0x15] = (byte)((Data[0x15] & ~7) | (value & 7)); }
|
public override int AbilityNumber { get => Data[0x15] & 7; set => Data[0x15] = (byte)((Data[0x15] & ~7) | (value & 7)); }
|
||||||
public bool IsFavorite { get => (Data[0x15] & 8) != 0; set => Data[0x15] = (byte)((Data[0x15] & ~8) | ((value ? 1 : 0) << 3)); }
|
public bool IsFavorite { get => (Data[0x15] & 8) != 0; set => Data[0x15] = (byte)((Data[0x15] & ~8) | ((value ? 1 : 0) << 3)); }
|
||||||
public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16), (ushort)value); }
|
public ushort MarkingValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16), value); }
|
||||||
|
|
||||||
public override uint PID
|
public override uint PID
|
||||||
{
|
{
|
||||||
|
@ -309,23 +309,30 @@ public sealed class PB7 : G6PKM, IHyperTrain, IAwakened, IScaledSizeValue, IComb
|
||||||
// 102/103 unused
|
// 102/103 unused
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public override int MarkingCount => 6;
|
public int MarkingCount => 6;
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public MarkingColor GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> (index * 2)) & 3;
|
return (MarkingColor)((MarkingValue >> (index * 2)) & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, MarkingColor value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var shift = index * 2;
|
var shift = index * 2;
|
||||||
MarkValue = (MarkValue & ~(0b11 << shift)) | ((value & 3) << shift);
|
MarkingValue = (ushort)((MarkingValue & ~(0b11 << shift)) | (((byte)value & 3) << shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MarkingColor MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public MarkingColor MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public MarkingColor MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public MarkingColor MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public MarkingColor MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public MarkingColor MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
protected override bool TradeOT(ITrainerInfo tr)
|
protected override bool TradeOT(ITrainerInfo tr)
|
||||||
{
|
{
|
||||||
// Check to see if the OT matches the SAV's OT info.
|
// Check to see if the OT matches the SAV's OT info.
|
||||||
|
|
|
@ -60,7 +60,7 @@ public sealed class PK3 : G3PKM, ISanityChecksum
|
||||||
get => StringConverter3.GetString(OT_Trash, Japanese);
|
get => StringConverter3.GetString(OT_Trash, Japanese);
|
||||||
set => StringConverter3.SetString(OT_Trash, value, 7, Japanese, StringConverterOption.None);
|
set => StringConverter3.SetString(OT_Trash, value, 7, Japanese, StringConverterOption.None);
|
||||||
}
|
}
|
||||||
public override int MarkValue { get => SwapBits(Data[0x1B], 1, 2); set => Data[0x1B] = (byte)SwapBits(value, 1, 2); }
|
public override byte MarkingValue { get => (byte)SwapBits(Data[0x1B], 1, 2); set => Data[0x1B] = (byte)SwapBits(value, 1, 2); }
|
||||||
public ushort Checksum { get => ReadUInt16LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1C), value); }
|
public ushort Checksum { get => ReadUInt16LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1C), value); }
|
||||||
public ushort Sanity { get => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), value); }
|
public ushort Sanity { get => ReadUInt16LittleEndian(Data.AsSpan(0x1E)); set => WriteUInt16LittleEndian(Data.AsSpan(0x1E), value); }
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ public sealed class PK3 : G3PKM, ISanityChecksum
|
||||||
Form = Form,
|
Form = Form,
|
||||||
// IsEgg = false, -- already false
|
// IsEgg = false, -- already false
|
||||||
OT_Friendship = 70,
|
OT_Friendship = 70,
|
||||||
MarkValue = MarkValue & 0b1111,
|
MarkingValue = (byte)(MarkingValue & 0b1111),
|
||||||
Language = Language,
|
Language = Language,
|
||||||
EV_HP = EV_HP,
|
EV_HP = EV_HP,
|
||||||
EV_ATK = EV_ATK,
|
EV_ATK = EV_ATK,
|
||||||
|
|
|
@ -43,7 +43,7 @@ public sealed class PK4 : G4PKM
|
||||||
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
||||||
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||||
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
||||||
public override int MarkValue { get => Data[0x16]; set => Data[0x16] = (byte)value; }
|
public override byte MarkingValue { get => Data[0x16]; set => Data[0x16] = value; }
|
||||||
public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
||||||
public override int EV_HP { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
public override int EV_HP { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
||||||
public override int EV_ATK { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
public override int EV_ATK { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace PKHeX.Core;
|
||||||
/// <summary> Generation 5 <see cref="PKM"/> format. </summary>
|
/// <summary> Generation 5 <see cref="PKM"/> format. </summary>
|
||||||
public sealed class PK5 : PKM, ISanityChecksum,
|
public sealed class PK5 : PKM, ISanityChecksum,
|
||||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetRibbons,
|
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetRibbons,
|
||||||
IContestStats, IGroundTile
|
IContestStats, IGroundTile, IAppliedMarkings4
|
||||||
{
|
{
|
||||||
public override ReadOnlySpan<ushort> ExtraBytes =>
|
public override ReadOnlySpan<ushort> ExtraBytes =>
|
||||||
[
|
[
|
||||||
|
@ -64,7 +64,7 @@ public sealed class PK5 : PKM, ISanityChecksum,
|
||||||
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
||||||
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||||
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
||||||
public override int MarkValue { get => Data[0x16]; set => Data[0x16] = (byte)value; }
|
public byte MarkingValue { get => Data[0x16]; set => Data[0x16] = value; }
|
||||||
public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
||||||
public override int EV_HP { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
public override int EV_HP { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
||||||
public override int EV_ATK { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
public override int EV_ATK { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
||||||
|
@ -307,22 +307,29 @@ public sealed class PK5 : PKM, ISanityChecksum,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int MarkingCount => 6;
|
public int MarkingCount => 6;
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public bool GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> index) & 1;
|
return ((MarkingValue >> index) & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, bool value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
MarkValue = (MarkValue & ~(1 << index)) | ((value & 1) << index);
|
MarkingValue = (byte)((MarkingValue & ~(1 << index)) | ((value ? 1 : 0) << index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public bool MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public bool MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public bool MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public bool MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public bool MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
public override void RefreshAbility(int n)
|
public override void RefreshAbility(int n)
|
||||||
{
|
{
|
||||||
base.RefreshAbility(n);
|
base.RefreshAbility(n);
|
||||||
|
@ -341,7 +348,7 @@ public sealed class PK5 : PKM, ISanityChecksum,
|
||||||
PID = PID,
|
PID = PID,
|
||||||
Ability = Ability,
|
Ability = Ability,
|
||||||
AbilityNumber = 1 << CalculateAbilityIndex(),
|
AbilityNumber = 1 << CalculateAbilityIndex(),
|
||||||
MarkValue = MarkValue & 0b_11_1111,
|
MarkingValue = MarkingValue,
|
||||||
Language = Math.Max((int)LanguageID.Japanese, Language), // Hacked or Bad IngameTrade (Japanese B/W)
|
Language = Math.Max((int)LanguageID.Japanese, Language), // Hacked or Bad IngameTrade (Japanese B/W)
|
||||||
|
|
||||||
CNT_Cool = CNT_Cool,
|
CNT_Cool = CNT_Cool,
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary> Generation 6 <see cref="PKM"/> format. </summary>
|
/// <summary> Generation 6 <see cref="PKM"/> format. </summary>
|
||||||
public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetRibbons,
|
public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetRibbons,
|
||||||
IContestStats, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection, IGroundTile
|
IContestStats, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection, IGroundTile, IAppliedMarkings4
|
||||||
{
|
{
|
||||||
public override ReadOnlySpan<ushort> ExtraBytes =>
|
public override ReadOnlySpan<ushort> ExtraBytes =>
|
||||||
[
|
[
|
||||||
|
@ -112,7 +112,7 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC
|
||||||
public byte CNT_Smart { get => Data[0x27]; set => Data[0x27] = value; }
|
public byte CNT_Smart { get => Data[0x27]; set => Data[0x27] = value; }
|
||||||
public byte CNT_Tough { get => Data[0x28]; set => Data[0x28] = value; }
|
public byte CNT_Tough { get => Data[0x28]; set => Data[0x28] = value; }
|
||||||
public byte CNT_Sheen { get => Data[0x29]; set => Data[0x29] = value; }
|
public byte CNT_Sheen { get => Data[0x29]; set => Data[0x29] = value; }
|
||||||
public override int MarkValue { get => Data[0x2A]; set => Data[0x2A] = (byte)value; }
|
public byte MarkingValue { get => Data[0x2A]; set => Data[0x2A] = value; }
|
||||||
private byte PKRS { get => Data[0x2B]; set => Data[0x2B] = value; }
|
private byte PKRS { get => Data[0x2B]; set => Data[0x2B] = value; }
|
||||||
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
public override int PKRS_Days { get => PKRS & 0xF; set => PKRS = (byte)((PKRS & ~0xF) | value); }
|
||||||
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); }
|
public override int PKRS_Strain { get => PKRS >> 4; set => PKRS = (byte)((PKRS & 0xF) | (value << 4)); }
|
||||||
|
@ -455,28 +455,35 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC
|
||||||
public override int MaxItemID => Legal.MaxItemID_6_AO;
|
public override int MaxItemID => Legal.MaxItemID_6_AO;
|
||||||
public override int MaxBallID => Legal.MaxBallID_6;
|
public override int MaxBallID => Legal.MaxBallID_6;
|
||||||
public override int MaxGameID => Legal.MaxGameID_6; // OR
|
public override int MaxGameID => Legal.MaxGameID_6; // OR
|
||||||
public override int MarkingCount => 6;
|
public int MarkingCount => 6;
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public bool GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> index) & 1;
|
return ((MarkingValue >> index) & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, bool value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
MarkValue = (MarkValue & ~(1 << index)) | ((value & 1) << index);
|
MarkingValue = (byte)((MarkingValue & ~(1 << index)) | ((value ? 1 : 0) << index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public bool MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public bool MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public bool MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public bool MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public bool MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
public PK7 ConvertToPK7()
|
public PK7 ConvertToPK7()
|
||||||
{
|
{
|
||||||
PK7 pk7 = new((byte[])Data.Clone())
|
PK7 pk7 = new((byte[])Data.Clone())
|
||||||
{
|
{
|
||||||
ResortEventStatus = 0, // Clears old Marking Value
|
ResortEventStatus = 0, // Clears old Marking Value
|
||||||
MarkValue = 0, // Clears old Super Training Bag & Hits Remaining
|
MarkingValue = 0, // Clears old Super Training Bag & Hits Remaining
|
||||||
FormArgument = 0, // Clears old style Form Argument
|
FormArgument = 0, // Clears old style Form Argument
|
||||||
DirtType = 0, // Clears old Form Argument byte
|
DirtType = 0, // Clears old Form Argument byte
|
||||||
DirtLocation = 0, // Clears old Form Argument byte
|
DirtLocation = 0, // Clears old Form Argument byte
|
||||||
|
@ -484,7 +491,7 @@ public sealed class PK6 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC
|
||||||
|
|
||||||
// Remap boolean markings to the dual-bit format -- set 1 if marked.
|
// Remap boolean markings to the dual-bit format -- set 1 if marked.
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
pk7.SetMarking(i, GetMarking(i));
|
pk7.SetMarking(i, GetMarking(i) ? MarkingColor.Blue : MarkingColor.None);
|
||||||
|
|
||||||
var an = AbilityNumber;
|
var an = AbilityNumber;
|
||||||
if (an is 1 or 2 or 4) // Valid Ability Numbers
|
if (an is 1 or 2 or 4) // Valid Ability Numbers
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary> Generation 7 <see cref="PKM"/> format. </summary>
|
/// <summary> Generation 7 <see cref="PKM"/> format. </summary>
|
||||||
public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetRibbons,
|
public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetRibbons,
|
||||||
IContestStats, IHyperTrain, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection, IPokerusStatus
|
IContestStats, IHyperTrain, IGeoTrack, ISuperTrain, IFormArgument, ITrainerMemories, IAffection, IPokerusStatus, IAppliedMarkings7
|
||||||
{
|
{
|
||||||
public override ReadOnlySpan<ushort> ExtraBytes =>
|
public override ReadOnlySpan<ushort> ExtraBytes =>
|
||||||
[
|
[
|
||||||
|
@ -88,7 +88,7 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC
|
||||||
|
|
||||||
public override int Ability { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
public override int Ability { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||||
public override int AbilityNumber { get => Data[0x15] & 7; set => Data[0x15] = (byte)((Data[0x15] & ~7) | (value & 7)); }
|
public override int AbilityNumber { get => Data[0x15] & 7; set => Data[0x15] = (byte)((Data[0x15] & ~7) | (value & 7)); }
|
||||||
public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16), (ushort)value); }
|
public ushort MarkingValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x16)); set => WriteUInt16LittleEndian(Data.AsSpan(0x16), value); }
|
||||||
|
|
||||||
public override uint PID
|
public override uint PID
|
||||||
{
|
{
|
||||||
|
@ -423,23 +423,30 @@ public sealed class PK7 : G6PKM, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetC
|
||||||
|
|
||||||
public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6;
|
public bool IsUntradedEvent6 => Geo1_Country == 0 && Geo1_Region == 0 && Met_Location / 10000 == 4 && Gen6;
|
||||||
|
|
||||||
public override int MarkingCount => 6;
|
public int MarkingCount => 6;
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public MarkingColor GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> (index * 2)) & 3;
|
return (MarkingColor)((MarkingValue >> (index * 2)) & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, MarkingColor value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var shift = index * 2;
|
var shift = index * 2;
|
||||||
MarkValue = (MarkValue & ~(0b11 << shift)) | ((value & 3) << shift);
|
MarkingValue = (ushort)((MarkingValue & ~(0b11 << shift)) | (((byte)value & 3) << shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MarkingColor MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public MarkingColor MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public MarkingColor MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public MarkingColor MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public MarkingColor MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public MarkingColor MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
public void FixMemories()
|
public void FixMemories()
|
||||||
{
|
{
|
||||||
if (IsEgg) // No memories if is egg.
|
if (IsEgg) // No memories if is egg.
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary> Generation 9 <see cref="PKM"/> format. </summary>
|
/// <summary> Generation 9 <see cref="PKM"/> format. </summary>
|
||||||
public sealed class PK9 : PKM, ISanityChecksum, ITeraType, ITechRecord, IObedienceLevel,
|
public sealed class PK9 : PKM, ISanityChecksum, ITeraType, ITechRecord, IObedienceLevel,
|
||||||
IContestStats, IHyperTrain, IScaledSize, IScaledSize3, IFavorite, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories,
|
IContestStats, IHyperTrain, IScaledSize, IScaledSize3, IFavorite, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IAppliedMarkings7,
|
||||||
IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetCommon9, IRibbonSetMarks, IRibbonSetMark8, IRibbonSetMark9
|
IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetCommon9, IRibbonSetMarks, IRibbonSetMark8, IRibbonSetMark9
|
||||||
{
|
{
|
||||||
public override ReadOnlySpan<ushort> ExtraBytes =>
|
public override ReadOnlySpan<ushort> ExtraBytes =>
|
||||||
|
@ -130,7 +130,7 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, ITechRecord, IObedien
|
||||||
public override int AbilityNumber { get => Data[0x16] & 7; set => Data[0x16] = (byte)((Data[0x16] & ~7) | (value & 7)); }
|
public override int AbilityNumber { get => Data[0x16] & 7; set => Data[0x16] = (byte)((Data[0x16] & ~7) | (value & 7)); }
|
||||||
public bool IsFavorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGPE but not in SWSH
|
public bool IsFavorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGPE but not in SWSH
|
||||||
// 0x17 alignment unused
|
// 0x17 alignment unused
|
||||||
public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), (ushort)value); }
|
public ushort MarkingValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), value); }
|
||||||
// 0x1A alignment unused
|
// 0x1A alignment unused
|
||||||
// 0x1B alignment unused
|
// 0x1B alignment unused
|
||||||
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); }
|
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); }
|
||||||
|
@ -512,23 +512,30 @@ public sealed class PK9 : PKM, ISanityChecksum, ITeraType, ITechRecord, IObedien
|
||||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x154)); set => WriteUInt16LittleEndian(Data.AsSpan(0x154), (ushort)value); }
|
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x154)); set => WriteUInt16LittleEndian(Data.AsSpan(0x154), (ushort)value); }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public override int MarkingCount => 6;
|
public int MarkingCount => 6;
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public MarkingColor GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> (index * 2)) & 3;
|
return (MarkingColor)((MarkingValue >> (index * 2)) & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, MarkingColor value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var shift = index * 2;
|
var shift = index * 2;
|
||||||
MarkValue = (MarkValue & ~(0b11 << shift)) | ((value & 3) << shift);
|
MarkingValue = (ushort)((MarkingValue & ~(0b11 << shift)) | (((byte)value & 3) << shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MarkingColor MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public MarkingColor MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public MarkingColor MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public MarkingColor MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public MarkingColor MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public MarkingColor MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
public bool GetRibbon(int index) => FlagUtil.GetFlag(Data, GetRibbonByte(index), index & 7);
|
public bool GetRibbon(int index) => FlagUtil.GetFlag(Data, GetRibbonByte(index), index & 7);
|
||||||
public void SetRibbon(int index, bool value = true) => FlagUtil.SetFlag(Data, GetRibbonByte(index), index & 7, value);
|
public void SetRibbon(int index, bool value = true) => FlagUtil.SetFlag(Data, GetRibbonByte(index), index & 7, value);
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,6 @@ public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILa
|
||||||
public abstract uint TSV { get; }
|
public abstract uint TSV { get; }
|
||||||
public abstract uint PSV { get; }
|
public abstract uint PSV { get; }
|
||||||
public abstract int Characteristic { get; }
|
public abstract int Characteristic { get; }
|
||||||
public abstract int MarkValue { get; set; }
|
|
||||||
public abstract int Met_Location { get; set; }
|
public abstract int Met_Location { get; set; }
|
||||||
public abstract int Egg_Location { get; set; }
|
public abstract int Egg_Location { get; set; }
|
||||||
public abstract int OT_Friendship { get; set; }
|
public abstract int OT_Friendship { get; set; }
|
||||||
|
@ -523,10 +522,6 @@ public abstract class PKM : ISpeciesForm, ITrainerID32, IGeneration, IShiny, ILa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract int MarkingCount { get; }
|
|
||||||
public abstract int GetMarking(int index);
|
|
||||||
public abstract void SetMarking(int index, int value);
|
|
||||||
|
|
||||||
private int HPBitValPower => ((IV_HP & 2) >> 1) | ((IV_ATK & 2) >> 0) | ((IV_DEF & 2) << 1) | ((IV_SPE & 2) << 2) | ((IV_SPA & 2) << 3) | ((IV_SPD & 2) << 4);
|
private int HPBitValPower => ((IV_HP & 2) >> 1) | ((IV_ATK & 2) >> 0) | ((IV_DEF & 2) << 1) | ((IV_SPE & 2) << 2) | ((IV_SPA & 2) << 3) | ((IV_SPD & 2) << 4);
|
||||||
public virtual int HPPower => Format < 6 ? ((40 * HPBitValPower) / 63) + 30 : 60;
|
public virtual int HPPower => Format < 6 ? ((40 * HPBitValPower) / 63) + 30 : 60;
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ public sealed class RK4 : G4PKM
|
||||||
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
public override uint EXP { get => ReadUInt32LittleEndian(Data.AsSpan(0x10)); set => WriteUInt32LittleEndian(Data.AsSpan(0x10), value); }
|
||||||
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
public override int OT_Friendship { get => Data[0x14]; set => Data[0x14] = (byte)value; }
|
||||||
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
public override int Ability { get => Data[0x15]; set => Data[0x15] = (byte)value; }
|
||||||
public override int MarkValue { get => Data[0x16]; set => Data[0x16] = (byte)value; }
|
public override byte MarkingValue { get => Data[0x16]; set => Data[0x16] = value; }
|
||||||
public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
public override int Language { get => Data[0x17]; set => Data[0x17] = (byte)value; }
|
||||||
public override int EV_HP { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
public override int EV_HP { get => Data[0x18]; set => Data[0x18] = (byte)value; }
|
||||||
public override int EV_ATK { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
public override int EV_ATK { get => Data[0x19]; set => Data[0x19] = (byte)value; }
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace PKHeX.Core;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generation 3 Base <see cref="PKM"/> Class
|
/// Generation 3 Base <see cref="PKM"/> Class
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonSetUnique3, IRibbonSetOnly3, IRibbonSetRibbons, IContestStats
|
public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonSetUnique3, IRibbonSetOnly3, IRibbonSetRibbons, IContestStats, IAppliedMarkings3
|
||||||
{
|
{
|
||||||
protected G3PKM(byte[] data) : base(data) { }
|
protected G3PKM(byte[] data) : base(data) { }
|
||||||
protected G3PKM([ConstantExpected] int size) : base(size) { }
|
protected G3PKM([ConstantExpected] int size) : base(size) { }
|
||||||
|
@ -39,22 +39,28 @@ public abstract class G3PKM : PKM, IRibbonSetEvent3, IRibbonSetCommon3, IRibbonS
|
||||||
public sealed override int CurrentFriendship { get => OT_Friendship; set => OT_Friendship = value; }
|
public sealed override int CurrentFriendship { get => OT_Friendship; set => OT_Friendship = value; }
|
||||||
public sealed override int CurrentHandler { get => 0; set { } }
|
public sealed override int CurrentHandler { get => 0; set { } }
|
||||||
public sealed override int Egg_Location { get => 0; set { } }
|
public sealed override int Egg_Location { get => 0; set { } }
|
||||||
public override int MarkingCount => 4;
|
public int MarkingCount => 4;
|
||||||
|
public abstract byte MarkingValue { get; set; }
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public bool GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> index) & 1;
|
return ((MarkingValue >> index) & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, bool value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
MarkValue = (MarkValue & ~(1 << index)) | ((value & 1) << index);
|
MarkingValue = (byte)((MarkingValue & ~(1 << index)) | ((value ? 1 : 0) << index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public bool MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); } // Purposefully reverse because we swap bits already and want to match Gen4+
|
||||||
|
public bool MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public bool MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
|
||||||
public abstract ushort SpeciesInternal { get; set; } // raw access
|
public abstract ushort SpeciesInternal { get; set; } // raw access
|
||||||
|
|
||||||
public sealed override byte Form
|
public sealed override byte Form
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary> Generation 4 <see cref="PKM"/> format. </summary>
|
/// <summary> Generation 4 <see cref="PKM"/> format. </summary>
|
||||||
public abstract class G4PKM : PKM,
|
public abstract class G4PKM : PKM,
|
||||||
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetRibbons, IContestStats, IGroundTile
|
IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetUnique3, IRibbonSetUnique4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetRibbons, IContestStats, IGroundTile, IAppliedMarkings4
|
||||||
{
|
{
|
||||||
protected G4PKM(byte[] data) : base(data) { }
|
protected G4PKM(byte[] data) : base(data) { }
|
||||||
protected G4PKM([ConstantExpected] int size) : base(size) { }
|
protected G4PKM([ConstantExpected] int size) : base(size) { }
|
||||||
|
@ -162,22 +162,30 @@ public abstract class G4PKM : PKM,
|
||||||
public abstract byte BallDPPt { get; set; }
|
public abstract byte BallDPPt { get; set; }
|
||||||
public abstract byte BallHGSS { get; set; }
|
public abstract byte BallHGSS { get; set; }
|
||||||
public abstract byte PokeathlonStat { get; set; }
|
public abstract byte PokeathlonStat { get; set; }
|
||||||
public override int MarkingCount => 6;
|
public int MarkingCount => 6;
|
||||||
|
public abstract byte MarkingValue { get; set; }
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public bool GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> index) & 1;
|
return ((MarkingValue >> index) & 1) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, bool value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
MarkValue = (MarkValue & ~(1 << index)) | ((value & 1) << index);
|
MarkingValue = (byte)((MarkingValue & ~(1 << index)) | ((value ? 1 : 0) << index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public bool MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public bool MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public bool MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public bool MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public bool MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
public abstract ushort Egg_LocationDP { get; set; }
|
public abstract ushort Egg_LocationDP { get; set; }
|
||||||
public abstract ushort Egg_LocationExtended { get; set; }
|
public abstract ushort Egg_LocationExtended { get; set; }
|
||||||
public abstract ushort Met_LocationDP { get; set; }
|
public abstract ushort Met_LocationDP { get; set; }
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace PKHeX.Core;
|
||||||
|
|
||||||
/// <summary> Generation 8 <see cref="PKM"/> format. </summary>
|
/// <summary> Generation 8 <see cref="PKM"/> format. </summary>
|
||||||
public abstract class G8PKM : PKM, ISanityChecksum,
|
public abstract class G8PKM : PKM, ISanityChecksum,
|
||||||
ITechRecord, ISociability, IContestStats, IHyperTrain, IScaledSize, IGigantamax, IFavorite, IDynamaxLevel, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IPokerusStatus,
|
ITechRecord, ISociability, IContestStats, IHyperTrain, IScaledSize, IGigantamax, IFavorite, IDynamaxLevel, IHandlerLanguage, IFormArgument, IHomeTrack, IBattleVersion, ITrainerMemories, IPokerusStatus, IAppliedMarkings7,
|
||||||
IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetCommon9, IRibbonSetMarks, IRibbonSetMark8, IRibbonSetMark9
|
IRibbonIndex, IRibbonSetAffixed, IRibbonSetRibbons, IRibbonSetEvent3, IRibbonSetEvent4, IRibbonSetCommon3, IRibbonSetCommon4, IRibbonSetCommon6, IRibbonSetMemory6, IRibbonSetCommon7, IRibbonSetCommon8, IRibbonSetCommon9, IRibbonSetMarks, IRibbonSetMark8, IRibbonSetMark9
|
||||||
{
|
{
|
||||||
protected G8PKM() : base(PokeCrypto.SIZE_8PARTY) { }
|
protected G8PKM() : base(PokeCrypto.SIZE_8PARTY) { }
|
||||||
|
@ -104,7 +104,7 @@ public abstract class G8PKM : PKM, ISanityChecksum,
|
||||||
public bool IsFavorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGP/E but not in SW/SH
|
public bool IsFavorite { get => (Data[0x16] & 8) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~8) | ((value ? 1 : 0) << 3)); } // unused, was in LGP/E but not in SW/SH
|
||||||
public bool CanGigantamax { get => (Data[0x16] & 16) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~16) | (value ? 16 : 0)); }
|
public bool CanGigantamax { get => (Data[0x16] & 16) != 0; set => Data[0x16] = (byte)((Data[0x16] & ~16) | (value ? 16 : 0)); }
|
||||||
// 0x17 alignment unused
|
// 0x17 alignment unused
|
||||||
public override int MarkValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), (ushort)value); }
|
public ushort MarkingValue { get => ReadUInt16LittleEndian(Data.AsSpan(0x18)); set => WriteUInt16LittleEndian(Data.AsSpan(0x18), value); }
|
||||||
// 0x1A alignment unused
|
// 0x1A alignment unused
|
||||||
// 0x1B alignment unused
|
// 0x1B alignment unused
|
||||||
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); }
|
public override uint PID { get => ReadUInt32LittleEndian(Data.AsSpan(0x1C)); set => WriteUInt32LittleEndian(Data.AsSpan(0x1C), value); }
|
||||||
|
@ -454,23 +454,30 @@ public abstract class G8PKM : PKM, ISanityChecksum,
|
||||||
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x154)); set => WriteUInt16LittleEndian(Data.AsSpan(0x154), (ushort)value); }
|
public override int Stat_SPD { get => ReadUInt16LittleEndian(Data.AsSpan(0x154)); set => WriteUInt16LittleEndian(Data.AsSpan(0x154), (ushort)value); }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public override int MarkingCount => 6;
|
public int MarkingCount => 6;
|
||||||
|
|
||||||
public override int GetMarking(int index)
|
public MarkingColor GetMarking(int index)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
return (MarkValue >> (index * 2)) & 3;
|
return (MarkingColor)((MarkingValue >> (index * 2)) & 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetMarking(int index, int value)
|
public void SetMarking(int index, MarkingColor value)
|
||||||
{
|
{
|
||||||
if ((uint)index >= MarkingCount)
|
if ((uint)index >= MarkingCount)
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||||||
var shift = index * 2;
|
var shift = index * 2;
|
||||||
MarkValue = (MarkValue & ~(0b11 << shift)) | ((value & 3) << shift);
|
MarkingValue = (ushort)((MarkingValue & ~(0b11 << shift)) | (((byte)value & 3) << shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MarkingColor MarkingCircle { get => GetMarking(0); set => SetMarking(0, value); }
|
||||||
|
public MarkingColor MarkingTriangle { get => GetMarking(1); set => SetMarking(1, value); }
|
||||||
|
public MarkingColor MarkingSquare { get => GetMarking(2); set => SetMarking(2, value); }
|
||||||
|
public MarkingColor MarkingHeart { get => GetMarking(3); set => SetMarking(3, value); }
|
||||||
|
public MarkingColor MarkingStar { get => GetMarking(4); set => SetMarking(4, value); }
|
||||||
|
public MarkingColor MarkingDiamond { get => GetMarking(5); set => SetMarking(5, value); }
|
||||||
|
|
||||||
public bool GetRibbon(int index) => FlagUtil.GetFlag(Data, GetRibbonByte(index), index & 7);
|
public bool GetRibbon(int index) => FlagUtil.GetFlag(Data, GetRibbonByte(index), index & 7);
|
||||||
public void SetRibbon(int index, bool value = true) => FlagUtil.SetFlag(Data, GetRibbonByte(index), index & 7, value);
|
public void SetRibbon(int index, bool value = true) => FlagUtil.SetFlag(Data, GetRibbonByte(index), index & 7, value);
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,6 @@ public abstract class GBPKM : PKM
|
||||||
public sealed override uint TSV => 0x0000;
|
public sealed override uint TSV => 0x0000;
|
||||||
public sealed override uint PSV => 0xFFFF;
|
public sealed override uint PSV => 0xFFFF;
|
||||||
public sealed override int Characteristic => -1;
|
public sealed override int Characteristic => -1;
|
||||||
public sealed override int MarkValue { get => 0; set { } }
|
|
||||||
public sealed override int Ability { get => -1; set { } }
|
public sealed override int Ability { get => -1; set { } }
|
||||||
public sealed override int CurrentHandler { get => 0; set { } }
|
public sealed override int CurrentHandler { get => 0; set { } }
|
||||||
public sealed override int Egg_Location { get => 0; set { } }
|
public sealed override int Egg_Location { get => 0; set { } }
|
||||||
|
@ -181,9 +180,6 @@ public abstract class GBPKM : PKM
|
||||||
public int IV_SPC { get => (DV16 >> 0) & 0xF; set => DV16 = (ushort)((DV16 & ~(0xF << 0)) | (ushort)((value > 0xF ? 0xF : value) << 0)); }
|
public int IV_SPC { get => (DV16 >> 0) & 0xF; set => DV16 = (ushort)((DV16 & ~(0xF << 0)) | (ushort)((value > 0xF ? 0xF : value) << 0)); }
|
||||||
public sealed override int IV_SPA { get => IV_SPC; set => IV_SPC = value; }
|
public sealed override int IV_SPA { get => IV_SPC; set => IV_SPC = value; }
|
||||||
public sealed override int IV_SPD { get => IV_SPC; set { } }
|
public sealed override int IV_SPD { get => IV_SPC; set { } }
|
||||||
public override int MarkingCount => 0;
|
|
||||||
public override int GetMarking(int index) => 0;
|
|
||||||
public override void SetMarking(int index, int value) { }
|
|
||||||
|
|
||||||
public void SetNotNicknamed() => SetNotNicknamed(GuessedLanguage());
|
public void SetNotNicknamed() => SetNotNicknamed(GuessedLanguage());
|
||||||
public abstract void SetNotNicknamed(int language);
|
public abstract void SetNotNicknamed(int language);
|
||||||
|
|
|
@ -44,7 +44,7 @@ public sealed class XK3 : G3PKM, IShadowCapture
|
||||||
public override int Stat_Level { get => Data[0x11]; set => Data[0x11] = (byte)value; }
|
public override int Stat_Level { get => Data[0x11]; set => Data[0x11] = (byte)value; }
|
||||||
public override byte CNT_Sheen { get => Data[0x12]; set => Data[0x12] = value; }
|
public override byte CNT_Sheen { get => Data[0x12]; set => Data[0x12] = value; }
|
||||||
public override int PKRS_Strain { get => Data[0x13] & 0xF; set => Data[0x13] = (byte)(value & 0xF); }
|
public override int PKRS_Strain { get => Data[0x13] & 0xF; set => Data[0x13] = (byte)(value & 0xF); }
|
||||||
public override int MarkValue { get => SwapBits(Data[0x14], 1, 2); set => Data[0x14] = (byte)SwapBits(value, 1, 2); }
|
public override byte MarkingValue { get => (byte)SwapBits(Data[0x14], 1, 2); set => Data[0x14] = (byte)SwapBits(value, 1, 2); }
|
||||||
public override int PKRS_Days { get => Math.Max((sbyte)Data[0x15], (sbyte)0); set => Data[0x15] = (byte)(value == 0 ? 0xFF : value & 0xF); }
|
public override int PKRS_Days { get => Math.Max((sbyte)Data[0x15], (sbyte)0); set => Data[0x15] = (byte)(value == 0 ? 0xFF : value & 0xF); }
|
||||||
// 0x16-0x1C Battle Related
|
// 0x16-0x1C Battle Related
|
||||||
private int XDPKMFLAGS { get => Data[0x1D]; set => Data[0x1D] = (byte)value; }
|
private int XDPKMFLAGS { get => Data[0x1D]; set => Data[0x1D] = (byte)value; }
|
||||||
|
|
|
@ -80,12 +80,12 @@ public sealed class DrawConfig : IDisposable
|
||||||
_ => TextColor,
|
_ => TextColor,
|
||||||
};
|
};
|
||||||
|
|
||||||
public bool GetMarkingColor(int markval, out Color c)
|
public bool GetMarkingColor(MarkingColor markval, out Color c)
|
||||||
{
|
{
|
||||||
switch (markval)
|
switch (markval)
|
||||||
{
|
{
|
||||||
case 1: c = MarkBlue; return true;
|
case MarkingColor.Blue: c = MarkBlue; return true;
|
||||||
case 2: c = MarkPink; return true;
|
case MarkingColor.Pink: c = MarkPink; return true;
|
||||||
default: c = MarkDefault; return false; // recolor not required
|
default: c = MarkDefault; return false; // recolor not required
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -496,27 +496,30 @@ public sealed partial class PKMEditor : UserControl, IMainEditor
|
||||||
|
|
||||||
private void SetMarkings()
|
private void SetMarkings()
|
||||||
{
|
{
|
||||||
var pba = Markings;
|
|
||||||
var count = Entity.MarkingCount;
|
|
||||||
for (int i = 0; i < pba.Length; i++)
|
|
||||||
pba[i].Image = GetMarkSprite(pba[i], i < count && Entity.GetMarking(i) != 0);
|
|
||||||
|
|
||||||
PB_MarkShiny.Image = GetMarkSprite(PB_MarkShiny, !BTN_Shinytize.Enabled);
|
PB_MarkShiny.Image = GetMarkSprite(PB_MarkShiny, !BTN_Shinytize.Enabled);
|
||||||
PB_MarkCured.Image = GetMarkSprite(PB_MarkCured, CHK_Cured.Checked);
|
PB_MarkCured.Image = GetMarkSprite(PB_MarkCured, CHK_Cured.Checked);
|
||||||
|
|
||||||
PB_Favorite.Image = GetMarkSprite(PB_Favorite, Entity is IFavorite { IsFavorite: true });
|
PB_Favorite.Image = GetMarkSprite(PB_Favorite, Entity is IFavorite { IsFavorite: true });
|
||||||
PB_Origin.Image = GetOriginSprite(Entity);
|
PB_Origin.Image = GetOriginSprite(Entity);
|
||||||
|
|
||||||
// Colored Markings
|
var pba = Markings;
|
||||||
if (Entity.Format < 7)
|
if (Entity is IAppliedMarkings<bool> b)
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
if (!Draw.GetMarkingColor(Entity.GetMarking(i), out Color c))
|
for (int i = 0; i < b.MarkingCount; i++)
|
||||||
continue;
|
pba[i].Image = GetMarkSprite(pba[i], b.GetMarking(i));
|
||||||
var pb = pba[i];
|
}
|
||||||
pb.Image = ImageUtil.ChangeAllColorTo(pb.Image, c);
|
else if (Entity is IAppliedMarkings<MarkingColor> c)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < pba.Length; i++)
|
||||||
|
{
|
||||||
|
var pb = pba[i];
|
||||||
|
var state = c.GetMarking(i);
|
||||||
|
var opaque = Draw.GetMarkingColor(state, out var color);
|
||||||
|
var img = GetMarkSprite(pb, opaque);
|
||||||
|
if (opaque)
|
||||||
|
img = ImageUtil.ChangeAllColorTo(img, color);
|
||||||
|
pb.Image = img;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue