Extract y2k datetime logic, also wardrobe tweak

swsh gonna have wardrobe, so rename class and relocate some logic in for
better docs
This commit is contained in:
Kurt
2019-09-15 22:12:32 -07:00
parent d26e294e58
commit b9246ece37
5 changed files with 105 additions and 110 deletions

View File

@@ -9,27 +9,53 @@ public sealed class FashionBlock7 : SaveBlock
private const int FashionLength = 0x1A08;
public sealed class FashionItem
// Every fashion item is 2 bits, New Flag (high) & Owned Flag (low)
public sealed class FashionItem7
{
public bool IsOwned { get; set; }
public bool IsNew { get; set; }
public FashionItem7(byte b)
{
IsOwned = (b & 1) != 0;
IsNew = (b & 2) != 0;
}
public byte Value => (byte)((IsOwned ? 1 : 0) | (IsNew ? 2 : 0));
}
public FashionItem[] Wardrobe
public FashionItem7[] Wardrobe
{
get
{
var data = SAV.GetData(Offset, 0x5A8);
return data.Select(b => new FashionItem { IsOwned = (b & 1) != 0, IsNew = (b & 2) != 0 }).ToArray();
return data.Select(b => new FashionItem7(b)).ToArray();
}
set
{
if (value.Length != 0x5A8)
throw new ArgumentOutOfRangeException($"Unexpected size: 0x{value.Length:X}");
SAV.SetData(value.Select(t => (byte)((t.IsOwned ? 1 : 0) | (t.IsNew ? 2 : 0))).ToArray(), Offset);
SAV.SetData(value.Select(z => z.Value).ToArray(), Offset);
}
}
public void Clear() => Array.Clear(Data, Offset, FashionLength);
/// <summary>
/// Resets the fashion unlocks to default values.
/// </summary>
public void Reset()
{
var offsetList = SAV is SAV7USUM
? (SAV.Gender == 0
? new[] { 0x03A, 0x109, 0x1DA, 0x305, 0x3D9, 0x4B1, 0x584 } // M
: new[] { 0x05E, 0x208, 0x264, 0x395, 0x3B4, 0x4F9, 0x5A8 }) // F
: (SAV.Gender == 0
? new[] { 0x000, 0x0FB, 0x124, 0x28F, 0x3B4, 0x452, 0x517 } // M
: new[] { 0x000, 0x100, 0x223, 0x288, 0x3B4, 0x452, 0x517 }); // F
foreach (var ofs in offsetList)
SAV.Data[Offset + ofs] = 3; // owned | new
}
}
}

View File

@@ -27,5 +27,33 @@ public static bool IsDateValid(uint year, uint month, uint day)
{
return year < int.MaxValue && month < int.MaxValue && day < int.MaxValue && IsDateValid((int)year, (int)month, (int)day);
}
private static readonly DateTime Epoch2000 = new DateTime(2000, 1, 1);
private const int spd = 86400; // seconds per day
public static int GetSecondsFrom2000(DateTime date, DateTime time)
{
int seconds = (int)(date - Epoch2000).TotalSeconds;
seconds -= seconds % spd;
seconds += (int)(time - Epoch2000).TotalSeconds;
return seconds;
}
public static void GetDateTime2000(uint seconds, out DateTime date, out DateTime time)
{
date = Epoch2000.AddSeconds(seconds);
time = Epoch2000.AddSeconds(seconds % spd);
}
public static string ConvertDateValueToString(int value, int secondsBias = -1)
{
string tip = string.Empty;
if (value >= spd)
tip += (value / spd) + "d ";
tip += new DateTime(0).AddSeconds(value).ToString("HH:mm:ss");
if (secondsBias >= 0)
tip += Environment.NewLine + $"Date: {Epoch2000.AddSeconds(value + secondsBias)}";
return tip;
}
}
}

View File

