Provide more slot information

remove lockedslots, store & save all teamslots for sav7
differentiate locked slots from overwrite protected slots by emitting an
enum containing info about the slot

locked = can't be replaced, period.
starter/battleteam = can't be pasted over by bulk-pastes

can eventually show more specific sprite layers to denote party
indexes/team#/starter
This commit is contained in:
Kurt 2018-12-04 22:59:28 -08:00
parent 4c1232855f
commit 71fab815bf
9 changed files with 139 additions and 79 deletions

View file

@ -145,7 +145,7 @@ namespace PKHeX.Core
{
if (c.Type > StorageSlotType.Party)
return true;
return SAV.IsSlotLocked(c.Box, c.Slot);
return SAV.IsSlotOverwriteProtected(c.Box, c.Slot);
}
private PKM ReadSlot(StorageSlotOffset slot) => SAV.GetPKM(slot);

View file

@ -42,12 +42,11 @@ namespace PKHeX.Core
if (demo || !Exportable)
{
PokeDex = -1; // Disabled
LockedSlots = Array.Empty<int>();
TeamSlots = Array.Empty<int>();
}
else // Valid slot locking info present
{
LoadLockedSlots();
LoadBattleTeams();
}
}
@ -105,6 +104,7 @@ namespace PKHeX.Core
if (!CanReadChecksums())
return;
Blocks.SetChecksums(Data);
SaveBattleTeams();
Data = SaveUtil.Resign7(Data);
IsMemeCryptoApplied = true;
}
@ -197,7 +197,6 @@ namespace PKHeX.Core
FashionLength = 0x1A08;
TeamCount = 6;
LockedSlots = new int[6*TeamCount];
TeamSlots = new int[6*TeamCount];
if (USUM)
{
@ -1240,46 +1239,55 @@ namespace PKHeX.Core
public override int BoxesUnlocked { get => Data[PCFlags + 1]; set => Data[PCFlags + 1] = (byte)value; }
public override bool IsSlotLocked(int box, int slot)
private void LoadBattleTeams()
{
if ((uint)slot >= 30 || (uint)box >= BoxCount)
return false;
int slotIndex = slot + (BoxSlotCount * box);
return LockedSlots.Any(s => s == slotIndex);
}
public override bool IsSlotInBattleTeam(int box, int slot)
for (int i = 0; i < TeamCount*6; i++)
{
if ((uint)slot >= 30 || (uint)box >= BoxCount)
return false;
int slotIndex = slot + (BoxSlotCount * box);
return TeamSlots.Any(s => s == slotIndex);
}
private void LoadLockedSlots()
{
int lockedCount = 0, teamCount = 0;
for (int i = 0; i < TeamCount; i++)
{
bool locked = Data[PCBackgrounds - TeamCount - i] == 1;
for (int j = 0; j < 6; j++)
{
short val = BitConverter.ToInt16(Data, BattleBoxFlags + (((i * 6) + j) * 2));
short val = BitConverter.ToInt16(Data, BattleBoxFlags + (i * 2));
if (val < 0)
{
TeamSlots[i] = -1;
continue;
}
var slotVal = ((BoxSlotCount * (val >> 8)) + (val & 0xFF)) & 0xFFFF;
if (locked)
LockedSlots[lockedCount++] = slotVal;
else
TeamSlots[teamCount++] = slotVal;
int box = val >> 8;
int slot = val & 0xFF;
int index = (BoxSlotCount * box) + slot;
TeamSlots[i] = index & 0xFFFF;
}
}
Array.Resize(ref LockedSlots, lockedCount);
Array.Resize(ref TeamSlots, teamCount);
private void SaveBattleTeams()
{
for (int i = 0; i < TeamCount * 6; i++)
{
int index = TeamSlots[i];
if (index < 0)
{
BitConverter.GetBytes((short)index).CopyTo(Data, BattleBoxFlags + (i * 2));
continue;
}
int box = index / BoxSlotCount;
int slot = index % BoxSlotCount;
int val = (box << 8) | slot;
BitConverter.GetBytes((short)val).CopyTo(Data, BattleBoxFlags + (i * 2));
}
}
private bool IsTeamLocked(int team) => Data[PCBackgrounds - TeamCount - team] == 1;
public override StorageSlotFlag GetSlotFlags(int index)
{
int team = Array.IndexOf(TeamSlots, index);
if (team < 0)
return StorageSlotFlag.None;
team /= 6;
var val = (StorageSlotFlag)((int)StorageSlotFlag.BattleTeam1 << team);
if (IsTeamLocked(team))
val |= StorageSlotFlag.Locked;
return val;
}
private int FusedCount => USUM ? 3 : 1;

View file

@ -170,11 +170,19 @@ namespace PKHeX.Core
public override int GetPartyOffset(int slot) => Storage.GetPartyOffset(slot);
public override int PartyCount { get => Storage.PartyCount; protected set => Storage.PartyCount = value; }
public override bool IsSlotInBattleTeam(int box, int slot) => Storage.IsSlotInBattleTeam(box, slot);
public override bool IsSlotLocked(int box, int slot) => Storage.IsSlotLocked(box, slot);
protected override bool IsSlotOverwriteProtected(int box, int slot) => false;
protected override void SetPartyValues(PKM pkm, bool isParty) => base.SetPartyValues(pkm, true);
public override StorageSlotFlag GetSlotFlags(int index)
{
var val = StorageSlotFlag.None;
if (Storage.PokeListInfo[6] == index)
val |= StorageSlotFlag.Starter;
int position = Array.IndexOf(Storage.PokeListInfo, index);
if ((uint) position < 6)
val |= (StorageSlotFlag)((int)StorageSlotFlag.Party1 << position);
return val;
}
public override string GetBoxName(int box) => $"Box {box + 1}";
public override void SetBoxName(int box, string value) { }

View file

@ -181,7 +181,7 @@ namespace PKHeX.Core
int ofs = GetBoxOffset(box);
for (int slot = 0; slot < BoxSlotCount; slot++, ofs += SIZE_STORED)
{
if (!IsSlotLocked(box, slot))
if (!GetSlotFlags(box, slot).IsOverwriteProtected())
SetStoredSlot(value[index + slot], ofs);
}
}
@ -204,7 +204,7 @@ namespace PKHeX.Core
data[i].Identifier = $"{boxName}:{slot + 1:00}";
data[i].Box = box + 1;
data[i].Slot = slot + 1;
data[i].Locked = IsSlotLocked(box, slot);
data[i].Locked = GetSlotFlags(box, slot).HasFlagFast(StorageSlotFlag.Locked);
}
}
@ -452,10 +452,12 @@ namespace PKHeX.Core
public virtual int BoxesUnlocked { get => -1; set { } }
public virtual byte[] BoxFlags { get => null; set { } }
public virtual int CurrentBox { get; set; }
protected int[] LockedSlots = Array.Empty<int>();
protected int[] TeamSlots = Array.Empty<int>();
protected virtual IList<int>[] SlotPointers => new[] {LockedSlots,TeamSlots};
protected virtual IList<int>[] SlotPointers => new[] {TeamSlots};
public virtual StorageSlotFlag GetSlotFlags(int index) => StorageSlotFlag.None;
public StorageSlotFlag GetSlotFlags(int box, int slot) => GetSlotFlags((box * BoxSlotCount) + slot);
public bool IsSlotLocked(int box, int slot) => GetSlotFlags(box, slot).HasFlagFast(StorageSlotFlag.Locked);
public bool IsSlotOverwriteProtected(int box, int slot) => GetSlotFlags(box, slot).IsOverwriteProtected();
public bool MoveBox(int box, int insertBeforeBox)
{
@ -661,25 +663,22 @@ namespace PKHeX.Core
PartyCount--;
}
public virtual bool IsSlotLocked(int box, int slot) => false;
public virtual bool IsSlotInBattleTeam(int box, int slot) => false;
protected virtual bool IsSlotOverwriteProtected(int box, int slot) => IsSlotLocked(box, slot) || IsSlotInBattleTeam(box, slot);
protected virtual bool IsSlotSwapProtected(int box, int slot) => false;
protected bool IsSlotSwapProtected(int box, int slot) => false;
private bool IsRegionOverwriteProtected(int min, int max)
{
if (LockedSlots.Any(slot => WithinRange(slot, min, max))) // locked slot within box
return true;
if (TeamSlots.Any(slot => WithinRange(slot, min, max))) // team slot within box
return true;
return false;
return SlotPointers.SelectMany(z => z)
.Where(z => GetSlotFlags(z).IsOverwriteProtected())
.Any(slot => WithinRange(slot, min, max));
}
private static bool WithinRange(int slot, int min, int max) => min <= slot && slot < max;
public bool IsAnySlotLockedInBox(int BoxStart, int BoxEnd)
{
return LockedSlots.Any(slot => WithinRange(slot, BoxStart*BoxSlotCount, (BoxEnd + 1)*BoxSlotCount));
return SlotPointers.SelectMany(z => z)
.Where(z => GetSlotFlags(z).HasFlagFast(StorageSlotFlag.Locked))
.Any(slot => WithinRange(slot, BoxStart*BoxSlotCount, (BoxEnd + 1)*BoxSlotCount));
}
public void SortBoxes(int BoxStart = 0, int BoxEnd = -1, Func<IEnumerable<PKM>, IEnumerable<PKM>> sortMethod = null, bool reverse = false)
@ -758,7 +757,7 @@ namespace PKHeX.Core
public bool SetPCBinary(byte[] data)
{
if (LockedSlots.Length != 0)
if (IsRegionOverwriteProtected(0, SlotCount))
return false;
if (data.Length != PCBinary.Length)
return false;
@ -774,7 +773,8 @@ namespace PKHeX.Core
{
int start = box * BoxSlotCount;
int end = start + BoxSlotCount;
if (LockedSlots.Any(slot => start <= slot && slot < end))
if (IsRegionOverwriteProtected(start, end))
return false;
if (data.Length != GetBoxBinary(box).Length)
return false;

View file

@ -0,0 +1,59 @@
using System;
namespace PKHeX.Core
{
[Flags]
public enum StorageSlotFlag
{
None,
Party1 = 1 << 0,
Party2 = 1 << 1,
Party3 = 1 << 2,
Party4 = 1 << 3,
Party5 = 1 << 4,
Party6 = 1 << 5,
BattleTeam1 = 1 << 6,
BattleTeam2 = 1 << 7,
BattleTeam3 = 1 << 8,
BattleTeam4 = 1 << 9,
BattleTeam5 = 1 << 10,
BattleTeam6 = 1 << 11,
Starter = 1 << 29,
Locked = 1 << 30,
}
public static class StorageSlotFlagExtensions
{
public static bool HasFlagFast(this StorageSlotFlag value, StorageSlotFlag flag) => (value & flag) != 0;
public static bool IsOverwriteProtected(this StorageSlotFlag value)
{
if (value.HasFlagFast(StorageSlotFlag.Locked))
return true;
if (value.HasFlagFast(StorageSlotFlag.Starter))
return true;
return value.IsBattleTeam();
}
public static bool IsBattleTeam(this StorageSlotFlag value)
{
if (value.HasFlagFast(StorageSlotFlag.BattleTeam1))
return true;
if (value.HasFlagFast(StorageSlotFlag.BattleTeam2))
return true;
if (value.HasFlagFast(StorageSlotFlag.BattleTeam3))
return true;
if (value.HasFlagFast(StorageSlotFlag.BattleTeam4))
return true;
if (value.HasFlagFast(StorageSlotFlag.BattleTeam5))
return true;
if (value.HasFlagFast(StorageSlotFlag.BattleTeam6))
return true;
return false;
}
}
}

View file

@ -123,22 +123,6 @@ namespace PKHeX.Core
return index >= 0 ? index : MAX_SLOTS;
}
public bool IsSlotInBattleTeam(int box, int slot)
{
if ((uint)slot >= SAV.SlotCount || (uint)box >= SAV.BoxCount)
return false;
int slotIndex = slot + (SAV.BoxSlotCount * box);
return PokeListInfo.Take(6).Any(s => s == slotIndex) || StarterIndex == slotIndex;
}
public bool IsSlotLocked(int box, int slot)
{
if ((uint)slot >= SAV.SlotCount || (uint)box >= SAV.BoxCount)
return false;
return false;
}
public bool CompressStorage()
{
// Box Data is stored as a list, instead of an array. Empty interstitials are not legal.

View file

@ -103,7 +103,7 @@ namespace PKHeX.Core
{
int box = getbox();
int slot = getslot();
while (SAV.IsSlotLocked(box, slot))
while (SAV.IsSlotOverwriteProtected(box, slot))
{
++i;
box = getbox();

View file

@ -330,7 +330,7 @@ namespace PKHeX.WinForms.Controls
int slotSkipped = 0;
for (int i = 0; i < SAV.BoxSlotCount; i++) // set to every slot in box
{
if (SAV.IsSlotLocked(box, i))
if (SAV.IsSlotOverwriteProtected(box, i))
{ slotSkipped++; continue; }
SAV.SetStoredSlot(pk, Box.GetSlotOffset(box, i));
Box.SetSlotFiller(pk, box, i);
@ -789,7 +789,7 @@ namespace PKHeX.WinForms.Controls
int slotSkipped = 0;
for (int i = 0; i < 24; i++)
{
if (SAV.IsSlotLocked(Box.CurrentBox, i))
if (SAV.IsSlotOverwriteProtected(Box.CurrentBox, i))
{ slotSkipped++; continue; }
SAV.SetStoredSlot(data[i], offset + (i * SAV.SIZE_STORED), noSetb);
}

View file

@ -127,9 +127,10 @@ namespace PKHeX.WinForms
}
if (inBox) // in box
{
if (SAV.IsSlotLocked(box, slot))
var flags = SAV.GetSlotFlags(box, slot);
if (flags.HasFlagFast(StorageSlotFlag.Locked))
sprite = ImageUtil.LayerImage(sprite, Resources.locked, 26, 0);
else if (SAV.IsSlotInBattleTeam(box, slot))
else if (flags != 0)
sprite = ImageUtil.LayerImage(sprite, Resources.team, 21, 0);
}