public void SetBuriedInMemory(WorldItem item, int acre, byte[] burriedItemData, bool buried, SaveType saveType) { if (saveType != SaveType.New_Leaf && saveType != SaveType.Welcome_Amiibo) { int buriedLocation = GetBuriedDataLocation(item, acre, saveType); if (buriedLocation > -1) { DataConverter.SetBit(ref burriedItemData[buriedLocation], item.Location.X % 8, buried); item.Burried = DataConverter.ToBit(burriedItemData[buriedLocation], item.Location.X % 8) == 1; } else { item.Burried = false; } } }
/// <summary> /// Loads the Acre's default <see cref="Item"/>s from a file. /// </summary> /// <param name="saveFile">The current save file.</param> /// <returns>bool ItemsWereLoaded</returns> public bool LoadDefaultItems(Save saveFile) { var defaultAcreDataFolder = MainForm.AssemblyLocation + Path.DirectorySeparatorChar + "Resources" + Path.DirectorySeparatorChar + "Default Acre Items"; switch (saveFile.SaveGeneration) { case SaveGeneration.GCN: defaultAcreDataFolder += Path.DirectorySeparatorChar + "GCN" + Path.DirectorySeparatorChar; break; } if (!Directory.Exists(defaultAcreDataFolder)) { return(false); } var filePath = defaultAcreDataFolder + BaseAcreId.ToString("X4") + ".bin"; if (!File.Exists(filePath)) { return(false); } try { using (var fStream = new FileStream(filePath, FileMode.Open)) { using (var reader = new BinaryReader(fStream)) { for (var i = 0; i < fStream.Length / 2; i++) { if (i >= 0x100) // Don't read past the maximum item slot. { break; } AcreItems[i] = new WorldItem(reader.ReadUInt16().Reverse(), i); } } } return(true); } catch { MainForm.DebugManager.WriteLine( $"Unable to open default acre data for Acre Id 0x{BaseAcreId:X4}", DebugLevel.Error); } return(false); }
//TODO: Change BuriedData from byte[] to ushort[] and use updated code private int GetBuriedDataLocation(WorldItem item, int acre, SaveType saveType) { if (item != null) { int worldPosition = 0; if (saveType == SaveType.Animal_Crossing || saveType == SaveType.Doubutsu_no_Mori_e_Plus || saveType == SaveType.City_Folk) { worldPosition = (acre * 256) + (15 - item.Location.X) + item.Location.Y * 16; //15 - item.Location.X because it's stored as a ushort in memory w/ reversed endianess } else if (saveType == SaveType.Wild_World) { worldPosition = (acre * 256) + item.Index; } return(worldPosition / 8); } return(-1); }
public Island(int offset, IEnumerable <Player> players, Save saveFile) { _saveFile = saveFile; _offset = offset; Name = new Utilities.AcString(saveFile.ReadByteArray(offset + IslandName, 6), saveFile.SaveType).Trim(); Id = saveFile.ReadUInt16(offset + IslandId, true); TownName = new Utilities.AcString(saveFile.ReadByteArray(offset + TownNameOffset, 6), saveFile.SaveType).Trim(); TownId = saveFile.ReadUInt16(offset + TownIdOffset, true); var identifier = saveFile.ReadUInt16(offset - 0x2214, true); foreach (var player in players) { if (player != null && player.Data.Identifier == identifier) { Owner = player; } } BuriedDataArray = saveFile.ReadByteArray(offset + BuriedData, 0x40); Items = new WorldItem[2][]; for (var acre = 0; acre < 2; acre++) { Items[acre] = new WorldItem[0x100]; var i = 0; foreach (var itemId in saveFile.ReadUInt16Array(offset + WorldData + acre * 0x200, 0x100, true)) { Items[acre][i] = new WorldItem(itemId, i % 256); SetBuried(Items[acre][i], acre, BuriedDataArray, saveFile.SaveType); i++; } } Cabana = new House(-1, offset + CottageData, 1, 0); Cabana.Data.Rooms[0].Name = "Cabana"; FlagPattern = new Pattern(offset + FlagData, 0, saveFile); Islander = new Villager(offset + IslanderData, 0, saveFile); Purchased = IsPurchased(); IslandLeftAcreIndex = saveFile.ReadByte(offset + IslandLeftAcreData); IslandRightAcreIndex = saveFile.ReadByte(offset + IslandRightAcreData); }
//Correct decoding/setting of buried items. Fixes the hacky SaveType case for AC/CF. (Don't forget to implement this!) private void SetBuriedInMemoryFixed(WorldItem item, int acre, ushort[] buriedItemData, bool buried, SaveType saveType) { if (saveType != SaveType.New_Leaf && saveType != SaveType.Welcome_Amiibo) { int buriedLocation = (acre * 256 + item.Index) / 16; if (buriedLocation > -1) { byte[] Buried_Row_Bytes = BitConverter.GetBytes(buriedItemData[buriedLocation]); DataConverter.SetBit(ref Buried_Row_Bytes[item.Location.X / 8], item.Location.X % 8, buried); //Should probably rewrite bit editing functions to take any data type item.Burried = DataConverter.ToBit(Buried_Row_Bytes[item.Location.X / 8], item.Location.X % 8) == 1; buriedItemData[buriedLocation] = BitConverter.ToUInt16(Buried_Row_Bytes, 0); } else { item.Burried = false; } } }
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; } }
public static byte[] Find_Villager_House(ushort Villager_ID) // TODO: Apply to WW { if (NewMainForm.Save_File != null) { ushort Villager_House_ID = (ushort)(0x5000 + (Villager_ID & 0xFF)); foreach (Normal_Acre Acre in NewMainForm.Town_Acres) { WorldItem Villager_House = Acre.Acre_Items.FirstOrDefault(o => o.ItemID == Villager_House_ID); if (Villager_House != null) { return(new byte[4] { (byte)(Acre.Index % 7), (byte)(Acre.Index / 7), (byte)(Villager_House.Location.X), (byte)(Villager_House.Location.Y + 1) }); } } } return(new byte[4] { 0xFF, 0xFF, 0xFF, 0xFF }); }
public Normal_Acre(ushort acreId, int position, ushort[] items = null, byte[] burriedItemData = null, SaveType saveType = SaveType.Animal_Crossing, uint[] nl_items = null, int townPosition = -1) : base(acreId, position) { if (items != null) { for (int i = 0; i < 256; i++) { Acre_Items[i] = new WorldItem(items[i], i); if (burriedItemData != null) { SetBuried(Acre_Items[i], townPosition == -1 ? position : townPosition, burriedItemData, saveType); //Broken in original save editor lol.. needs a position - 1 to function properly } } } else if (nl_items != null) { for (int i = 0; i < 256; i++) { Acre_Items[i] = new WorldItem(nl_items[i], i); //add buried logic } } }
private static int GetBuriedDataLocation(WorldItem item, int acre, SaveType saveType) { if (item == null) { return(-1); } var worldPosition = 0; switch (saveType) { case SaveType.AnimalCrossing: case SaveType.DoubutsuNoMoriEPlus: case SaveType.AnimalForestEPlus: case SaveType.CityFolk: worldPosition = (acre * 256) + (15 - item.Location.X) + item.Location.Y * 16; //15 - item.Location.X because it's stored as a ushort in memory w/ reversed endianess break; case SaveType.WildWorld: worldPosition = (acre * 256) + item.Index; break; } return(worldPosition / 8); }
public static bool[] Check_Perfect_Town_Requirements(Normal_Acre[] Acres, bool Make_Perfect = false) { bool[] Acre_Results = new bool[Acres.Length]; int Points = 0; for (int i = 0; i < Acre_Results.Length; i++) { Normal_Acre Acre = Acres[i]; switch (NewMainForm.Save_File.Game_System) { case SaveGeneration.N64: case SaveGeneration.GCN: //TODO: Implement Special Acre Check (Player Houses, Train Station, Oceanfront Acres, Lake Acres, Wishing Well, & Museum //Special Acre Info: < 9 Trees, 0 Points | 9 - 11, 1 Point | 12 - 14, 2 Points | 15 - 17, 1 Point | > 18, 0 Points int Tree_Count = 0; int Weed_Count = 0; for (int o = 0; o < 256; o++) { WorldItem Item = Acre.Acre_Items[o]; if (Item.Name == "Weed") { Weed_Count++; if (Make_Perfect) { Acre.Acre_Items[o] = new WorldItem(0, o); } } else if (ItemData.GetItemType(Item.ItemID) == "Tree") { Tree_Count++; } } if (Make_Perfect) { if (Tree_Count > 14) { for (int o = 0; o < Tree_Count - 13; o++) { for (int x = 0; x < 256; x++) { if (ItemData.GetItemType(Acre.Acre_Items[x].ItemID) == "Tree") { Acre.Acre_Items[x] = new WorldItem(0, x); break; } } } } else if (Tree_Count < 12) { for (int o = 0; o < 13 - Tree_Count; o++) { for (int x = 0; x < 256; x++) { // Check to make sure the item directly above, below, and to the left and right isn't already occupied. if (Acre.Acre_Items[x].ItemID == 0 && (x < 16 || Acre.Acre_Items[x - 16].ItemID == 0) && (x > 239 || Acre.Acre_Items[x + 16].ItemID == 0) && (x == 0 || Acre.Acre_Items[x - 1].ItemID == 0) && (x == 255 || Acre.Acre_Items[x + 1].ItemID == 0)) { Acre.Acre_Items[x] = new WorldItem(0x0804, x); break; } } } } } Acre_Results[i] = Make_Perfect || ((Tree_Count > 11 && Tree_Count < 15) && Weed_Count < 4); if (Acre_Results[i]) { Points++; } break; case SaveGeneration.NDS: case SaveGeneration.Wii: case SaveGeneration.N3DS: throw new NotImplementedException(); } } return(Acre_Results); }