Encounter visualization: Show ball and differentiate visually

This commit is contained in:
Kurt 2021-08-24 14:03:20 -07:00
parent 302b5d1d90
commit 6e3bcd5b66
8 changed files with 70 additions and 4 deletions

View file

@ -5,7 +5,7 @@ namespace PKHeX.Core
/// <summary>
/// Contains details about an encounter that can be found in <see cref="GameVersion.GO"/>.
/// </summary>
public abstract record EncounterSlotGO : EncounterSlot, IPogoSlot
public abstract record EncounterSlotGO : EncounterSlot, IPogoSlot, IFixedBall
{
/// <inheritdoc/>
public int Start { get; }
@ -24,6 +24,8 @@ namespace PKHeX.Core
public override bool IsShiny => Shiny.IsShiny();
public Ball FixedBall => Type.GetValidBall();
protected EncounterSlotGO(EncounterArea area, int species, int form, int start, int end, Shiny shiny, Gender gender, PogoType type) : base(area, species, form, type.GetMinLevel(), EncountersGO.MAX_LEVEL)
{
Start = start;

View file

@ -9,7 +9,7 @@ namespace PKHeX.Core
/// <remarks>
/// Static Encounters are fixed position encounters with properties that are not subject to Wild Encounter conditions.
/// </remarks>
public abstract record EncounterStatic : IEncounterable, IMoveset, ILocation, IEncounterMatch
public abstract record EncounterStatic : IEncounterable, IMoveset, ILocation, IEncounterMatch, IFixedBall
{
public int Species { get; init; }
public int Form { get; init; }
@ -28,6 +28,8 @@ namespace PKHeX.Core
public bool Gift { get; init; }
public int Ball { get; init; } = 4; // Only checked when is Gift
public Ball FixedBall => Gift ? (Ball)Ball : Core.Ball.None;
public IReadOnlyList<int> Moves { get; init; } = Array.Empty<int>();
public IReadOnlyList<int> IVs { get; init; } = Array.Empty<int>();
public int FlawlessIVCount { get; init; }

View file

@ -10,7 +10,7 @@ namespace PKHeX.Core
/// <remarks>
/// Trade data is fixed level in all cases except for the first few generations of games.
/// </remarks>
public abstract record EncounterTrade : IEncounterable, IMoveset, ILocation, IEncounterMatch
public abstract record EncounterTrade : IEncounterable, IMoveset, ILocation, IEncounterMatch, IFixedBall
{
public int Species { get; init; }
public int Form { get; init; }
@ -29,6 +29,8 @@ namespace PKHeX.Core
public Shiny Shiny { get; init; } = Shiny.Never;
public int Ball { get; init; } = 4;
public Ball FixedBall => (Ball)Ball;
public int TID { get; init; }
public int SID { get; init; }
public int OTGender { get; init; } = -1;

View file

@ -0,0 +1,7 @@
namespace PKHeX.Core
{
public interface IFixedBall
{
Ball FixedBall { get; }
}
}

View file

@ -7,7 +7,7 @@ namespace PKHeX.Core
/// <summary>
/// Mystery Gift Template File
/// </summary>
public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn, ILocation
public abstract class MysteryGift : IEncounterable, IMoveset, IRelearn, ILocation, IFixedBall
{
/// <summary>
/// Determines whether or not the given length of bytes is valid for a mystery gift.
@ -146,6 +146,8 @@ namespace PKHeX.Core
public virtual bool EggEncounter => IsEgg;
public abstract int EggLocation { get; set; }
public Ball FixedBall => (Ball)Ball;
public int TrainerID7 => (int)((uint)(TID | (SID << 16)) % 1000000);
public int TrainerSID7 => (int)((uint)(TID | (SID << 16)) / 1000000);

View file

@ -50,6 +50,19 @@ namespace PKHeX.Drawing
return bmp;
}
public static Bitmap ChangeTransparentTo(Image img, Color c)
{
var bmp = (Bitmap)img.Clone();
GetBitmapData(bmp, out BitmapData bmpData, out IntPtr ptr, out byte[] data);
Marshal.Copy(ptr, data, 0, data.Length);
SetAllTransparencyTo(data, c);
Marshal.Copy(data, 0, ptr, data.Length);
bmp.UnlockBits(bmpData);
return bmp;
}
public static Bitmap ToGrayscale(Image img)
{
var bmp = (Bitmap)img.Clone();
@ -117,6 +130,22 @@ namespace PKHeX.Drawing
data[i + 3] = (byte)(data[i + 3] * trans);
}
public static void SetAllTransparencyTo(byte[] data, Color c)
{
byte R = c.R;
byte G = c.G;
byte B = c.B;
for (int i = 0; i < data.Length; i += 4)
{
if (data[i + 3] != 0)
continue;
data[i + 0] = B;
data[i + 1] = G;
data[i + 2] = R;
data[i + 3] = 0x3F;
}
}
public static void ChangeAllColorTo(byte[] data, Color c)
{
byte R = c.R;

View file

@ -7,6 +7,8 @@ namespace PKHeX.Drawing
public abstract class SpriteBuilder : ISpriteBuilder<Image>
{
public static bool ShowEggSpriteAsItem { get; set; } = true;
public static bool EncounterColorBackground { get; set; } = true;
public static bool EncounterShowFixedBall { get; set; } = true;
/// <summary> Width of the generated Sprite image. </summary>
public abstract int Width { get; }

View file

@ -68,6 +68,11 @@ namespace PKHeX.Drawing
return Spriter.None;
var img = GetBaseImage(gift);
if (SpriteBuilder.EncounterColorBackground)
{
var color = Color.FromArgb(gift.GetType().Name.GetHashCode() * 0x43FD43FD);
img = ImageUtil.ChangeTransparentTo(img, color);
}
if (gift.GiftUsed)
img = ImageUtil.ChangeOpacity(img, 0.3);
return img;
@ -81,6 +86,11 @@ namespace PKHeX.Drawing
{
var gender = Math.Max(0, gift.Gender);
var img = GetSprite(gift.Species, gift.Form, gender, 0, gift.HeldItem, gift.IsEgg, gift.IsShiny, gift.Generation);
if (SpriteBuilder.EncounterShowFixedBall && gift is IFixedBall { FixedBall: not Ball.None } b)
{
var ballSprite = GetBallSprite((int)b.FixedBall);
img = ImageUtil.LayerImage(img, ballSprite, 0, img.Height - ballSprite.Height);
}
if (gift is IGigantamax {CanGigantamax: true})
{
var gm = Resources.dyna;
@ -224,6 +234,16 @@ namespace PKHeX.Drawing
return g.Sprite();
var gender = GetDisplayGender(enc);
var img = GetSprite(enc.Species, enc.Form, gender, 0, 0, enc.EggEncounter, enc.IsShiny, enc.Generation);
if (SpriteBuilder.EncounterColorBackground)
{
var color = Color.FromArgb(enc.GetType().Name.GetHashCode() * 0x43FD43FD);
img = ImageUtil.ChangeTransparentTo(img, color);
}
if (SpriteBuilder.EncounterShowFixedBall && enc is IFixedBall {FixedBall: not Ball.None} b)
{
var ballSprite = GetBallSprite((int)b.FixedBall);
img = ImageUtil.LayerImage(img, ballSprite, 0, img.Height - ballSprite.Height);
}
if (enc is IGigantamax {CanGigantamax: true})
{
var gm = Resources.dyna;