NHSE/NHSE.Core/Structures/Villager/PlayerHouse1.cs
2026-01-17 22:12:37 -06:00

94 lines
3.7 KiB
C#

using System;
using System.Runtime.InteropServices;
using static System.Buffers.Binary.BinaryPrimitives;
namespace NHSE.Core;
public class PlayerHouse1(Memory<byte> raw) : IPlayerHouse
{
public const int SIZE = 0x26400;
public virtual string Extension => "nhph";
public Span<byte> Data => raw.Span;
public byte[] Write() => Data.ToArray();
public uint HouseLevel { get => ReadUInt32LittleEndian(Data); set => WriteUInt32LittleEndian(Data, value); }
public WallType WallUniqueID { get => (WallType)ReadUInt16LittleEndian(Data[0x04..]); set => WriteUInt16LittleEndian(Data[0x04..], (ushort)value); }
public RoofType RoofUniqueID { get => (RoofType)ReadUInt16LittleEndian(Data[0x06..]); set => WriteUInt16LittleEndian(Data[0x06..], (ushort)value); }
public DoorKind DoorUniqueID { get => (DoorKind)ReadUInt16LittleEndian(Data[0x08..]); set => WriteUInt16LittleEndian(Data[0x08..], (ushort)value); }
public WallType OrderWallUniqueID { get => (WallType)ReadUInt16LittleEndian(Data[0x0A..]); set => WriteUInt16LittleEndian(Data[0x0A..], (ushort)value); }
public RoofType OrderRoofUniqueID { get => (RoofType)ReadUInt16LittleEndian(Data[0x0C..]); set => WriteUInt16LittleEndian(Data[0x0C..], (ushort)value); }
public DoorKind OrderDoorUniqueID { get => (DoorKind)ReadUInt16LittleEndian(Data[0x0E..]); set => WriteUInt16LittleEndian(Data[0x0E..], (ushort)value); }
public EncryptedInt32 Loan
{
get => EncryptedInt32.Read(Data[0x10..]);
set => value.Write(Data[0x10..]);
}
public EncryptedInt32 Unknown
{
get => EncryptedInt32.Read(Data[0x18..]);
set => value.Write(Data[0x18..]);
}
public Span<short> EventFlags => MemoryMarshal.Cast<byte, short>(Data.Slice(0x20, 0x100));
public const int MaxRoom = 6;
public const int RoomStart = 0x120;
public virtual IPlayerRoom GetRoom(int roomIndex)
{
if ((uint)roomIndex >= MaxRoom)
throw new ArgumentOutOfRangeException(nameof(roomIndex));
var data = Data.Slice(RoomStart + (roomIndex * PlayerRoom1.SIZE), PlayerRoom1.SIZE);
return new PlayerRoom1(data.ToArray());
}
public virtual void SetRoom(int roomIndex, IPlayerRoom room)
{
if ((uint)roomIndex >= MaxRoom)
throw new ArgumentOutOfRangeException(nameof(roomIndex));
var dest = Data.Slice(RoomStart + (roomIndex * PlayerRoom1.SIZE), PlayerRoom1.SIZE);
room.Write().CopyTo(dest);
}
public sbyte NPC1 { get => (sbyte)Data[0x263D0]; set => Data[0x263D0] = (byte)value; }
public sbyte NPC2 { get => (sbyte)Data[0x263D1]; set => Data[0x263D1] = (byte)value; }
// 2 bytes padding
public Item DoorDecoItemName
{
get => Data.Slice(0x263D4, 8).ToArray().ToClass<Item>();
set => value.ToBytesClass().CopyTo(Data[0x263D4..]);
}
public bool PlayerHouseFlag { get => Data[0x263DC] != 0; set => Data[0x263DC] = (byte)(value ? 1 : 0); }
public Item PostItemName
{
get => Data.Slice(0x263E0, 8).ToArray().ToClass<Item>();
set => value.ToBytesClass().CopyTo(Data[0x263E0..]);
}
public Item OrderPostItemName
{
get => Data.Slice(0x263E8, 8).ToArray().ToClass<Item>();
set => value.ToBytesClass().CopyTo(Data[0x263E8..]);
}
// cockroach @ 0x263f0 -- meh
public PlayerHouse2 Upgrade()
{
var data = new byte[PlayerHouse2.SIZE];
Data[..0x120].CopyTo(data.AsSpan(0)); // HouseLevel -> EventFlag
for (int i = 0; i < MaxRoom; i++)
((PlayerRoom1)GetRoom(i)).Upgrade().Write().CopyTo(data.AsSpan(0x120 + (i * PlayerRoom2.SIZE))); // RoomList
Data.Slice(0x263D0, 0x30).CopyTo(data.AsSpan(0x289F8)); // PlayerList -> Cockroach
return new PlayerHouse2(data);
}
}