PKHeX/PKHeX.Core/Saves/Substructures/Gen7/EventWork7b.cs
Kurt 02420d3e93
PKHeX.Core Nullable cleanup (#2401)
* Handle some nullable cases

Refactor MysteryGift into a second abstract class (backed by a byte array, or fake data)
Make some classes have explicit constructors instead of { } initialization

* Handle bits more obviously without null

* Make SaveFile.BAK explicitly readonly again

* merge constructor methods to have readonly fields

* Inline some properties

* More nullable handling

* Rearrange box actions

define straightforward classes to not have any null properties

* Make extrabyte reference array immutable

* Move tooltip creation to designer

* Rearrange some logic to reduce nesting

* Cache generated fonts
* Split mystery gift album purpose
* Handle more tooltips
* Disallow null setters
* Don't capture RNG object, only type enum

* Unify learnset objects
Now have readonly properties which are never null
don't new() empty learnsets (>800 Learnset objects no longer created,
total of 2400 objects since we also new() a move & level array)
optimize g1/2 reader for early abort case

* Access rewrite
Initialize blocks in a separate object, and get via that object
removes a couple hundred "might be null" warnings since blocks are now readonly getters
some block references have been relocated, but interfaces should expose all that's needed
put HoF6 controls in a groupbox, and disable

* Readonly personal data
* IVs non nullable for mystery gift
* Explicitly initialize forced encounter moves
* Make shadow objects readonly & non-null
Put murkrow fix in binary data resource, instead of on startup
* Assign dex form fetch on constructor
Fixes legality parsing edge cases
also handle cxd parse for valid; exit before exception is thrown in FrameGenerator

* Remove unnecessary null checks
* Keep empty value until init
SetPouch sets the value to an actual one during load, but whatever

* Readonly team lock data
* Readonly locks
Put locked encounters at bottom (favor unlocked)

* Mail readonly data / offset
Rearrange some call flow and pass defaults
Add fake classes for SaveDataEditor mocking
Always party size, no need to check twice in stat editor
use a fake save file as initial data for savedata editor, and for
gamedata (wow i found a usage)
constrain eventwork editor to struct variable types (uint, int, etc),
thus preventing null assignment errors
2019-10-16 18:47:31 -07:00

182 lines
6.7 KiB
C#