@@ -53,10 +53,12 @@ public SAV_Trainer(SaveFile sav)
L_Style.Visible = TB_Style.Visible = SAV is SAV6XY;
if (!(SAV is SAV6XY))
TC_Editor.TabPages.Remove(Tab_Appearance);
if (SAV is SAV6AODemo)
{
TC_Editor.TabPages.Remove(Tab_Multiplayer);
if (SAV is SAV6AODemo)
TC_Editor.TabPages.Remove(Tab_Maison);
}
GetComboBoxes();
GetTextBoxes();
@@ -68,7 +70,7 @@ public SAV_Trainer(SaveFile sav)
CHK_MegaRayquazaUnlocked.Checked = status.IsMegaRayquazaUnlocked;
}
private readonly bool editing = true;
private readonly bool editing;
private readonly ToolTip Tip1 = new ToolTip(), Tip2 = new ToolTip();
private readonly MaskedTextBox[] MaisonRecords;
private readonly CheckBox[] cba;
@@ -217,11 +219,13 @@ private void GetTextBoxes()
L_LastSaved.Visible = CAL_LastSavedDate.Visible = CAL_LastSavedTime.Visible = false;
}
var epoch = new DateTime(2000, 1, 1);
CAL_AdventureStartDate.Value = epoch.AddSeconds(SAV.SecondsToStart);
CAL_AdventureStartTime.Value = epoch.AddSeconds(SAV.SecondsToStart % 86400);
CAL_HoFDate.Value = epoch.AddSeconds(SAV.SecondsToFame);
CAL_HoFTime.Value = epoch.AddSeconds(SAV.SecondsToFame % 86400);
Util.GetDateTime2000(SAV.SecondsToStart, out var date, out var time);
CAL_AdventureStartDate.Value = date;
CAL_AdventureStartTime.Value = time;
Util.GetDateTime2000(SAV.SecondsToStart, out date, out time);
CAL_HoFDate.Value = date;
CAL_HoFTime.Value = time;
}
private void Save()
@@ -295,15 +299,8 @@ private void Save()
// Vivillon
SAV.Vivillon = CB_Vivillon.SelectedIndex;
uint seconds = (uint)(CAL_AdventureStartDate.Value - new DateTime(2000, 1, 1)).TotalSeconds;
seconds -= seconds%86400;
seconds += (uint)(CAL_AdventureStartTime.Value - new DateTime(2000, 1, 1)).TotalSeconds;
SAV.SecondsToStart = seconds;
uint fame = (uint)(CAL_HoFDate.Value - new DateTime(2000, 1, 1)).TotalSeconds;
fame -= fame % 86400;
fame += (uint)(CAL_HoFTime.Value - new DateTime(2000, 1, 1)).TotalSeconds;
SAV.SecondsToFame = fame;
SAV.SecondsToStart = (uint)Util.GetSecondsFrom2000(CAL_AdventureStartDate.Value, CAL_AdventureStartTime.Value);
SAV.SecondsToFame = (uint)Util.GetSecondsFrom2000(CAL_HoFDate.Value, CAL_HoFTime.Value);
if (SAV.Played.LastSavedDate.HasValue)
SAV.Played.LastSavedDate = new DateTime(CAL_LastSavedDate.Value.Year, CAL_LastSavedDate.Value.Month, CAL_LastSavedDate.Value.Day, CAL_LastSavedTime.Value.Hour, CAL_LastSavedTime.Value.Minute, 0);
@@ -360,8 +357,10 @@ private void Change255(object sender, EventArgs e)
private void ChangeFFFF(object sender, EventArgs e)
{
MaskedTextBox box = (MaskedTextBox)sender;
if (box.Text.Length == 0) box.Text = "0";
if (Util.ToInt32(box.Text) > 65535) box.Text = "65535";
if (box.Text.Length == 0)
box.Text = "0";
else if (Util.ToInt32(box.Text) > 65535)
box.Text = "65535";
}
private void GiveAllAccessories(object sender, EventArgs e)
@@ -401,26 +400,11 @@ private string UpdateTip(int index)
switch (index)
{
case 2: // Storyline Completed Time
var epoch = new DateTime(2000, 1, 1);
int seconds = (int)(CAL_AdventureStartDate.Value - epoch).TotalSeconds;
seconds -= seconds % 86400;
seconds += (int)(CAL_AdventureStartTime.Value - epoch).TotalSeconds;
return ConvertDateValueToString(SAV.GetRecord(index), seconds);
var seconds = Util.GetSecondsFrom2000(CAL_AdventureStartDate.Value, CAL_AdventureStartTime.Value);
return Util.ConvertDateValueToString(SAV.GetRecord(index), seconds);
default:
return null;
}
}
private static string ConvertDateValueToString(int value, int secondsBias = -1)
{
const int spd = 86400; // seconds per day
string tip = string.Empty;
if (value >= spd)
tip += (value / spd) + "d ";
tip += new DateTime(0).AddSeconds(value).ToString("HH:mm:ss");
if (secondsBias >= 0)
tip += Environment.NewLine + $"Date: {new DateTime(2000, 1, 1).AddSeconds(value + secondsBias)}";
return tip;
}
}
}

View File

