mirror of
https://github.com/kwsch/NHSE.git
synced 2026-03-26 11:34:44 -05:00
Add handling for revised player house and room structure (v2.0) (#547)
* Add handling for revised player house and room structure (v2.0) * Update player room load/dump file type filters
This commit is contained in:
parent
8a2a562cdb
commit
8aed43a67f
|
|
@ -66,29 +66,19 @@ public IReadOnlyList<Building> Buildings
|
|||
set => Building.SetArray(value).CopyTo(Data, Offsets.MainFieldStructure);
|
||||
}
|
||||
|
||||
public PlayerHouse GetPlayerHouse(int index)
|
||||
public IPlayerHouse GetPlayerHouse(int index) => Offsets.ReadPlayerHouse(Data, index);
|
||||
public void SetPlayerHouse(IPlayerHouse value, int index) => Offsets.WritePlayerHouse(value, Data, index);
|
||||
|
||||
|
||||
public IPlayerHouse[] GetPlayerHouses()
|
||||
{
|
||||
if ((uint)index >= MainSaveOffsets.PlayerCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
return new PlayerHouse(Data.Slice(Offsets.PlayerHouseList + (index * PlayerHouse.SIZE), PlayerHouse.SIZE));
|
||||
var players = new IPlayerHouse[MainSaveOffsets.PlayerCount];
|
||||
for (int i = 0; i < players.Length; i++)
|
||||
players[i] = GetPlayerHouse(i);
|
||||
return players;
|
||||
}
|
||||
|
||||
public void SetPlayerHouse(PlayerHouse h, int index)
|
||||
{
|
||||
if ((uint)index >= MainSaveOffsets.PlayerCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
h.Data.CopyTo(Data, Offsets.PlayerHouseList + (index * PlayerHouse.SIZE));
|
||||
}
|
||||
|
||||
public PlayerHouse[] GetPlayerHouses()
|
||||
{
|
||||
var villagers = new PlayerHouse[MainSaveOffsets.PlayerCount];
|
||||
for (int i = 0; i < villagers.Length; i++)
|
||||
villagers[i] = GetPlayerHouse(i);
|
||||
return villagers;
|
||||
}
|
||||
|
||||
public void SetPlayerHouses(IReadOnlyList<PlayerHouse> houses)
|
||||
public void SetPlayerHouses(IReadOnlyList<IPlayerHouse> houses)
|
||||
{
|
||||
for (int i = 0; i < houses.Count; i++)
|
||||
SetPlayerHouse(houses[i], i);
|
||||
|
|
|
|||
|
|
@ -48,9 +48,13 @@ public abstract class MainSaveOffsets
|
|||
|
||||
public abstract int VillagerSize { get; }
|
||||
public abstract int VillagerHouseSize { get; }
|
||||
public abstract int PlayerHouseSize { get; }
|
||||
public abstract int PlayerRoomSize { get; }
|
||||
|
||||
public abstract IVillager ReadVillager(byte[] data);
|
||||
public abstract IVillagerHouse ReadVillagerHouse(byte[] data);
|
||||
public abstract IPlayerHouse ReadPlayerHouse(byte[] data);
|
||||
public abstract IPlayerRoom ReadPlayerRoom(byte[] data);
|
||||
|
||||
public static MainSaveOffsets GetOffsets(FileHeaderInfo Info)
|
||||
{
|
||||
|
|
@ -162,5 +166,23 @@ public void WriteVillagerHouse(IVillagerHouse v, byte[] data, int index)
|
|||
var size = VillagerHouseSize;
|
||||
v.Write().CopyTo(data, NpcHouseList + (index * size));
|
||||
}
|
||||
|
||||
public IPlayerHouse ReadPlayerHouse(byte[] data, int index)
|
||||
{
|
||||
if ((uint)index >= PlayerCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
|
||||
var size = PlayerHouseSize;
|
||||
var v = data.Slice(PlayerHouseList + (index * size), size);
|
||||
return ReadPlayerHouse(v);
|
||||
}
|
||||
|
||||
public void WritePlayerHouse(IPlayerHouse v, byte[] data, int index)
|
||||
{
|
||||
if ((uint)index >= PlayerCount)
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
var size = PlayerHouseSize;
|
||||
v.Write().CopyTo(data, PlayerHouseList + (index * size));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,5 +52,11 @@ public class MainSaveOffsets10 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,5 +52,10 @@ public class MainSaveOffsets11 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,5 +54,10 @@ public class MainSaveOffsets110 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,5 +55,10 @@ public class MainSaveOffsets111 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,5 +52,10 @@ public class MainSaveOffsets12 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,5 +52,10 @@ public class MainSaveOffsets13 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,5 +52,10 @@ public class MainSaveOffsets14 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,5 +52,10 @@ public class MainSaveOffsets15 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,5 +52,10 @@ public class MainSaveOffsets16 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,5 +52,10 @@ public class MainSaveOffsets17 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,5 +53,10 @@ public class MainSaveOffsets18 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,5 +54,10 @@ public class MainSaveOffsets19 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse1.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse1(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse1(data);
|
||||
public override int PlayerRoomSize => PlayerHouse1.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom1(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,5 +55,10 @@ public class MainSaveOffsets20 : MainSaveOffsets
|
|||
|
||||
public override int VillagerHouseSize => VillagerHouse2.SIZE;
|
||||
public override IVillagerHouse ReadVillagerHouse(byte[] data) => new VillagerHouse2(data);
|
||||
|
||||
public override int PlayerHouseSize => PlayerHouse2.SIZE;
|
||||
public override IPlayerHouse ReadPlayerHouse(byte[] data) => new PlayerHouse2(data);
|
||||
public override int PlayerRoomSize => PlayerHouse2.SIZE;
|
||||
public override IPlayerRoom ReadPlayerRoom(byte[] data) => new PlayerRoom2(data);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
33
NHSE.Core/Structures/Building/SoundAmbientKind.cs
Normal file
33
NHSE.Core/Structures/Building/SoundAmbientKind.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
namespace NHSE.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Ambient sound for a house.
|
||||
/// </summary>
|
||||
public enum SoundAmbientKind : byte
|
||||
{
|
||||
Silence = 0x0,
|
||||
Rain = 0x1,
|
||||
Sea = 0x2,
|
||||
InWater = 0x3,
|
||||
Wind = 0x4,
|
||||
Plateau = 0x5,
|
||||
Jungle = 0x6,
|
||||
Crowd = 0x7,
|
||||
Cheers = 0x8,
|
||||
City = 0x9,
|
||||
Train = 0xA,
|
||||
Construction = 0xB,
|
||||
Space = 0xC,
|
||||
Echo = 0xD,
|
||||
Storm = 0xE,
|
||||
Cave = 0x10,
|
||||
Earthquake = 0x11,
|
||||
Squeak = 0x12,
|
||||
Country = 0x14,
|
||||
Factory = 0x15,
|
||||
Cyber = 0x1A,
|
||||
Healing = 0x1B,
|
||||
Forest = 0x1C,
|
||||
Duct = 0x1D,
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ private static void Dump(string path, byte[] data, string name)
|
|||
/// <param name="houses"></param>
|
||||
/// <param name="players"></param>
|
||||
/// <param name="path">Path to dump to</param>
|
||||
public static void DumpPlayerHouses(this IReadOnlyList<PlayerHouse> houses, IReadOnlyList<Player> players, string path)
|
||||
public static void DumpPlayerHouses(this IReadOnlyList<IPlayerHouse> houses, IReadOnlyList<Player> players, string path)
|
||||
{
|
||||
for (int i = 0; i < houses.Count; i++)
|
||||
{
|
||||
|
|
@ -84,12 +84,12 @@ public static void DumpPlayerHouses(this HorizonSave sav, string path)
|
|||
}
|
||||
}
|
||||
|
||||
private static void Dump(this PlayerHouse h, string path, IVillagerOrigin p) => h.Dump(p.PlayerName, path);
|
||||
private static void Dump(this IPlayerHouse h, string path, IVillagerOrigin p) => h.Dump(p.PlayerName, path);
|
||||
|
||||
private static void Dump(this PlayerHouse h, string player, string path)
|
||||
private static void Dump(this IPlayerHouse h, string player, string path)
|
||||
{
|
||||
var dest = Path.Combine(path, $"{player}.nhph");
|
||||
var data = h.Data;
|
||||
var dest = Path.Combine(path, $"{player}.{h.Extension}");
|
||||
var data = h.Write();
|
||||
File.WriteAllBytes(dest, data);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ public class RoomItemManager
|
|||
{
|
||||
public readonly RoomItemLayer[] Layers;
|
||||
|
||||
public readonly PlayerRoom Room;
|
||||
public readonly IPlayerRoom Room;
|
||||
private const int LayerCount = 8;
|
||||
|
||||
public RoomItemManager(PlayerRoom room)
|
||||
public RoomItemManager(IPlayerRoom room)
|
||||
{
|
||||
Layers = room.GetItemLayers();
|
||||
Room = room;
|
||||
|
|
|
|||
16
NHSE.Core/Structures/Villager/IPlayerHouse.cs
Normal file
16
NHSE.Core/Structures/Villager/IPlayerHouse.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
namespace NHSE.Core
|
||||
{
|
||||
public interface IPlayerHouse : IHouseInfo
|
||||
{
|
||||
/// <summary> Returns the inner data buffer of the object, flushing any pending changes. </summary>
|
||||
byte[] Write();
|
||||
|
||||
sbyte NPC1 { get; set; }
|
||||
sbyte NPC2 { get; set; }
|
||||
string Extension { get; }
|
||||
short[] GetEventFlags();
|
||||
void SetEventFlags(short[] value);
|
||||
IPlayerRoom GetRoom(int v);
|
||||
void SetRoom(int roomIndex, IPlayerRoom room);
|
||||
}
|
||||
}
|
||||
15
NHSE.Core/Structures/Villager/IPlayerRoom.cs
Normal file
15
NHSE.Core/Structures/Villager/IPlayerRoom.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace NHSE.Core
|
||||
{
|
||||
public interface IPlayerRoom
|
||||
{
|
||||
/// <summary> Returns the inner data buffer of the object, flushing any pending changes. </summary>
|
||||
byte[] Write();
|
||||
|
||||
string Extension { get; }
|
||||
RoomItemLayer[] GetItemLayers();
|
||||
void SetItemLayers(IReadOnlyList<RoomItemLayer> value);
|
||||
IPlayerRoom Upgrade();
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,15 @@
|
|||
|
||||
namespace NHSE.Core
|
||||
{
|
||||
public class PlayerHouse : IHouseInfo
|
||||
public class PlayerHouse1 : IPlayerHouse
|
||||
{
|
||||
public const int SIZE = 0x26400;
|
||||
public virtual string Extension => "nhph";
|
||||
|
||||
public readonly byte[] Data;
|
||||
public PlayerHouse(byte[] data) => Data = data;
|
||||
public PlayerHouse1(byte[] data) => Data = data;
|
||||
|
||||
public byte[] Write() => Data;
|
||||
|
||||
public uint HouseLevel { get => BitConverter.ToUInt32(Data, 0x00); set => BitConverter.GetBytes(value).CopyTo(Data, 0x00); }
|
||||
public WallType WallUniqueID { get => (WallType)BitConverter.ToUInt16(Data, 0x04); set => BitConverter.GetBytes((ushort)value).CopyTo(Data, 0x04); }
|
||||
|
|
@ -39,29 +42,29 @@ public short[] GetEventFlags()
|
|||
public void SetEventFlags(short[] value) => Buffer.BlockCopy(value, 0, Data, 0x20, value.Length * sizeof(short));
|
||||
|
||||
public const int MaxRoom = 6;
|
||||
private const int RoomStart = 0x120;
|
||||
public const int RoomStart = 0x120;
|
||||
|
||||
public PlayerRoom GetRoom(int roomIndex)
|
||||
public IPlayerRoom GetRoom(int roomIndex)
|
||||
{
|
||||
if ((uint)roomIndex >= MaxRoom)
|
||||
throw new ArgumentOutOfRangeException(nameof(roomIndex));
|
||||
|
||||
var data = Data.Slice(RoomStart + (roomIndex * PlayerRoom.SIZE), PlayerRoom.SIZE);
|
||||
return new PlayerRoom(data);
|
||||
var data = Data.Slice(RoomStart + (roomIndex * PlayerRoom1.SIZE), PlayerRoom1.SIZE);
|
||||
return new PlayerRoom1(data);
|
||||
}
|
||||
|
||||
public void SetRoom(int roomIndex, PlayerRoom room)
|
||||
public void SetRoom(int roomIndex, IPlayerRoom room)
|
||||
{
|
||||
if ((uint)roomIndex >= MaxRoom)
|
||||
throw new ArgumentOutOfRangeException(nameof(roomIndex));
|
||||
|
||||
room.Data.CopyTo(Data, RoomStart + (roomIndex * PlayerRoom.SIZE));
|
||||
room.Write().CopyTo(Data, RoomStart + (roomIndex * PlayerRoom1.SIZE));
|
||||
}
|
||||
|
||||
public sbyte NPC1 { get => (sbyte)Data[0x263D0]; set => Data[0x263D0] = (byte)value; }
|
||||
public sbyte NPC2 { get => (sbyte)Data[0x263D1]; set => Data[0x263D1] = (byte)value; }
|
||||
|
||||
// 2bytes padding
|
||||
// 2 bytes padding
|
||||
|
||||
public Item DoorDecoItemName
|
||||
{
|
||||
|
|
@ -84,5 +87,15 @@ public Item OrderPostItemName
|
|||
}
|
||||
|
||||
// cockroach @ 0x263f0 -- meh
|
||||
|
||||
public PlayerHouse2 Upgrade()
|
||||
{
|
||||
var data = new byte[PlayerHouse2.SIZE];
|
||||
Data.Slice(0x0, 0x120).CopyTo(data, 0); // HouseLevel -> EventFlag
|
||||
for (int i = 0; i < MaxRoom; i++)
|
||||
GetRoom(i).Upgrade().Write().CopyTo(data, 0x120 + i * PlayerRoom2.SIZE); // RoomList
|
||||
Data.Slice(0x263D0, 0x30).CopyTo(data, 0x289F8); // PlayerList -> Cockroach
|
||||
return new PlayerHouse2(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
66
NHSE.Core/Structures/Villager/PlayerHouse2.cs
Normal file
66
NHSE.Core/Structures/Villager/PlayerHouse2.cs
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
using System;
|
||||
|
||||
namespace NHSE.Core
|
||||
{
|
||||
public class PlayerHouse2 : PlayerHouse1
|
||||
{
|
||||
public new const int SIZE = 0x28A28;
|
||||
public override string Extension => "nhph2";
|
||||
|
||||
public PlayerHouse2(byte[] data) : base(data) { }
|
||||
|
||||
public new PlayerRoom2 GetRoom(int roomIndex)
|
||||
{
|
||||
if ((uint)roomIndex >= MaxRoom)
|
||||
throw new ArgumentOutOfRangeException(nameof(roomIndex));
|
||||
|
||||
var data = Data.Slice(RoomStart + (roomIndex * PlayerRoom2.SIZE), PlayerRoom2.SIZE);
|
||||
return new PlayerRoom2(data);
|
||||
}
|
||||
|
||||
public void SetRoom(int roomIndex, PlayerRoom2 room)
|
||||
{
|
||||
if ((uint)roomIndex >= MaxRoom)
|
||||
throw new ArgumentOutOfRangeException(nameof(roomIndex));
|
||||
|
||||
room.Data.CopyTo(Data, RoomStart + (roomIndex * PlayerRoom2.SIZE));
|
||||
}
|
||||
|
||||
public new sbyte NPC1 { get => (sbyte)Data[0x289F8]; set => Data[0x289F8] = (byte)value; }
|
||||
public new sbyte NPC2 { get => (sbyte)Data[0x289F9]; set => Data[0x289F9] = (byte)value; }
|
||||
|
||||
// 2 bytes padding
|
||||
|
||||
public new Item DoorDecoItemName
|
||||
{
|
||||
get => Data.Slice(0x289FC, 8).ToClass<Item>();
|
||||
set => value.ToBytesClass().CopyTo(Data, 0x289FC);
|
||||
}
|
||||
|
||||
public new bool PlayerHouseFlag { get => Data[0x28A04] != 0; set => Data[0x28A04] = (byte)(value ? 1 : 0); }
|
||||
|
||||
public new Item PostItemName
|
||||
{
|
||||
get => Data.Slice(0x28A08, 8).ToClass<Item>();
|
||||
set => value.ToBytesClass().CopyTo(Data, 0x28A08);
|
||||
}
|
||||
|
||||
public new Item OrderPostItemName
|
||||
{
|
||||
get => Data.Slice(0x28A10, 8).ToClass<Item>();
|
||||
set => value.ToBytesClass().CopyTo(Data, 0x28A10);
|
||||
}
|
||||
|
||||
// cockroach @ 0x28A18 -- meh
|
||||
|
||||
public PlayerHouse1 Downgrade()
|
||||
{
|
||||
var data = new byte[PlayerHouse1.SIZE];
|
||||
Data.Slice(0x0, 0x120).CopyTo(data, 0); // HouseLevel -> EventFlag
|
||||
for (int i = 0; i < MaxRoom; i++)
|
||||
GetRoom(i).Downgrade().Data.CopyTo(data, 0x120 + i * PlayerRoom2.SIZE); // RoomList
|
||||
Data.Slice(0x289F8, 0x30).CopyTo(data, 0x263D0); // PlayerList -> Cockroach
|
||||
return new PlayerHouse1(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
73
NHSE.Core/Structures/Villager/PlayerHouseConverter.cs
Normal file
73
NHSE.Core/Structures/Villager/PlayerHouseConverter.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
namespace NHSE.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts Player House objects to different revisions.
|
||||
/// </summary>
|
||||
public static class PlayerHouseConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks to see if the <see cref="size"/> matches any of the House object sizes.
|
||||
/// </summary>
|
||||
/// <param name="size">Size of the byte array that might represent a House object.</param>
|
||||
/// <returns>True if it matches any size.</returns>
|
||||
public static bool IsHouse(int size)
|
||||
{
|
||||
return size == PlayerHouse1.SIZE || size == PlayerHouse2.SIZE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the input <see cref="size"/> can be converted to the <see cref="expect"/> size.
|
||||
/// </summary>
|
||||
/// <param name="size">Current house file size</param>
|
||||
/// <param name="expect">Expected house file size</param>
|
||||
/// <returns>True if can be converted, false if no conversion available.</returns>
|
||||
public static bool IsCompatible(int size, int expect)
|
||||
{
|
||||
return expect switch
|
||||
{
|
||||
// Can convert to any format
|
||||
PlayerHouse1.SIZE or PlayerHouse2.SIZE => IsHouse(size),
|
||||
// No conversion available
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the House data format to another format.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Before calling this method, check that a conversion method exists via <see cref="IsCompatible"/> and that the length of the <see cref="data"/> is not the same as what you <see cref="expect"/>.
|
||||
/// If the sizes are the same, it will return the input <see cref="data"/>.
|
||||
/// If no conversion path exists, it will return the input <see cref="data"/>.
|
||||
/// </remarks>
|
||||
/// <param name="data">Current format</param>
|
||||
/// <param name="expect">Target size</param>
|
||||
/// <returns>Converted data</returns>
|
||||
public static byte[] GetCompatible(byte[] data, int expect)
|
||||
{
|
||||
if (data.Length == expect)
|
||||
return data;
|
||||
|
||||
return expect switch
|
||||
{
|
||||
PlayerHouse1.SIZE when data.Length == PlayerHouse2.SIZE => Convert21(data),
|
||||
PlayerHouse2.SIZE when data.Length == PlayerHouse1.SIZE => Convert12(data),
|
||||
_ => data,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="PlayerHouse1"/> object byte array to a <see cref="PlayerHouse2"/>
|
||||
/// </summary>
|
||||
/// <param name="h1"><see cref="PlayerHouse1"/> object byte array</param>
|
||||
/// <returns><see cref="PlayerHouse2"/> object byte array</returns>
|
||||
private static byte[] Convert12(byte[] h1) => new PlayerHouse1(h1).Upgrade().Data;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="PlayerHouse2"/> object byte array to a <see cref="PlayerHouse1"/>
|
||||
/// </summary>
|
||||
/// <param name="h2"><see cref="PlayerHouse2"/> object byte array</param>
|
||||
/// <returns><see cref="PlayerHouse1"/> object byte array</returns>
|
||||
private static byte[] Convert21(byte[] h2) => new PlayerHouse2(h2).Downgrade().Data;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,15 @@
|
|||
|
||||
namespace NHSE.Core
|
||||
{
|
||||
public class PlayerRoom
|
||||
public class PlayerRoom1 : IPlayerRoom
|
||||
{
|
||||
public const int SIZE = 0x65C8;
|
||||
public virtual string Extension => "nhpr";
|
||||
|
||||
public readonly byte[] Data;
|
||||
public PlayerRoom(byte[] data) => Data = data;
|
||||
public PlayerRoom1(byte[] data) => Data = data;
|
||||
|
||||
public byte[] Write() => Data;
|
||||
|
||||
/*
|
||||
s_d8bc748b ItemLayerList[8]; // @0x0 size 0xc80, align 4
|
||||
|
|
@ -34,5 +37,12 @@ public GSaveRoomFloorWall RoomFloorWall
|
|||
get => Data.Slice(0x65A4, GSaveRoomFloorWall.SIZE).ToStructure<GSaveRoomFloorWall>();
|
||||
set => value.ToBytes().CopyTo(Data, 0x65A4);
|
||||
}
|
||||
|
||||
public IPlayerRoom Upgrade()
|
||||
{
|
||||
var data = new byte[PlayerRoom2.SIZE];
|
||||
Data.CopyTo(data, 0);
|
||||
return new PlayerRoom2(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
91
NHSE.Core/Structures/Villager/PlayerRoom2.cs
Normal file
91
NHSE.Core/Structures/Villager/PlayerRoom2.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace NHSE.Core
|
||||
{
|
||||
public class PlayerRoom2 : PlayerRoom1
|
||||
{
|
||||
public new const int SIZE = 0x6C24;
|
||||
public new virtual string Extension => "nhpr2";
|
||||
|
||||
public PlayerRoom2(byte[] data) : base(data) { }
|
||||
|
||||
/*
|
||||
s_665e9093 ExtraEffectLayerList[2]; // @0x65c8 size 0x320, align 2
|
||||
GSaveMusicBoxInfo MusicBoxInfo; // @0x6c08 size 0x4, align 2
|
||||
u8 SoundAmbient; // @0x6c0c size 0x1, align 1
|
||||
u8 gap_6c0d[3];
|
||||
s_e13a81f4 _cfb139b9; // @0x6c10 size 0x14, align 4
|
||||
*/
|
||||
|
||||
public s_665e9093[] ExtraEffectLayerList
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new s_665e9093[2];
|
||||
for (int i = 0; i < result.Length; i++)
|
||||
{
|
||||
var slice = Data.Slice(0x65C8 + i * s_665e9093.SIZE, s_665e9093.SIZE);
|
||||
result[i] = slice.ToStructure<s_665e9093>();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
set => value.ToBytesClass().CopyTo(Data, 0x65C8);
|
||||
}
|
||||
|
||||
public GSaveMusicBoxInfo MusicBoxInfo
|
||||
{
|
||||
get => Data.Slice(0x6C08, GSaveMusicBoxInfo.SIZE).ToStructure<GSaveMusicBoxInfo>();
|
||||
set => value.ToBytes().CopyTo(Data, 0x6C08);
|
||||
}
|
||||
|
||||
public SoundAmbientKind SoundAmbientUniqueID { get => (SoundAmbientKind)Data[0x6C0C]; set => Data[0x6C0C]= (byte)value; }
|
||||
|
||||
// 3 bytes padding
|
||||
|
||||
public s_e13a81f4 _cfb139b9
|
||||
{
|
||||
get => Data.Slice(0x6C10, s_e13a81f4.SIZE).ToStructure<s_e13a81f4>();
|
||||
set => value.ToBytes().CopyTo(Data, 0x6C10);
|
||||
}
|
||||
|
||||
public PlayerRoom1 Downgrade()
|
||||
{
|
||||
var result = new byte[PlayerRoom1.SIZE];
|
||||
Data.CopyTo(result, 0);
|
||||
return new PlayerRoom1(result);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS8618, CA1815, CA1819, IDE1006, RCS1170
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)]
|
||||
[TypeConverter(typeof(ValueTypeTypeConverter))]
|
||||
public struct s_665e9093
|
||||
{
|
||||
public const int SIZE = 0x320; /* 0x320 big, align 2 */
|
||||
|
||||
[field: MarshalAs(UnmanagedType.LPArray, SizeConst = 400)]
|
||||
public GSaveItemExtraEffect[] ItemExtraEffectBuffer { get; set; } // @0x0 size 0x2, align 2
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)]
|
||||
[TypeConverter(typeof(ValueTypeTypeConverter))]
|
||||
public struct GSaveItemExtraEffect
|
||||
{
|
||||
public const int SIZE = 0x2; /* 0x2 big, align 2 */
|
||||
|
||||
public ushort InnerData { get; set; } // @0x0 size 0x2, align 2
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 2, Size = SIZE)]
|
||||
[TypeConverter(typeof(ValueTypeTypeConverter))]
|
||||
public struct GSaveMusicBoxInfo
|
||||
{
|
||||
public const int SIZE = 0x4; /* 0x4 big, align 2 */
|
||||
|
||||
public ushort PlayingAudioMusicID { get; set; } // @0x0 size 0x2, align 2
|
||||
public byte _749b78c2 { get; set; } // @0x2 size 0x1, align 1
|
||||
}
|
||||
}
|
||||
73
NHSE.Core/Structures/Villager/PlayerRoomConverter.cs
Normal file
73
NHSE.Core/Structures/Villager/PlayerRoomConverter.cs
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
namespace NHSE.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts Player Room objects to different revisions.
|
||||
/// </summary>
|
||||
public static class PlayerRoomConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks to see if the <see cref="size"/> matches any of the Room object sizes.
|
||||
/// </summary>
|
||||
/// <param name="size">Size of the byte array that might represent a Room object.</param>
|
||||
/// <returns>True if it matches any size.</returns>
|
||||
public static bool IsRoom(int size)
|
||||
{
|
||||
return size == PlayerRoom1.SIZE || size == PlayerRoom2.SIZE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the input <see cref="size"/> can be converted to the <see cref="expect"/> size.
|
||||
/// </summary>
|
||||
/// <param name="size">Current room file size</param>
|
||||
/// <param name="expect">Expected room file size</param>
|
||||
/// <returns>True if can be converted, false if no conversion available.</returns>
|
||||
public static bool IsCompatible(int size, int expect)
|
||||
{
|
||||
return expect switch
|
||||
{
|
||||
// Can convert to any format
|
||||
PlayerRoom1.SIZE or PlayerRoom2.SIZE => IsRoom(size),
|
||||
// No conversion available
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the Room data format to another format.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Before calling this method, check that a conversion method exists via <see cref="IsCompatible"/> and that the length of the <see cref="data"/> is not the same as what you <see cref="expect"/>.
|
||||
/// If the sizes are the same, it will return the input <see cref="data"/>.
|
||||
/// If no conversion path exists, it will return the input <see cref="data"/>.
|
||||
/// </remarks>
|
||||
/// <param name="data">Current format</param>
|
||||
/// <param name="expect">Target size</param>
|
||||
/// <returns>Converted data</returns>
|
||||
public static byte[] GetCompatible(byte[] data, int expect)
|
||||
{
|
||||
if (data.Length == expect)
|
||||
return data;
|
||||
|
||||
return expect switch
|
||||
{
|
||||
PlayerRoom1.SIZE when data.Length == PlayerRoom2.SIZE => Convert21(data),
|
||||
PlayerRoom2.SIZE when data.Length == PlayerRoom1.SIZE => Convert12(data),
|
||||
_ => data,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="PlayerRoom1"/> object byte array to a <see cref="PlayerRoom2"/>
|
||||
/// </summary>
|
||||
/// <param name="h1"><see cref="PlayerRoom1"/> object byte array</param>
|
||||
/// <returns><see cref="PlayerRoom2"/> object byte array</returns>
|
||||
private static byte[] Convert12(byte[] h1) => new PlayerRoom1(h1).Upgrade().Write();
|
||||
|
||||
/// <summary>
|
||||
/// Converts a <see cref="PlayerRoom2"/> object byte array to a <see cref="PlayerRoom1"/>
|
||||
/// </summary>
|
||||
/// <param name="h2"><see cref="PlayerRoom2"/> object byte array</param>
|
||||
/// <returns><see cref="PlayerRoom1"/> object byte array</returns>
|
||||
private static byte[] Convert21(byte[] h2) => new PlayerRoom2(h2).Downgrade().Write();
|
||||
}
|
||||
}
|
||||
|
|
@ -470,7 +470,7 @@ private void B_EditDesignsTailor_Click(object sender, EventArgs e)
|
|||
private void B_EditPlayerHouses_Click(object sender, EventArgs e)
|
||||
{
|
||||
var houses = SAV.Main.GetPlayerHouses();
|
||||
using var editor = new PlayerHouseEditor(houses, SAV.Players, PlayerIndex);
|
||||
using var editor = new PlayerHouseEditor(houses, SAV.Players, SAV.Main, PlayerIndex);
|
||||
if (editor.ShowDialog() == DialogResult.OK)
|
||||
SAV.Main.SetPlayerHouses(houses);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ public static bool LoadMuseum(Museum museum)
|
|||
return true;
|
||||
}
|
||||
|
||||
public static void DumpHouse(IReadOnlyList<Player> players, IReadOnlyList<PlayerHouse> houses, int index, bool dumpAll)
|
||||
public static void DumpHouse(IReadOnlyList<Player> players, IReadOnlyList<IPlayerHouse> houses, int index, bool dumpAll)
|
||||
{
|
||||
if (dumpAll)
|
||||
DumpAllPlayerHouses(houses, players);
|
||||
|
|
@ -104,23 +104,25 @@ public static void DumpHouse(IReadOnlyList<Player> players, IReadOnlyList<Player
|
|||
DumpPlayerHouse(players, houses, index);
|
||||
}
|
||||
|
||||
private static void DumpPlayerHouse(IReadOnlyList<Player> players, IReadOnlyList<PlayerHouse> houses, int index)
|
||||
private static void DumpPlayerHouse(IReadOnlyList<Player> players, IReadOnlyList<IPlayerHouse> houses, int index)
|
||||
{
|
||||
var house = houses[index];
|
||||
var name = PlayerHouseEditor.GetHouseSummary(players, house, index);
|
||||
using var sfd = new SaveFileDialog
|
||||
{
|
||||
Filter = "New Horizons Player House (*.nhph)|*.nhph|All files (*.*)|*.*",
|
||||
FileName = $"{name}.nhph",
|
||||
Filter = "New Horizons Player House (*.nhph)|*.nhph|" +
|
||||
"New Horizons Player House (*.nhph2)|*.nhph2|" +
|
||||
"All files (*.*)|*.*",
|
||||
FileName = $"{name}.{house.Extension}",
|
||||
};
|
||||
if (sfd.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
var data = house.Data;
|
||||
var data = house.Write();
|
||||
File.WriteAllBytes(sfd.FileName, data);
|
||||
}
|
||||
|
||||
private static void DumpAllPlayerHouses(IReadOnlyList<PlayerHouse> houses, IReadOnlyList<Player> players)
|
||||
private static void DumpAllPlayerHouses(IReadOnlyList<IPlayerHouse> houses, IReadOnlyList<Player> players)
|
||||
{
|
||||
using var fbd = new FolderBrowserDialog();
|
||||
if (fbd.ShowDialog() != DialogResult.OK)
|
||||
|
|
@ -132,69 +134,90 @@ private static void DumpAllPlayerHouses(IReadOnlyList<PlayerHouse> houses, IRead
|
|||
houses.DumpPlayerHouses(players, fbd.SelectedPath);
|
||||
}
|
||||
|
||||
public static bool LoadHouse(IReadOnlyList<Player> players, PlayerHouse[] houses, int index)
|
||||
public static bool LoadHouse(MainSaveOffsets offsets, IReadOnlyList<Player> players, IPlayerHouse[] houses, int index)
|
||||
{
|
||||
var h = houses[index];
|
||||
var name = PlayerHouseEditor.GetHouseSummary(players, houses[index], index);
|
||||
using var ofd = new OpenFileDialog
|
||||
{
|
||||
Filter = "New Horizons Player House (*.nhph)|*.nhph|All files (*.*)|*.*",
|
||||
FileName = $"{name}.nhph",
|
||||
Filter = "New Horizons Player House (*.nhph)|*.nhph|" +
|
||||
"New Horizons Player House (*.nhph2)|*.nhph2|" +
|
||||
"All files (*.*)|*.*",
|
||||
FileName = $"{name}.{h.Extension}",
|
||||
};
|
||||
if (ofd.ShowDialog() != DialogResult.OK)
|
||||
return false;
|
||||
|
||||
var file = ofd.FileName;
|
||||
var fi = new FileInfo(file);
|
||||
const int expectLength = PlayerHouse.SIZE;
|
||||
if (fi.Length != expectLength)
|
||||
var path = ofd.FileName;
|
||||
var expectLength = offsets.PlayerHouseSize;
|
||||
var fi = new FileInfo(path);
|
||||
if (!VillagerHouseConverter.IsCompatible((int)fi.Length, expectLength))
|
||||
{
|
||||
WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength));
|
||||
WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path);
|
||||
return false;
|
||||
}
|
||||
|
||||
var data = File.ReadAllBytes(file);
|
||||
var h = new PlayerHouse(data);
|
||||
var data = File.ReadAllBytes(ofd.FileName);
|
||||
data = PlayerHouseConverter.GetCompatible(data, expectLength);
|
||||
if (fi.Length != expectLength)
|
||||
{
|
||||
WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path);
|
||||
return false;
|
||||
}
|
||||
|
||||
h = offsets.ReadPlayerHouse(data);
|
||||
var current = houses[index];
|
||||
h.NPC1 = current.NPC1;
|
||||
houses[index] = h;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void DumpRoom(PlayerRoom room, int index)
|
||||
public static void DumpRoom(IPlayerRoom room, int index)
|
||||
{
|
||||
using var sfd = new SaveFileDialog
|
||||
{
|
||||
Filter = "New Horizons Player House Room (*.nhpr)|*.nhpr|All files (*.*)|*.*",
|
||||
FileName = $"Room {index + 1}.nhpr",
|
||||
Filter = "New Horizons Player House Room (*.nhpr)|*.nhpr|" +
|
||||
"New Horizons Player House Room (*.nhpr2)|*.nhpr2|" +
|
||||
"All files (*.*)|*.*",
|
||||
FileName = $"Room {index + 1}.{room.Extension}",
|
||||
};
|
||||
if (sfd.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
var data = room.Data;
|
||||
var data = room.Write();
|
||||
File.WriteAllBytes(sfd.FileName, data);
|
||||
}
|
||||
|
||||
public static bool LoadRoom(PlayerRoom room, int index)
|
||||
public static bool LoadRoom(MainSaveOffsets offsets, IPlayerRoom room, int index)
|
||||
{
|
||||
using var ofd = new OpenFileDialog
|
||||
{
|
||||
Filter = "New Horizons Player House Room (*.nhpr)|*.nhpr|All files (*.*)|*.*",
|
||||
FileName = $"Room {index + 1}.nhpr",
|
||||
Filter = "New Horizons Player House Room (*.nhpr)|*.nhpr|" +
|
||||
"New Horizons Player House Room (*.nhpr2)|*.nhpr2|" +
|
||||
"All files (*.*)|*.*",
|
||||
FileName = $"Room {index + 1}.{room.Extension}",
|
||||
};
|
||||
if (ofd.ShowDialog() != DialogResult.OK)
|
||||
return false;
|
||||
|
||||
var file = ofd.FileName;
|
||||
var fi = new FileInfo(file);
|
||||
const int expectLength = PlayerRoom.SIZE;
|
||||
if (fi.Length != expectLength)
|
||||
var path = ofd.FileName;
|
||||
var expectLength = offsets.PlayerRoomSize;
|
||||
var fi = new FileInfo(path);
|
||||
if (!PlayerRoomConverter.IsCompatible((int)fi.Length, expectLength))
|
||||
{
|
||||
WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength));
|
||||
WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path);
|
||||
return false;
|
||||
}
|
||||
|
||||
var data = File.ReadAllBytes(file);
|
||||
data.CopyTo(room.Data, 0);
|
||||
var data = File.ReadAllBytes(ofd.FileName);
|
||||
data = PlayerRoomConverter.GetCompatible(data, offsets.PlayerRoomSize);
|
||||
if (fi.Length != expectLength)
|
||||
{
|
||||
WinFormsUtil.Error(MessageStrings.MsgCanceling, string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path);
|
||||
return false;
|
||||
}
|
||||
|
||||
room = offsets.ReadPlayerRoom(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ namespace NHSE.WinForms
|
|||
{
|
||||
public partial class PlayerHouseEditor : Form
|
||||
{
|
||||
private readonly PlayerHouse[] Houses;
|
||||
private readonly MainSave SAV;
|
||||
private readonly IPlayerHouse[] Houses;
|
||||
private readonly IReadOnlyList<Player> Players;
|
||||
private RoomItemManager Manager;
|
||||
private const int scale = 24;
|
||||
|
|
@ -17,10 +18,11 @@ public partial class PlayerHouseEditor : Form
|
|||
private int Index = -1;
|
||||
private int RoomIndex = -1;
|
||||
|
||||
public PlayerHouseEditor(PlayerHouse[] houses, IReadOnlyList<Player> players, int index)
|
||||
public PlayerHouseEditor(IPlayerHouse[] houses, IReadOnlyList<Player> players, MainSave sav, int index)
|
||||
{
|
||||
InitializeComponent();
|
||||
this.TranslateInterface(GameInfo.CurrentLanguage);
|
||||
SAV = sav;
|
||||
Houses = houses;
|
||||
Players = players;
|
||||
Manager = new RoomItemManager(houses[0].GetRoom(0));
|
||||
|
|
@ -73,7 +75,7 @@ private void PG_Item_PropertyValueChanged(object s, PropertyValueChangedEventArg
|
|||
LB_Items.Items[Index] = GetHouseSummary(Players, Houses[Index], Index);
|
||||
}
|
||||
|
||||
public static string GetHouseSummary(IReadOnlyList<Player> players, PlayerHouse house, int index)
|
||||
public static string GetHouseSummary(IReadOnlyList<Player> players, IPlayerHouse house, int index)
|
||||
{
|
||||
var houseName = index >= players.Count ? $"House {index}" : $"{players[index].Personal.PlayerName}'s House";
|
||||
return $"{houseName} (lv {house.HouseLevel})";
|
||||
|
|
@ -86,7 +88,7 @@ private void B_DumpHouse_Click(object sender, EventArgs e)
|
|||
|
||||
private void B_LoadHouse_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (!MiscDumpHelper.LoadHouse(Players, Houses, Index))
|
||||
if (!MiscDumpHelper.LoadHouse(SAV.Offsets, Players, Houses, Index))
|
||||
return;
|
||||
|
||||
RoomIndex = -1;
|
||||
|
|
@ -141,14 +143,14 @@ private static void GetCoordinates(MouseEventArgs e, out int x, out int y)
|
|||
y = e.Y / scale;
|
||||
}
|
||||
|
||||
private void ChangeRoom(PlayerHouse house)
|
||||
private void ChangeRoom(IPlayerHouse house)
|
||||
{
|
||||
RoomIndex = (int) NUD_Room.Value - 1;
|
||||
ReloadManager(house);
|
||||
DrawLayer();
|
||||
}
|
||||
|
||||
private void ReloadManager(PlayerHouse house)
|
||||
private void ReloadManager(IPlayerHouse house)
|
||||
{
|
||||
var unsupported = Manager.GetUnsupportedTiles();
|
||||
if (unsupported.Count != 0)
|
||||
|
|
@ -300,7 +302,7 @@ private void DeleteTile(Item tile, int x, int y)
|
|||
private void B_LoadRoom_Click(object sender, EventArgs e)
|
||||
{
|
||||
var room = Manager.Room;
|
||||
MiscDumpHelper.LoadRoom(room, RoomIndex);
|
||||
MiscDumpHelper.LoadRoom(SAV.Offsets, room, RoomIndex);
|
||||
|
||||
var house = Houses[Index];
|
||||
house.SetRoom(RoomIndex, room);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user