mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-29 23:40:27 +00:00
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:
parent
4c1232855f
commit
71fab815bf
9 changed files with 139 additions and 79 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) { }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
59
PKHeX.Core/Saves/Storage/StorageSlotFlag.cs
Normal file
59
PKHeX.Core/Saves/Storage/StorageSlotFlag.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue