* New Buried Item Logic. Much more clean and organized. No more hacky code.

* Fixed Wild World acre database loading

* Fixed a few misc bugs & crashes
This commit is contained in:
Cuyler36 2018-11-12 02:10:10 -05:00
parent 13dcd5f29d
commit b43ade5e29
9 changed files with 313 additions and 229 deletions

View file

@ -17,16 +17,23 @@ public static (byte, byte) GetNibbles(this byte b)
}
/// <summary>
/// Returns the bit from a specified index of a byte.
/// Returns the bit from a specified index of a <see cref="ValueType"/>.
/// </summary>
/// <param name="b">The input byte</param>
/// <param name="input">The input <see cref="ValueType"/></param>
/// <param name="index">The bit to retrieve</param>
/// <param name="reverse">Sets if the index should be reversed</param>
/// <returns>The requested bit</returns>
public static byte GetBit(this byte b, int index, bool reverse = false)
public static T GetBit<T>(this T input, int index, bool reverse = false)
{
if (index < 0 || index > 7) throw new ArgumentException("Index is expected to be in the range of 0 - 7!");
return (byte)((reverse ? b >> (7 - index) : b >> index) & 1);
if (!(input is ValueType))
throw new ArgumentException($"{nameof(input)} must be a ValueType!");
var highBit = Marshal.SizeOf(input) * 8 - 1;
if (index < 0 || index > highBit)
throw new ArgumentException($"Bit index was out of range! Expected range: 0 - {highBit}");
dynamic obj = input;
return (T) ((reverse ? obj >> (highBit - index) : obj >> index) & 1);
}
/// <summary>
@ -52,22 +59,32 @@ public static ICollection<byte> GetBits(this ValueType input)
/// <summary>
/// Sets a specified bit of a byte.
/// </summary>
/// <param name="b">The byte to modify</param>
/// <param name="input">The byte to modify</param>
/// <param name="index">The index of the bit to set</param>
/// <param name="set">Should the bit be set or not</param>
/// <param name="reverse">Is the index reversed (e.g. 0 = topmost bit)</param>
public static void SetBit(ref this byte b, int index, bool set, bool reverse = false)
public static T SetBit<T>(this T input, int index, bool set, bool reverse = false)
{
if (index < 0 || index > 7) throw new ArgumentException("Index is expected to be in the range of 0 - 7!");
var bitmask = 1 << (reverse ? 7 - index : index);
if (!(input is ValueType))
throw new ArgumentException($"{nameof(input)} must be a ValueType!");
var highBit = Marshal.SizeOf(input) * 8 - 1;
if (index < 0 || index > highBit)
throw new ArgumentException($"Bit index was out of range! Expected range: 0 - {highBit}");
var bitmask = 1 << (reverse ? highBit - index : index);
dynamic obj = input;
if (set)
{
b |= (byte) bitmask;
obj |= bitmask;
}
else
{
b &= (byte) ~bitmask;
obj &= ~bitmask;
}
return (T) obj;
}
/// <summary>

View file

@ -929,14 +929,21 @@ public static Dictionary<string, List<byte>> GetFiledAcreData(SaveType saveType,
StreamReader contents;
var acreDbLocation = PathUtility.GetResourcesDirectory();
if (saveType == SaveType.WildWorld)
acreDbLocation += "WW_Acres_" + language + ".txt";
try { contents = File.OpenText(acreDbLocation); }
{
acreDbLocation = Path.Combine(acreDbLocation, $"WW_Acres_{language}.txt");
}
try
{
contents = File.OpenText(acreDbLocation);
}
catch (Exception e)
{
DebugUtility.DebugManagerInstance.WriteLine(
$"An error occured opening acre database file:\n\"{acreDbLocation}\"\nError Info:\n{e.Message}", DebugLevel.Error);
return null;
}
var filedList = new Dictionary<string, List<byte>>();
string line;
var currentAcreType = "Unsorted";

View file

@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using ACSE.Core.Debug;
using ACSE.Core.Items;
using ACSE.Core.Saves;
@ -31,18 +32,19 @@ public Acre(byte acreId, int position)
public class WorldAcre : Acre
{
public WorldItem[] AcreItems = new WorldItem[16 * 16];
public int TownIndex;
public WorldAcre(ushort acreId, int position, ushort[] items = null, byte[] buriedItemData = null,
SaveType saveType = SaveType.AnimalCrossing, uint[] nlItems = null, int townPosition = -1) : base(acreId,
position)
public WorldAcre(ushort acreId, int position, ushort[] items = null, uint[] nlItems = null,
int townPosition = -1) : base(acreId, position)
{
TownIndex = townPosition;
if (items != null)
{
for (var i = 0; i < 256; i++)
{
AcreItems[i] = new WorldItem(items[i], i);
if (buriedItemData != null)
SetBuried(AcreItems[i], townPosition == -1 ? position : townPosition, buriedItemData, saveType);
AcreItems[i].Buried = IsItemBuried(AcreItems[i], Save.SaveInstance.SaveGeneration);
}
}
else if (nlItems != null)
@ -50,66 +52,84 @@ public WorldAcre(ushort acreId, int position, ushort[] items = null, byte[] buri
for (var i = 0; i < 256; i++)
{
AcreItems[i] = new WorldItem(nlItems[i], i);
//add buried logic
}
}
}
public WorldAcre(ushort acreId, int position) : base(acreId, position) { }
public WorldAcre(ushort acreId, int position, uint[] items = null, byte[] buriedItemData = null, SaveType saveType = SaveType.AnimalCrossing)
: this(acreId, position, null, null, saveType, items) { }
public WorldAcre(ushort acreId, int position, uint[] items = null) : this(acreId, position, null, items)
{ }
public WorldAcre(ushort acreId, int position, WorldItem[] items, byte[] buriedItemData = null,
SaveType saveType = SaveType.AnimalCrossing, int townPosition = -1) : base(acreId, position)
public WorldAcre(ushort acreId, int position, WorldItem[] items, int townPosition = -1) : base(acreId, position)
{
AcreItems = items;
if (buriedItemData == null || townPosition <= -1) return;
if (townPosition <= -1) return;
for (var i = 0; i < 256; i++)
SetBuried(AcreItems[i], townPosition, buriedItemData, saveType);
{
AcreItems[i].Buried = IsItemBuried(AcreItems[i], Save.SaveInstance.SaveGeneration);
}
}
//TODO: Change BuriedData from byte[] to ushort[] and use updated code
private static int GetBuriedDataLocation(WorldItem item, int acre, SaveType saveType)
public bool IsItemBuried(Item item, SaveGeneration generation)
{
if (item == null) return -1;
var worldPosition = 0;
switch (saveType)
if (item == null || !AcreItems.Contains(item)) return false;
var itemIdx = Array.IndexOf(AcreItems, item);
if (itemIdx < 0 || itemIdx > 255) return false;
int offset;
switch (generation)
{
//15 - item.Location.X because it's stored as a ushort in memory w/ reversed endianess
case SaveType.AnimalCrossing:
case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus:
case SaveType.CityFolk:
worldPosition = (acre * 256) + (15 - item.Location.X) + item.Location.Y * 16;
case SaveGeneration.N64:
case SaveGeneration.GCN:
case SaveGeneration.iQue:
case SaveGeneration.Wii:
offset = Save.SaveInstance.SaveInfo.SaveOffsets.BuriedData + (TownIndex * 16 + itemIdx / 16) * 2;
return Save.SaveInstance.ReadUInt16(offset, true, true).GetBit(itemIdx % 16) == 1;
case SaveGeneration.NDS:
offset = Save.SaveInstance.SaveInfo.SaveOffsets.BuriedData + (Index * 256 + itemIdx) / 8;
return Save.SaveInstance.ReadByte(offset, true).GetBit(itemIdx % 8) == 1;
case SaveGeneration.N3DS:
return (item.Flag1 & 0x80) == 0x80;
}
return false;
}
public bool SetItemBuried(Item item, bool buried, SaveGeneration generation)
{
if (item == null || !AcreItems.Contains(item)) return false;
var itemIdx = Array.IndexOf(AcreItems, item);
if (itemIdx < 0 || itemIdx > 255) return false;
int offset;
switch (generation)
{
case SaveGeneration.N64:
case SaveGeneration.GCN:
case SaveGeneration.iQue:
case SaveGeneration.Wii:
offset = Save.SaveInstance.SaveInfo.SaveOffsets.BuriedData + (TownIndex * 16 + itemIdx / 16) * 2;
Save.SaveInstance.Write(offset,
Save.SaveInstance.ReadUInt16(offset, true, true).SetBit(itemIdx % 16, buried), true, true);
break;
case SaveType.WildWorld:
worldPosition = (acre * 256) + item.Index;
case SaveGeneration.NDS:
offset = Save.SaveInstance.SaveInfo.SaveOffsets.BuriedData + (Index * 256 + itemIdx) / 8;
Save.SaveInstance.Write(offset,
Save.SaveInstance.ReadByte(offset, true).SetBit(itemIdx % 8, buried), true);
break;
case SaveGeneration.N3DS:
item.Flag1 &= 0x7F;
break;
}
return worldPosition / 8;
}
public void SetBuriedInMemory(WorldItem item, int acre, byte[] buriedItemData, bool buried, SaveType saveType)
{
if (saveType == SaveType.NewLeaf || saveType == SaveType.WelcomeAmiibo) return;
var buriedLocation = GetBuriedDataLocation(item, acre, saveType);
if (buriedLocation > -1)
{
buriedItemData[buriedLocation].SetBit(item.Location.X % 8, buried);
item.Buried = buriedItemData[buriedLocation].GetBit(item.Location.X % 8) == 1;
}
else
item.Buried = false;
}
private static void SetBuried(WorldItem item, int acre, byte[] buriedItemData, SaveType saveType)
{
var burriedDataOffset = GetBuriedDataLocation(item, acre, saveType);
if (burriedDataOffset > -1 && burriedDataOffset < buriedItemData.Length)
{
item.Buried = buriedItemData[burriedDataOffset].GetBit(item.Location.X % 8) == 1;
}
return IsItemBuried(item, generation);
}
/// <summary>

View file

@ -165,7 +165,7 @@ public void SetBuriedInMemory(WorldItem item, int acre, byte[] buriedItemData, b
var buriedLocation = GetBuriedDataLocation(item, acre, saveType);
if (buriedLocation > -1)
{
buriedItemData[buriedLocation].SetBit(item.Location.X % 8, buried);
buriedItemData[buriedLocation] = buriedItemData[buriedLocation].SetBit(item.Location.X % 8, buried);
item.Buried = buriedItemData[buriedLocation].GetBit(item.Location.X % 8) == 1;
}
else

View file

@ -70,6 +70,9 @@
<DependentUpon>AboutBox.cs</DependentUpon>
</Compile>
<Compile Include="Backups\Backup.cs" />
<Compile Include="Controls\AcreItemEditor.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Controls\BadgeControl.cs">
<SubType>Component</SubType>
</Compile>

View file

@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ACSE.Core.Items;
using ACSE.Core.Town.Acres;
namespace ACSE.WinForms.Controls
{
public sealed class AcreItemEditor : ItemEditor
{
/// <summary>
/// The acre whose items are being edited.
/// </summary>
public WorldAcre Acre { get; private set; }
/// <summary>
/// The <see cref="WorldItem"/>s associated with the acre.
/// </summary>
public new WorldItem[] Items => Acre?.AcreItems;
public AcreItemEditor(MainForm form, WorldItem Items, int itemsPerRow)
{
}
}
}

View file

@ -47,6 +47,11 @@ public StalkMarketEditor(Save saveData)
_offset = saveData.SaveDataStartOffset + 0x20480;
_trendOffset = _offset + 0xE;
break;
case SaveType.DoubutsuNoMoriEPlus:
case SaveType.AnimalForestEPlus:
_offset = saveData.SaveDataStartOffset + 0x223C8;
_trendOffset = _offset + 0xE;
break;
case SaveType.NewLeaf:
Days = 6;
_offset = saveData.SaveDataStartOffset + 0x6535C;

View file

@ -33,13 +33,11 @@ private void InitializeComponent()
this.components = new System.ComponentModel.Container();
System.Windows.Forms.TabPage patternsTab;
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.patternNameTextBox = new System.Windows.Forms.PlaceholderTextBox();
this.paletteColorSelectedPictureBox = new System.Windows.Forms.PictureBox();
this.paletteIndexLabel = new System.Windows.Forms.Label();
this.palettePreviousButton = new System.Windows.Forms.Button();
this.paletteNextButton = new System.Windows.Forms.Button();
this.patternEditorPanel = new System.Windows.Forms.Panel();
this.patternEditorPictureBox = new ACSE.WinForms.Controls.PictureBoxWithInterpolationMode();
this.patternEditorPreviewPanel = new System.Windows.Forms.Panel();
this.patternGroupTabControl = new System.Windows.Forms.TabControl();
this.player1Tab = new System.Windows.Forms.TabPage();
@ -271,14 +269,15 @@ private void InitializeComponent()
this.loadingPanel = new System.Windows.Forms.Panel();
this.label45 = new System.Windows.Forms.Label();
this.infoTip = new System.Windows.Forms.ToolTip(this.components);
this.itemIdTextBox = new System.Windows.Forms.PlaceholderTextBox();
this.itemIdLabel = new System.Windows.Forms.Label();
this.StatusLabel = new System.Windows.Forms.TextBox();
this.itemIdTextBox = new System.Windows.Forms.PlaceholderTextBox();
this.patternNameTextBox = new System.Windows.Forms.PlaceholderTextBox();
this.patternEditorPictureBox = new ACSE.WinForms.Controls.PictureBoxWithInterpolationMode();
patternsTab = new System.Windows.Forms.TabPage();
patternsTab.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.paletteColorSelectedPictureBox)).BeginInit();
this.patternEditorPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.patternEditorPictureBox)).BeginInit();
this.patternGroupTabControl.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.paletteSelectionPictureBox)).BeginInit();
this.menuStrip1.SuspendLayout();
@ -315,6 +314,7 @@ private void InitializeComponent()
this.pictureContextMenu.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.acreHeightTrackBar)).BeginInit();
this.loadingPanel.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.patternEditorPictureBox)).BeginInit();
this.SuspendLayout();
//
// patternsTab
@ -335,18 +335,6 @@ private void InitializeComponent()
patternsTab.Text = "Patterns";
patternsTab.UseVisualStyleBackColor = true;
//
// patternNameTextBox
//
this.patternNameTextBox.Anchor = System.Windows.Forms.AnchorStyles.None;
this.patternNameTextBox.Location = new System.Drawing.Point(415, 538);
this.patternNameTextBox.MaxLength = 16;
this.patternNameTextBox.Name = "patternNameTextBox";
this.patternNameTextBox.PlaceholderText = "Pattern Name";
this.patternNameTextBox.PlaceholderTextColor = System.Drawing.Color.Gray;
this.patternNameTextBox.Size = new System.Drawing.Size(100, 20);
this.patternNameTextBox.TabIndex = 0;
this.patternNameTextBox.TextChanged += new System.EventHandler(this.PatternEditorNameBox_TextChanged);
//
// paletteColorSelectedPictureBox
//
this.paletteColorSelectedPictureBox.Anchor = System.Windows.Forms.AnchorStyles.None;
@ -399,23 +387,6 @@ private void InitializeComponent()
this.patternEditorPanel.Size = new System.Drawing.Size(513, 513);
this.patternEditorPanel.TabIndex = 16;
//
// patternEditorPictureBox
//
this.patternEditorPictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.patternEditorPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.patternEditorPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
this.patternEditorPictureBox.Location = new System.Drawing.Point(0, 0);
this.patternEditorPictureBox.Name = "patternEditorPictureBox";
this.patternEditorPictureBox.Size = new System.Drawing.Size(513, 513);
this.patternEditorPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.patternEditorPictureBox.TabIndex = 0;
this.patternEditorPictureBox.TabStop = false;
this.patternEditorPictureBox.UseInternalInterpolationSetting = false;
this.patternEditorPictureBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseDown);
this.patternEditorPictureBox.MouseLeave += new System.EventHandler(this.PatternEditorBoxMouseLeave);
this.patternEditorPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseMove);
this.patternEditorPictureBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseUp);
//
// patternEditorPreviewPanel
//
this.patternEditorPreviewPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
@ -2797,21 +2768,6 @@ private void InitializeComponent()
this.label45.TabIndex = 15;
this.label45.Text = "Loading...";
//
// itemIdTextBox
//
this.itemIdTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.itemIdTextBox.Enabled = false;
this.itemIdTextBox.Location = new System.Drawing.Point(132, 620);
this.itemIdTextBox.Name = "itemIdTextBox";
this.itemIdTextBox.PlaceholderText = "Item ID";
this.itemIdTextBox.PlaceholderTextColor = System.Drawing.Color.Gray;
this.itemIdTextBox.Size = new System.Drawing.Size(46, 20);
this.itemIdTextBox.TabIndex = 78;
this.itemIdTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.infoTip.SetToolTip(this.itemIdTextBox, "The hexadecimal Item ID. Example: A31C");
this.itemIdTextBox.TextChanged += new System.EventHandler(this.CurrentItemIdTextChanged);
this.itemIdTextBox.Leave += new System.EventHandler(this.CurrentItemIdLostFocus);
//
// itemIdLabel
//
this.itemIdLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
@ -2834,6 +2790,50 @@ private void InitializeComponent()
this.StatusLabel.TabIndex = 16;
this.StatusLabel.TabStop = false;
//
// itemIdTextBox
//
this.itemIdTextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.itemIdTextBox.Enabled = false;
this.itemIdTextBox.Location = new System.Drawing.Point(132, 620);
this.itemIdTextBox.Name = "itemIdTextBox";
this.itemIdTextBox.PlaceholderText = "Item ID";
this.itemIdTextBox.PlaceholderTextColor = System.Drawing.Color.Gray;
this.itemIdTextBox.Size = new System.Drawing.Size(46, 20);
this.itemIdTextBox.TabIndex = 78;
this.itemIdTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
this.infoTip.SetToolTip(this.itemIdTextBox, "The hexadecimal Item ID. Example: A31C");
this.itemIdTextBox.TextChanged += new System.EventHandler(this.CurrentItemIdTextChanged);
this.itemIdTextBox.Leave += new System.EventHandler(this.CurrentItemIdLostFocus);
//
// patternNameTextBox
//
this.patternNameTextBox.Anchor = System.Windows.Forms.AnchorStyles.None;
this.patternNameTextBox.Location = new System.Drawing.Point(415, 538);
this.patternNameTextBox.MaxLength = 16;
this.patternNameTextBox.Name = "patternNameTextBox";
this.patternNameTextBox.PlaceholderText = "Pattern Name";
this.patternNameTextBox.PlaceholderTextColor = System.Drawing.Color.Gray;
this.patternNameTextBox.Size = new System.Drawing.Size(100, 20);
this.patternNameTextBox.TabIndex = 0;
this.patternNameTextBox.TextChanged += new System.EventHandler(this.PatternEditorNameBox_TextChanged);
//
// patternEditorPictureBox
//
this.patternEditorPictureBox.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Stretch;
this.patternEditorPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
this.patternEditorPictureBox.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
this.patternEditorPictureBox.Location = new System.Drawing.Point(0, 0);
this.patternEditorPictureBox.Name = "patternEditorPictureBox";
this.patternEditorPictureBox.Size = new System.Drawing.Size(513, 513);
this.patternEditorPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.patternEditorPictureBox.TabIndex = 0;
this.patternEditorPictureBox.TabStop = false;
this.patternEditorPictureBox.UseInternalInterpolationSetting = false;
this.patternEditorPictureBox.MouseDown += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseDown);
this.patternEditorPictureBox.MouseLeave += new System.EventHandler(this.PatternEditorBoxMouseLeave);
this.patternEditorPictureBox.MouseMove += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseMove);
this.patternEditorPictureBox.MouseUp += new System.Windows.Forms.MouseEventHandler(this.PatternEditorBoxMouseUp);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -2865,7 +2865,6 @@ private void InitializeComponent()
patternsTab.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.paletteColorSelectedPictureBox)).EndInit();
this.patternEditorPanel.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.patternEditorPictureBox)).EndInit();
this.patternGroupTabControl.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.paletteSelectionPictureBox)).EndInit();
this.menuStrip1.ResumeLayout(false);
@ -2913,6 +2912,7 @@ private void InitializeComponent()
((System.ComponentModel.ISupportInitialize)(this.acreHeightTrackBar)).EndInit();
this.loadingPanel.ResumeLayout(false);
this.loadingPanel.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.patternEditorPictureBox)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();