@@ -111,13 +111,13 @@ private void GetTextBoxes()
CB_Region.SelectedValue = SAV.SubRegion;
CB_3DSReg.SelectedValue = SAV.ConsoleRegion;
CB_Language.SelectedValue = SAV.Language;
var time = SAV.GameTime.AlolaTime;
if (time == 0)
time = 24 * 60 * 60; // Patch up any bad times from previous program versions.
if (time == 9_999_999)
var timeA = SAV.GameTime.AlolaTime;
if (timeA == 0)
timeA = 24 * 60 * 60; // Patch up any bad times from previous program versions.
if (timeA == 9_999_999)
CB_AlolaTime.Enabled = false; // alola time doesn't exist yet
else
CB_AlolaTime.SelectedValue = (int)time;
CB_AlolaTime.SelectedValue = (int)timeA;
if (CB_AlolaTime.SelectedValue == null)
CB_AlolaTime.Enabled = false;
@@ -147,11 +147,13 @@ private void GetTextBoxes()
L_LastSaved.Visible = CAL_LastSavedDate.Visible = CAL_LastSavedTime.Visible = false;
}
var epoch = new DateTime(2000, 1, 1);
CAL_AdventureStartDate.Value = epoch.AddSeconds(SAV.SecondsToStart);
CAL_AdventureStartTime.Value = epoch.AddSeconds(SAV.SecondsToStart % 86400);
CAL_HoFDate.Value = epoch.AddSeconds(SAV.SecondsToFame);
CAL_HoFTime.Value = epoch.AddSeconds(SAV.SecondsToFame % 86400);
Util.GetDateTime2000(SAV.SecondsToStart, out var date, out var time);
CAL_AdventureStartDate.Value = date;
CAL_AdventureStartTime.Value = time;
Util.GetDateTime2000(SAV.SecondsToStart, out date, out time);
CAL_HoFDate.Value = date;
CAL_HoFTime.Value = time;
NUD_BP.Value = Math.Min(NUD_BP.Maximum, SAV.MiscBlock.BP);
NUD_FC.Value = Math.Min(NUD_FC.Maximum, SAV.Festa.FestaCoins);
@@ -349,16 +351,8 @@ private void SaveTrainerInfo()
SAV.PlayedMinutes = ushort.Parse(MT_Minutes.Text)%60;
SAV.PlayedSeconds = ushort.Parse(MT_Seconds.Text)%60;
var epoch = new DateTime(2000, 1, 1);
uint seconds = (uint)(CAL_AdventureStartDate.Value - epoch).TotalSeconds;
seconds -= seconds%86400;
seconds += (uint)(CAL_AdventureStartTime.Value - epoch).TotalSeconds;
SAV.SecondsToStart = seconds;
uint fame = (uint)(CAL_HoFDate.Value - epoch).TotalSeconds;
fame -= fame % 86400;
fame += (uint)(CAL_HoFTime.Value - epoch).TotalSeconds;
SAV.SecondsToFame = fame;
SAV.SecondsToStart = (uint)Util.GetSecondsFrom2000(CAL_AdventureStartDate.Value, CAL_AdventureStartTime.Value);
SAV.SecondsToFame = (uint)Util.GetSecondsFrom2000(CAL_HoFDate.Value, CAL_HoFTime.Value);
if (SAV.Played.LastSavedDate.HasValue)
SAV.Played.LastSavedDate = new DateTime(CAL_LastSavedDate.Value.Year, CAL_LastSavedDate.Value.Month, CAL_LastSavedDate.Value.Day, CAL_LastSavedTime.Value.Hour, CAL_LastSavedTime.Value.Minute, 0);
@@ -505,13 +499,6 @@ private void Change255(object sender, EventArgs e)
if (Util.ToInt32(box.Text) > 255) box.Text = "255";
}
private void ChangeFFFF(object sender, EventArgs e)
{
MaskedTextBox box = (MaskedTextBox)sender;
if (box.Text.Length == 0) box.Text = "0";
if (Util.ToInt32(box.Text) > 65535) box.Text = "65535";
}
private void ChangeMapValue(object sender, EventArgs e)
{
if (!Loading)
@@ -535,35 +522,25 @@ private void B_Fashion_Click(object sender, EventArgs e)
SAV.FashionBlock.Clear();
// Write Payload
// Every fashion item is 2 bits, New Flag (high) & Owned Flag (low)
switch (CB_Fashion.SelectedIndex)
{
case 0: // Base Fashion
{
var list = SAV is SAV7USUM
? (SAV.Gender == 0
? new[] {0x03A, 0x109, 0x1DA, 0x305, 0x3D9, 0x4B1, 0x584} // M
: new[] {0x05E, 0x208, 0x264, 0x395, 0x3B4, 0x4F9, 0x5A8}) // F
: (SAV.Gender == 0
? new[] {0x000, 0x0FB, 0x124, 0x28F, 0x3B4, 0x452, 0x517} // M
: new[] {0x000, 0x100, 0x223, 0x288, 0x3B4, 0x452, 0x517}); // F
foreach (var ofs in list)
SAV.Data[SAV.Fashion + ofs] = 3;
SAV.FashionBlock.Reset();
break;
}
case 1: // Full Legal
byte[] data1 = SAV is SAV7USUM
? SAV.Gender == 0 ? Properties.Resources.fashion_m_uu : Properties.Resources.fashion_f_uu
: SAV.Gender == 0 ? Properties.Resources.fashion_m_sm : Properties.Resources.fashion_f_sm;
data1.CopyTo(SAV.Data, SAV.Fashion);
SAV.SetData(data1, SAV.Fashion);
break;
case 2: // Everything
byte[] data2 = SAV is SAV7USUM
? SAV.Gender == 0 ? Properties.Resources.fashion_m_uu_illegal : Properties.Resources.fashion_f_uu_illegal
: SAV.Gender == 0 ? Properties.Resources.fashion_m_sm_illegal : Properties.Resources.fashion_f_sm_illegal;
data2.CopyTo(SAV.Data, SAV.Fashion);
SAV.SetData(data2, SAV.Fashion);
break;
default:
return;
@@ -576,27 +553,13 @@ private string UpdateTip(int index)
switch (index)
{
case 2: // Storyline Completed Time
int seconds = (int)(CAL_AdventureStartDate.Value - new DateTime(2000, 1, 1)).TotalSeconds;
seconds -= seconds % 86400;
seconds += (int)(CAL_AdventureStartTime.Value - new DateTime(2000, 1, 1)).TotalSeconds;
return ConvertDateValueToString(SAV.GetRecord(index), seconds);
var seconds = Util.GetSecondsFrom2000(CAL_AdventureStartDate.Value, CAL_AdventureStartTime.Value);
return Util.ConvertDateValueToString(SAV.GetRecord(index), seconds);
default:
return null;
}
}
private static string ConvertDateValueToString(int value, int secondsBias = -1)
{
const int spd = 86400; // seconds per day
string tip = string.Empty;
if (value >= spd)
tip += (value / spd) + "d ";
tip += new DateTime(0).AddSeconds(value).ToString("HH:mm:ss");
if (secondsBias >= 0)
tip += Environment.NewLine + $"Date: {new DateTime(2000, 1, 1).AddSeconds(value + secondsBias)}";
return tip;
}
private void UpdateBattleStyle(object sender, EventArgs e)
{
if (CB_BallThrowTypeListMode.SelectedIndex == 0)

View File

@@ -151,10 +151,13 @@ public SAV_SimpleTrainer(SaveFile sav)
cba[i].Checked = (badgeval & 1 << i) != 0;
}
CAL_HoFDate.Value = new DateTime(2000, 1, 1).AddSeconds(SAV.SecondsToFame);
CAL_HoFTime.Value = new DateTime(2000, 1, 1).AddSeconds(SAV.SecondsToFame % 86400);
CAL_AdventureStartDate.Value = new DateTime(2000, 1, 1).AddSeconds(SAV.SecondsToStart);
CAL_AdventureStartTime.Value = new DateTime(2000, 1, 1).AddSeconds(SAV.SecondsToStart % 86400);
Util.GetDateTime2000(SAV.SecondsToStart, out var date, out var time);
CAL_AdventureStartDate.Value = date;
CAL_AdventureStartTime.Value = time;
Util.GetDateTime2000(SAV.SecondsToStart, out date, out time);
CAL_HoFDate.Value = date;
CAL_HoFTime.Value = time;
Loading = false;
}
@@ -252,8 +255,8 @@ private void B_Save_Click(object sender, EventArgs e)
s.BattleSubwayBlock.BP = (ushort)Math.Min(Util.ToUInt32(MT_Coins.Text), SAV.MaxCoins);
}
SAV.SecondsToStart = GetSeconds(CAL_AdventureStartDate, CAL_AdventureStartTime);
SAV.SecondsToFame = GetSeconds(CAL_HoFDate, CAL_HoFTime);
SAV.SecondsToStart = (uint)Util.GetSecondsFrom2000(CAL_AdventureStartDate.Value, CAL_AdventureStartTime.Value);
SAV.SecondsToFame = (uint)Util.GetSecondsFrom2000(CAL_HoFDate.Value, CAL_HoFTime.Value);
Origin.CopyChangesFrom(SAV);
Close();
@@ -264,15 +267,6 @@ private void B_Cancel_Click(object sender, EventArgs e)
Close();
}
private static uint GetSeconds(DateTimePicker date, DateTimePicker time)
{
var epoch = new DateTime(2000, 1, 1);
uint val = (uint)(date.Value - epoch).TotalSeconds;
val -= val % 86400;
val += (uint)(time.Value - epoch).TotalSeconds;
return val;
}
private void ChangeMapValue(object sender, EventArgs e)
{
if (!Loading)