using System;
namespace PKHeX.Core
{
public sealed class EventWork7b : SaveBlock, IEventWork<int>
{
public EventWork7b(SAV7b sav, int offset) : base(sav)
{
Offset = offset;
// Zone @ 0x21A0 - 0x21AF (128 flags)
// System @ 0x21B0 - 0x21EF (512 flags) -- is this really 256 instead, with another 256 region after for the small vanish?
// Vanish @ 0x21F0 - 0x22AF (1536 flags)
// Event @ 0x22B0 - 0x23A7 (rest of the flags) (512) -- I think trainer flags are afterwards.... For now, this is a catch-all
// time flags (39 used flags of 42) = 6 bytes 0x22F0-0x22F5
// trainer flags (???) = 0x22F6 - end?
}
// Overall Layout
private const int WorkCount = 1000;
private const int WorkSize = sizeof(int);
private const int FlagStart = WorkCount * WorkSize;
private const int FlagCount = EventFlagStart + EventFlagCount;
// Breakdown!
private const int ZoneWorkCount = 0x20; // 32
private const int SystemWorkCount = 0x80; // 128
private const int SceneWorkCount = 0x200; // 512
private const int EventWorkCount = 0x100; // 256
// private const int UnusedWorkCount = 72;
private const int ZoneWorkStart = 0;
private const int SystemWorkStart = ZoneWorkStart + ZoneWorkCount;
private const int SceneWorkStart = SystemWorkStart + SystemWorkCount;
private const int EventWorkStart = SceneWorkStart + SceneWorkCount;
private const int ZoneFlagCount = 0x80; // 128
private const int SystemFlagCount = 0x200; // 512
private const int VanishFlagCount = 0x600; // 1536
private const int EventFlagCount = 0x7C0; // 1984
private const int ZoneFlagStart = 0;
private const int SystemFlagStart = ZoneFlagStart + ZoneFlagCount;
private const int VanishFlagStart = SystemFlagStart + SystemFlagCount;
private const int EventFlagStart = VanishFlagStart + VanishFlagCount;
public int MaxFlag => FlagCount;
public int MaxWork => WorkCount;
public int GetWork(int index) => BitConverter.ToInt32(Data, Offset + (index * WorkSize));
public void SetWork(int index, int value) => BitConverter.GetBytes(value).CopyTo(Data, Offset + (index * WorkSize));
public int GetWork(EventVarType type, int index) => GetWork(GetWorkRawIndex(type, index));
public void SetWork(EventVarType type, int index, int value) => SetWork(GetWorkRawIndex(type, index), value);
public bool GetFlag(EventVarType type, int index) => GetFlag(GetFlagRawIndex(type, index));
public void SetFlag(EventVarType type, int index, bool value = true) => SetFlag(GetFlagRawIndex(type, index), value);
public int GetFlagRawIndex(EventVarType type, int index)
{
int max = GetFlagCount(type);
if ((uint)index > max)
throw new ArgumentException(nameof(index));
var start = GetFlagStart(type);
return start + index;
}
public int GetWorkRawIndex(EventVarType type, int index)
{
int max = GetWorkCount(type);
if ((uint)index > max)
throw new ArgumentException(nameof(index));
var start = GetWorkStart(type);
return start + index;
}
public bool GetFlag(int index)
{
var offset = Offset + FlagStart + (index >> 3);
var current = Data[offset];
return (current & (1 << (index & 7))) != 0;
}
public void SetFlag(int index, bool value = true)
{
var offset = Offset + FlagStart + (index >> 3);
var bit = 1 << (index & 7);
if (value)
Data[offset] |= (byte)bit;
else
Data[offset] &= (byte)~bit;
}
public EventVarType GetFlagType(int index, out int subIndex)
{
subIndex = index;
if (index < ZoneFlagCount)
return EventVarType.Zone;
subIndex -= ZoneFlagCount;
if (subIndex < SystemFlagCount)
return EventVarType.System;
subIndex -= SystemFlagCount;
if (subIndex < VanishFlagCount)
return EventVarType.Vanish;
subIndex -= VanishFlagCount;
if (subIndex < EventFlagCount)
return EventVarType.Event;
throw new ArgumentException(nameof(index));
}
public EventVarType GetWorkType(int index, out int subIndex)
{
subIndex = index;
if (subIndex < ZoneWorkCount)
return EventVarType.Zone;
subIndex -= ZoneWorkCount;
if (subIndex < SystemWorkCount)
return EventVarType.System;
subIndex -= SystemWorkCount;
if (subIndex < SceneWorkCount)
return EventVarType.Scene;
subIndex -= SceneWorkCount;
if (subIndex < EventWorkCount)
return EventVarType.Event;
throw new ArgumentException(nameof(index));
}
private int GetFlagStart(EventVarType type)
{
return type switch
{
EventVarType.Zone => ZoneFlagStart,
EventVarType.System => SystemFlagStart,
EventVarType.Vanish => VanishFlagStart,
EventVarType.Event => EventFlagStart,
_ => throw new ArgumentException(nameof(type))
};
}
private int GetWorkStart(EventVarType type)
{
return type switch
{
EventVarType.Zone => ZoneWorkStart,
EventVarType.System => SystemWorkStart,
EventVarType.Scene => SceneWorkStart,
EventVarType.Event => EventWorkStart,
_ => throw new ArgumentException(nameof(type))
};
}
private int GetFlagCount(EventVarType type)
{
return type switch
{
EventVarType.Zone => ZoneFlagCount,
EventVarType.System => SystemFlagCount,
EventVarType.Vanish => VanishFlagCount,
EventVarType.Event => EventFlagCount,
_ => throw new ArgumentException(nameof(type))
};
}
private int GetWorkCount(EventVarType type)
{
return type switch
{
EventVarType.Zone => ZoneWorkCount,
EventVarType.System => SystemWorkCount,
EventVarType.Scene => SceneWorkCount,
EventVarType.Event => EventWorkCount,
_ => throw new ArgumentException(nameof(type))
};
}
}
}