View file

@ -92,7 +92,6 @@ public sealed partial class MainForm : Form
private readonly SecureValueForm _secureNandValueForm = new SecureValueForm();
private readonly SettingsMenuForm _settingsMenu;
private bool _clicking;
private byte[] _buriedBuffer;
private byte[] _islandBuriedBuffer;
private ushort _selectedAcreId;
private int _selectedBuilding = -1;
@ -605,9 +604,6 @@ private void LoadAcres(Save save)
var x = 0;
var acreData = save.ReadUInt16Array(save.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.AcreData,
CurrentSaveInfo.AcreCount, true);
_buriedBuffer =
save.ReadByteArray(save.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.BuriedData,
CurrentSaveInfo.SaveOffsets.BuriedDataSize);
if (save.SaveGeneration == SaveGeneration.GCN)
{
@ -619,14 +615,13 @@ private void LoadAcres(Save save)
for (var i = 0; i < acreData.Length; i++)
{
if (i >= CurrentSaveInfo.XAcreCount + 1 && (i % CurrentSaveInfo.XAcreCount > 0
&& i % CurrentSaveInfo.XAcreCount <
&& i % CurrentSaveInfo.XAcreCount <
CurrentSaveInfo.XAcreCount - 1) && i <= 47)
{
var itemsBuff = save.ReadUInt16Array(save.SaveDataStartOffset +
CurrentSaveInfo.SaveOffsets.TownData + x * 512, 256,
true);
TownAcres[x] = new WorldAcre(acreData[i], i, itemsBuff, _buriedBuffer, save.SaveType, null,
x);
TownAcres[x] = new WorldAcre(acreData[i], i, itemsBuff, null, x);
x++;
}
@ -642,16 +637,14 @@ private void LoadAcres(Save save)
var x = 0;
var acreData = save.ReadByteArray(save.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.AcreData,
36);
_buriedBuffer =
save.ReadByteArray(save.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.BuriedData,
CurrentSaveInfo.SaveOffsets.BuriedDataSize);
for (var i = 0; i < 36; i++)
{
if (i >= 7 && (i % 6 > 0 && i % 6 < 5) && i <= 28)
{
var itemsBuff = save.ReadUInt16Array(save.SaveDataStartOffset +
CurrentSaveInfo.SaveOffsets.TownData + x * 512, 256);
TownAcres[x] = new WorldAcre(acreData[i], x, itemsBuff, _buriedBuffer, SaveType.WildWorld);
TownAcres[x] = new WorldAcre(acreData[i], x, itemsBuff, null, x);
x++;
}
@ -668,9 +661,7 @@ private void LoadAcres(Save save)
var x = 0;
var acreData = save.ReadUInt16Array(save.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.AcreData,
CurrentSaveInfo.AcreCount, true);
_buriedBuffer =
save.ReadByteArray(save.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.BuriedData,
CurrentSaveInfo.SaveOffsets.BuriedDataSize);
for (var i = 0; i < acreData.Length; i++)
{
if (i >= CurrentSaveInfo.XAcreCount + 1
@ -681,7 +672,7 @@ private void LoadAcres(Save save)
var itemsBuff = save.ReadUInt16Array(
save.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.TownData + x * 512, 256,
true);
TownAcres[x] = new WorldAcre(acreData[i], x, itemsBuff, _buriedBuffer, SaveType.CityFolk);
TownAcres[x] = new WorldAcre(acreData[i], x, itemsBuff, null, x);
x++;
}
@ -720,7 +711,7 @@ private void LoadAcres(Save save)
{
var itemsBuff = save.ReadUInt32Array(save.SaveDataStartOffset +
CurrentSaveInfo.SaveOffsets.TownData + x * 1024, 256);
TownAcres[x] = new WorldAcre(acreData[i], x, itemsBuff, _buriedBuffer, SaveType.NewLeaf);
TownAcres[x] = new WorldAcre(acreData[i], x, itemsBuff);
x++;
}
@ -980,11 +971,11 @@ private async Task SetupEditor(Save save)
_acreHeightModifier = 0;
_selectedAcreId = 0;
_selectedAcrePicturebox.Image = null;
_lastTownAcre = -1;
_selectedAcrePicturebox.BackgroundImage = null;
_buildings = null;
_islandBuildings = null;
_selectedPatternObject = null;
_buriedBuffer = null;
_islandBuriedBuffer = null;
_selectedHouse = null;
_tpcPicture.Image = NoTPC;
@ -1143,8 +1134,7 @@ await Task.Run(() =>
buildingsPanel.Controls[i].Dispose();
//Set building panel visibility
var visibility = (save.SaveType == SaveType.CityFolk || save.SaveType == SaveType.NewLeaf ||
save.SaveType == SaveType.WelcomeAmiibo);
var visibility = save.SaveGeneration == SaveGeneration.Wii || save.SaveGeneration == SaveGeneration.N3DS;
buildingsPanel.Visible = visibility;
buildingsLabel.Visible = visibility;
townPanel.Size = new Size(visibility ? townTab.Size.Width - 213 : townTab.Size.Width - 9,
@ -2527,92 +2517,100 @@ private void SetupMapPictureBoxes()
//Add events here
}
if (!CurrentSaveInfo.ContainsIsland) return;
IslandAcres = new WorldAcre[CurrentSaveInfo.IslandAcreCount];
_islandAcreMap = new PictureBoxWithInterpolationMode[IslandAcres.Length];
_newLeafIslandAcreMap = new PictureBoxWithInterpolationMode[16];
for (var y = 0; y < CurrentSaveInfo.IslandAcreCount / CurrentSaveInfo.IslandXAcreCount; y++)
if (CurrentSaveInfo.ContainsIsland)
{
for (var x = 0; x < CurrentSaveInfo.IslandXAcreCount; x++)
IslandAcres = new WorldAcre[CurrentSaveInfo.IslandAcreCount];
_islandAcreMap = new PictureBoxWithInterpolationMode[IslandAcres.Length];
_newLeafIslandAcreMap = new PictureBoxWithInterpolationMode[16];
for (var y = 0; y < CurrentSaveInfo.IslandAcreCount / CurrentSaveInfo.IslandXAcreCount; y++)
{
var idx = y * CurrentSaveInfo.IslandXAcreCount + x;
var acreId =
SaveFile.ReadUInt16(
SaveFile.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.IslandAcreData + idx * 2,
SaveFile.IsBigEndian);
var acreItems = new WorldItem[256];
for (var i = 0; i < 256; i++)
if (SaveFile.SaveGeneration == SaveGeneration.GCN)
{
acreItems[i] =
new WorldItem(
SaveFile.ReadUInt16(
SaveFile.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.IslandWorldData +
idx * 512 + i * 2, true), i);
}
else if ((idx > 4 && idx < 7) || (idx > 8 && idx < 11)) //Other acres are water acres
{
var worldIdx = (y - 1) * 2 + ((x - 1) % 4);
acreItems[i] =
new WorldItem(
SaveFile.ReadUInt32(SaveFile.SaveDataStartOffset +
CurrentSaveInfo.SaveOffsets.IslandWorldData + worldIdx * 1024 +
i * 4), i);
}
IslandAcres[idx] = new WorldAcre(acreId, idx, acreItems, _islandBuriedBuffer); //Add buried item data for Animal Crossing
if (SaveFile.SaveGeneration == SaveGeneration.GCN || ((idx > 4 && idx < 7) || (idx > 8 && idx < 11)))
for (var x = 0; x < CurrentSaveInfo.IslandXAcreCount; x++)
{
_islandAcreMap[idx] = new PictureBoxWithInterpolationMode
{
Size = new Size(_townMapTotalSize, _townMapTotalSize),
SizeMode = PictureBoxSizeMode.StretchImage,
BackgroundImageLayout = ImageLayout.Stretch,
InterpolationMode = InterpolationMode.HighQualityBicubic,
UseInternalInterpolationSetting = false,
Tag = idx
};
if (SaveFile.SaveType == SaveType.DoubutsuNoMoriEPlus || SaveFile.SaveType == SaveType.AnimalForestEPlus)
{
_islandAcreMap[idx].Image = GenerateAcreItemsBitmap(_selectedIsland.Items[idx], idx, true);
_islandAcreMap[idx].BackgroundImage = GetAcreImage(_acres[0x3C + idx].BaseAcreId);
}
else
{
_islandAcreMap[idx].Image = GenerateAcreItemsBitmap(IslandAcres[idx].AcreItems,
IslandAcres[idx].Index, true);
_islandAcreMap[idx].BackgroundImage = GetAcreImage(acreId);
}
_islandAcreMap[idx].MouseMove += (sender, e) => TownMove(sender, e, true);
_islandAcreMap[idx].MouseLeave += HideTownTip;
_islandAcreMap[idx].MouseDown += (sender, e) => TownMouseDown(sender, e, true);
_islandAcreMap[idx].MouseEnter += (sender, e) => TownEnter(sender);
_islandAcreMap[idx].MouseUp += TownMouseUp;
_islandAcreMap[idx].Location = (SaveFile.SaveGeneration == SaveGeneration.GCN)
? new Point(x * _townMapTotalSize, y * _townMapTotalSize)
: new Point(((x - 1) % 4) * _townMapTotalSize, (y - 1) * _townMapTotalSize);
islandPanel.Controls.Add(_islandAcreMap[idx]);
}
var idx = y * CurrentSaveInfo.IslandXAcreCount + x;
var acreId =
SaveFile.ReadUInt16(
SaveFile.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.IslandAcreData + idx * 2,
SaveFile.IsBigEndian);
if (SaveFile.SaveGeneration != SaveGeneration.N3DS) continue;
{
_newLeafIslandAcreMap[idx] = new PictureBoxWithInterpolationMode
var acreItems = new WorldItem[256];
for (var i = 0; i < 256; i++)
if (SaveFile.SaveGeneration == SaveGeneration.GCN)
{
acreItems[i] =
new WorldItem(
SaveFile.ReadUInt16(
SaveFile.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.IslandWorldData +
idx * 512 + i * 2, true), i);
}
else if ((idx > 4 && idx < 7) || (idx > 8 && idx < 11)) //Other acres are water acres
{
var worldIdx = (y - 1) * 2 + ((x - 1) % 4);
acreItems[i] =
new WorldItem(
SaveFile.ReadUInt32(SaveFile.SaveDataStartOffset +
CurrentSaveInfo.SaveOffsets.IslandWorldData +
worldIdx * 1024 +
i * 4), i);
}
IslandAcres[idx] = new WorldAcre(acreId, idx, acreItems);
if (SaveFile.SaveGeneration == SaveGeneration.GCN ||
((idx > 4 && idx < 7) || (idx > 8 && idx < 11)))
{
Size = new Size(_acreMapSize, _acreMapSize),
Location = new Point(x * _acreMapSize, _townMapTotalSize * 2 + 24 + y * _acreMapSize),
BackgroundImage = GetAcreImage(IslandAcres[idx].AcreId),
SizeMode = PictureBoxSizeMode.StretchImage,
BackgroundImageLayout = ImageLayout.Stretch,
UseInternalInterpolationSetting = true,
};
_newLeafIslandAcreMap[idx].MouseMove += (s, e) => AcreEditorMouseMove(s, e, true);
_newLeafIslandAcreMap[idx].MouseLeave += HideAcreTip;
_newLeafIslandAcreMap[idx].MouseClick += (s, e) => AcreClick(s, e, true);
_newLeafIslandAcreMap[idx].MouseEnter += AcreEditorMouseEnter;
_newLeafIslandAcreMap[idx].MouseLeave += AcreEditorMouseLeave;
islandPanel.Controls.Add(_newLeafIslandAcreMap[idx]);
_islandAcreMap[idx] = new PictureBoxWithInterpolationMode
{
Size = new Size(_townMapTotalSize, _townMapTotalSize),
SizeMode = PictureBoxSizeMode.StretchImage,
BackgroundImageLayout = ImageLayout.Stretch,
InterpolationMode = InterpolationMode.HighQualityBicubic,
UseInternalInterpolationSetting = false,
Tag = idx
};
if (SaveFile.SaveType == SaveType.DoubutsuNoMoriEPlus ||
SaveFile.SaveType == SaveType.AnimalForestEPlus)
{
_islandAcreMap[idx].Image =
GenerateAcreItemsBitmap(_selectedIsland.Items[idx], idx, true);
_islandAcreMap[idx].BackgroundImage = GetAcreImage(_acres[0x3C + idx].BaseAcreId);
}
else
{
_islandAcreMap[idx].Image = GenerateAcreItemsBitmap(IslandAcres[idx].AcreItems,
IslandAcres[idx].Index, true);
_islandAcreMap[idx].BackgroundImage = GetAcreImage(acreId);
}
_islandAcreMap[idx].MouseMove += (sender, e) => TownMove(sender, e, true);
_islandAcreMap[idx].MouseLeave += HideTownTip;
_islandAcreMap[idx].MouseDown += (sender, e) => TownMouseDown(sender, e, true);
_islandAcreMap[idx].MouseEnter += (sender, e) => TownEnter(sender);
_islandAcreMap[idx].MouseUp += TownMouseUp;
_islandAcreMap[idx].Location = (SaveFile.SaveGeneration == SaveGeneration.GCN)
? new Point(x * _townMapTotalSize, y * _townMapTotalSize)
: new Point(((x - 1) % 4) * _townMapTotalSize, (y - 1) * _townMapTotalSize);
islandPanel.Controls.Add(_islandAcreMap[idx]);
}
if (SaveFile.SaveGeneration != SaveGeneration.N3DS) continue;
{
_newLeafIslandAcreMap[idx] = new PictureBoxWithInterpolationMode
{
Size = new Size(_acreMapSize, _acreMapSize),
Location = new Point(x * _acreMapSize, _townMapTotalSize * 2 + 24 + y * _acreMapSize),
BackgroundImage = GetAcreImage(IslandAcres[idx].AcreId),
SizeMode = PictureBoxSizeMode.StretchImage,
BackgroundImageLayout = ImageLayout.Stretch,
UseInternalInterpolationSetting = true,
};
_newLeafIslandAcreMap[idx].MouseMove += (s, e) => AcreEditorMouseMove(s, e, true);
_newLeafIslandAcreMap[idx].MouseLeave += HideAcreTip;
_newLeafIslandAcreMap[idx].MouseClick += (s, e) => AcreClick(s, e, true);
_newLeafIslandAcreMap[idx].MouseEnter += AcreEditorMouseEnter;
_newLeafIslandAcreMap[idx].MouseLeave += AcreEditorMouseLeave;
islandPanel.Controls.Add(_newLeafIslandAcreMap[idx]);
}
}
}
}
@ -2622,8 +2620,14 @@ private void SetupMapPictureBoxes()
islandPanel.ResumeLayout();
grassPanel.ResumeLayout();
acrePanel.Refresh();
townPanel.Refresh();
islandPanel.Refresh();
grassPanel.Refresh();
if ((SaveFile.SaveType != SaveType.DoubutsuNoMoriEPlus && SaveFile.SaveType != SaveType.AnimalForestEPlus)
|| _selectedIsland == null) return;
|| _selectedIsland == null || _islandAcreMap == null) return;
var islandAcreIds = _selectedIsland.GetAcreIds();
_islandAcreMap[0].BackgroundImage = GetAcreImage(islandAcreIds[0]);
_islandAcreMap[1].BackgroundImage = GetAcreImage(islandAcreIds[1]);
@ -3082,7 +3086,7 @@ private void AcreClick(object sender, MouseEventArgs e, bool island = false)
{
var currentTownAcre = TownAcres[townAcre];
TownAcres[townAcre] = new WorldAcre((ushort)(_selectedAcreId + _acreHeightModifier),
townAcre, currentTownAcre.AcreItems, _buriedBuffer, SaveFile.SaveType);
townAcre, currentTownAcre.AcreItems);
if (loadDefaultItems)
{
TownAcres[townAcre].LoadDefaultItems(SaveFile);
@ -4000,12 +4004,18 @@ private void HandleTownClick(object sender, WorldItem item, int acre, int index,
// TODO: Island buried items
}
else
IslandAcres[acre].SetBuriedInMemory(IslandAcres[acre].AcreItems[index],
acre, _islandBuriedBuffer, true, SaveFile.SaveType);
{
IslandAcres[acre].AcreItems[index].Buried = IslandAcres[acre].SetItemBuried(
IslandAcres[acre].AcreItems[index], true,
SaveFile.SaveGeneration);
}
}
else
TownAcres[acre].SetBuriedInMemory(TownAcres[acre].AcreItems[index], acre,
_buriedBuffer, true, SaveFile.SaveType);
{
TownAcres[acre].AcreItems[index].Buried = TownAcres[acre].SetItemBuried(
TownAcres[acre].AcreItems[index], true,
SaveFile.SaveGeneration);
}
break;
}
@ -4159,6 +4169,11 @@ private void TownMove(object sender, MouseEventArgs e, bool island = false, bool
return;
}
if (_lastTownAcre < 0)
{
_lastTownAcre = 0;
}
WorldItem[] lastAcreItems;
if (island)
{
@ -4321,11 +4336,6 @@ private void SaveToolStripMenuItemClick(object sender, EventArgs e)
}
}
if (SaveFile.SaveGeneration != SaveGeneration.N3DS && CurrentSaveInfo.SaveOffsets.BuriedData != 0)
{
SaveFile.Write(SaveFile.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.BuriedData, _buriedBuffer);
}
if (CurrentSaveInfo.SaveOffsets.GrassWear > 0)
{
SaveFile.Write(SaveFile.SaveDataStartOffset + CurrentSaveInfo.SaveOffsets.GrassWear, _grassWear);
@ -5204,12 +5214,6 @@ private void GenerateRandomTownToolStripMenuItemClick(object sender, EventArgs e
case SaveGeneration.GCN:
var newAcreData = Generator.GetGenerator(SaveFile.SaveGeneration).Generate(seed);
// Clear Buried Items Bitmap if it exists
if (_buriedBuffer != null)
{
_buriedBuffer = new byte[_buriedBuffer.Length];
}
for (var i = 0; i < newAcreData.Length; i++)
{
_acres[i] = new WorldAcre(newAcreData[i], i);
@ -5226,8 +5230,7 @@ private void GenerateRandomTownToolStripMenuItemClick(object sender, EventArgs e
var townAcre = (y - CurrentSaveInfo.TownYAcreStart) * (CurrentSaveInfo.XAcreCount - 2) + (x - 1);
if (townAcre >= CurrentSaveInfo.TownAcreCount) continue;
TownAcres[townAcre] = new WorldAcre(_acres[i].AcreId, townAcre, _acres[i].AcreItems,
_buriedBuffer, SaveFile.SaveType);
TownAcres[townAcre] = new WorldAcre(_acres[i].AcreId, townAcre, _acres[i].AcreItems);
RefreshPictureBoxImage(_townAcreMap[townAcre],
GenerateAcreItemsBitmap(TownAcres[townAcre].AcreItems, townAcre));
_townAcreMap[townAcre].BackgroundImage = _acreMap[i].BackgroundImage;