mirror of
https://github.com/kwsch/NHSE.git
synced 2026-04-17 14:16:02 -05:00
ReloadAll() wasn't loading the villager that was currently selected on load (or 0 if not in panel) leading to incorrect villager import. Fix: Add public Reload() method to VillagerEditor to call LoadVillagers() and call it after Villagers and Origin are loaded. Reset Villager index NUD to 0 in LoadVillagers() so the slot is moved to 0 and then load occurs (so UI is refreshed and villager is loaded).
322 lines
11 KiB
C#
322 lines
11 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using NHSE.Core;
|
|
using NHSE.Sprites;
|
|
using NHSE.Villagers;
|
|
|
|
namespace NHSE.WinForms;
|
|
|
|
public partial class VillagerEditor : UserControl
|
|
{
|
|
public IVillager[] Villagers;
|
|
public IVillagerOrigin Origin;
|
|
private readonly HorizonSave SAV;
|
|
private int VillagerIndex = -1;
|
|
private int PlayerIndex = -1;
|
|
private bool Loading;
|
|
|
|
public VillagerEditor(IVillager[] villagers, IVillagerOrigin origin, HorizonSave sav, bool hasHouses, int playerIndex)
|
|
{
|
|
InitializeComponent();
|
|
Villagers = villagers;
|
|
Origin = origin;
|
|
SAV = sav;
|
|
PlayerIndex = playerIndex;
|
|
LoadVillagers();
|
|
|
|
B_EditHouses.Visible = hasHouses;
|
|
}
|
|
|
|
public void Save() => SaveVillager(VillagerIndex);
|
|
|
|
public void Reload() => LoadVillagers();
|
|
|
|
private void LoadVillagers()
|
|
{
|
|
CB_Personality.Items.Clear();
|
|
var personalities = Enum.GetNames<VillagerPersonality>();
|
|
CB_Personality.Items.AddRange(personalities);
|
|
|
|
VillagerIndex = -1;
|
|
NUD_Villager.Value = 0;
|
|
LoadVillager(0);
|
|
}
|
|
|
|
private void LoadVillager(object sender, EventArgs e) => LoadVillager((int)NUD_Villager.Value);
|
|
|
|
private void LoadVillager(int index)
|
|
{
|
|
if (VillagerIndex >= 0)
|
|
SaveVillager(VillagerIndex);
|
|
|
|
if (index < 0)
|
|
return;
|
|
|
|
LoadVillager(Villagers[index]);
|
|
VillagerIndex = index;
|
|
}
|
|
|
|
private void LoadVillager(IVillager v)
|
|
{
|
|
Loading = true;
|
|
NUD_Species.Value = v.Species;
|
|
NUD_Variant.Value = v.Variant;
|
|
CB_Personality.SelectedIndex = (int)v.Personality;
|
|
TB_Catchphrase.Text = v.CatchPhrase;
|
|
CHK_VillagerMovingOut.Checked = v.MovingOut;
|
|
Loading = false;
|
|
}
|
|
|
|
private void SaveVillager(int index)
|
|
{
|
|
var v = Villagers[index];
|
|
|
|
v.Species = (byte)NUD_Species.Value;
|
|
v.Variant = (byte)NUD_Variant.Value;
|
|
v.Personality = (VillagerPersonality)CB_Personality.SelectedIndex;
|
|
v.CatchPhrase = TB_Catchphrase.Text;
|
|
v.MovingOut = CHK_VillagerMovingOut.Checked;
|
|
}
|
|
|
|
private void CHK_VillagerMovingOut_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (Loading)
|
|
return;
|
|
|
|
if (!CHK_VillagerMovingOut.Checked)
|
|
return;
|
|
|
|
WinFormsUtil.Alert(MessageStrings.MsgMoveOut, MessageStrings.MsgMoveOutSuggest);
|
|
}
|
|
|
|
private void B_DumpVillager_Click(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys == Keys.Shift)
|
|
{
|
|
using var fbd = new FolderBrowserDialog();
|
|
if (fbd.ShowDialog() != DialogResult.OK)
|
|
return;
|
|
|
|
var dir = Path.GetDirectoryName(fbd.SelectedPath);
|
|
if (dir == null || !Directory.Exists(dir))
|
|
return;
|
|
Villagers.Dump(fbd.SelectedPath);
|
|
return;
|
|
}
|
|
|
|
var name = L_ExternalName.Text;
|
|
using var sfd = new SaveFileDialog();
|
|
sfd.Filter = "New Horizons Villager (*.nhv)|*.nhv|" +
|
|
"New Horizons Villager (*.nhv2)|*.nhv2|" +
|
|
"All files (*.*)|*.*";
|
|
sfd.FileName = $"{name}.{Villagers[VillagerIndex].Extension}";
|
|
if (sfd.ShowDialog() != DialogResult.OK)
|
|
return;
|
|
|
|
SaveVillager(VillagerIndex);
|
|
var v = Villagers[VillagerIndex];
|
|
File.WriteAllBytes(sfd.FileName, v.Write());
|
|
}
|
|
|
|
private void B_LoadVillager_Click(object sender, EventArgs e)
|
|
{
|
|
var name = L_ExternalName.Text;
|
|
using var ofd = new OpenFileDialog();
|
|
ofd.Filter = "New Horizons Villager (*.nhv)|*.nhv|" +
|
|
"New Horizons Villager (*.nhv2)|*.nhv2|" +
|
|
"All files (*.*)|*.*";
|
|
ofd.FileName = $"{name}.{Villagers[VillagerIndex].Extension}";
|
|
if (ofd.ShowDialog() != DialogResult.OK)
|
|
return;
|
|
|
|
var path = ofd.FileName;
|
|
var expectLength = SAV.Main.Offsets.VillagerSize;
|
|
var fi = new FileInfo(path);
|
|
if (!VillagerConverter.IsCompatible((int)fi.Length, expectLength))
|
|
{
|
|
WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path);
|
|
return;
|
|
}
|
|
|
|
var data = File.ReadAllBytes(ofd.FileName);
|
|
data = VillagerConverter.GetCompatible(data, expectLength);
|
|
if (data.Length != expectLength)
|
|
{
|
|
WinFormsUtil.Error(string.Format(MessageStrings.MsgDataSizeMismatchImport, fi.Length, expectLength), path);
|
|
return;
|
|
}
|
|
|
|
var v = SAV.Main.Offsets.ReadVillager(data);
|
|
var player0 = Origin;
|
|
if (!v.IsOriginatedFrom(player0))
|
|
{
|
|
string msg = string.Format(MessageStrings.MsgDataDidNotOriginateFromHost_0, player0.PlayerName);
|
|
var result = WinFormsUtil.Prompt(MessageBoxButtons.YesNoCancel, msg, MessageStrings.MsgAskUpdateValues);
|
|
if (result == DialogResult.Cancel)
|
|
return;
|
|
if (result == DialogResult.Yes)
|
|
v.ChangeOrigins(player0, v.Write());
|
|
}
|
|
|
|
LoadVillager(Villagers[VillagerIndex] = v);
|
|
}
|
|
|
|
private void B_EditWear_Click(object sender, EventArgs e)
|
|
{
|
|
var v = Villagers[VillagerIndex];
|
|
var items = v.WearStockList;
|
|
using var editor = new PlayerItemEditor(items, 8, 3);
|
|
if (editor.ShowDialog() == DialogResult.OK)
|
|
v.WearStockList = items;
|
|
}
|
|
|
|
private void B_EditFurniture_Click(object sender, EventArgs e)
|
|
{
|
|
var v = Villagers[VillagerIndex];
|
|
var items = v.FtrStockList;
|
|
using var editor = new PlayerItemEditor(items, 8, 4);
|
|
if (editor.ShowDialog() == DialogResult.OK)
|
|
v.FtrStockList = items;
|
|
}
|
|
|
|
private void B_EditVillagerFlags_Click(object sender, EventArgs e)
|
|
{
|
|
var v = Villagers[VillagerIndex];
|
|
var flags = v.GetEventFlagsSave();
|
|
using var editor = new VillagerFlagEditor(flags);
|
|
if (editor.ShowDialog() == DialogResult.OK)
|
|
v.SetEventFlagsSave(flags);
|
|
}
|
|
|
|
private string GetCurrentVillagerInternalName() => VillagerUtil.GetInternalVillagerName((VillagerSpecies)NUD_Species.Value, (int)NUD_Variant.Value);
|
|
private void ChangeVillager(object sender, EventArgs e) => ChangeVillager();
|
|
private void ChangeVillager()
|
|
{
|
|
var name = GetCurrentVillagerInternalName();
|
|
L_InternalName.Text = name;
|
|
L_ExternalName.Text = GameInfo.Strings.GetVillager(name);
|
|
PB_Villager.Image = VillagerSprite.GetVillagerSprite(name);
|
|
}
|
|
|
|
private void B_EditHouse_Click(object sender, EventArgs e)
|
|
{
|
|
SaveVillager(VillagerIndex);
|
|
var villagers = SAV.Main.GetVillagers();
|
|
var houses = SAV.Main.GetVillagerHouses();
|
|
using var editor = new VillagerHouseEditor(houses, villagers, SAV.Main, VillagerIndex);
|
|
if (editor.ShowDialog() == DialogResult.OK)
|
|
SAV.Main.SetVillagerHouses(houses);
|
|
}
|
|
|
|
private static void ShowContextMenuBelow(ToolStripDropDown c, Control n) => c.Show(n.PointToScreen(new System.Drawing.Point(0, n.Height)));
|
|
private void B_EditVillager_Click(object sender, EventArgs e) => ShowContextMenuBelow(CM_EditVillager, B_EditVillager);
|
|
|
|
private void B_EditVillagerRoom_Click(object sender, EventArgs e)
|
|
{
|
|
var v = Villagers[VillagerIndex];
|
|
using var editor = new SaveRoomFloorWallEditor(v.Room);
|
|
if (editor.ShowDialog() == DialogResult.OK)
|
|
v.Room = editor.Entity;
|
|
}
|
|
|
|
private void B_EditVillagerDesign_Click(object sender, EventArgs e)
|
|
{
|
|
var player = SAV.Players[PlayerIndex];
|
|
var v = Villagers[VillagerIndex];
|
|
DesignPatternPRO[] tmp = [v.Design];
|
|
using var editor = new PatternEditorPRO(tmp, player);
|
|
if (editor.ShowDialog() == DialogResult.OK)
|
|
v.Design = tmp[0];
|
|
}
|
|
|
|
private void B_EditVillagerPlayerMemories_Click(object sender, EventArgs e)
|
|
{
|
|
if (ModifierKeys == Keys.Shift)
|
|
{
|
|
var prompt = WinFormsUtil.Prompt(MessageBoxButtons.YesNo, MessageStrings.MsgVillagerFriendshipMax);
|
|
if (prompt != DialogResult.Yes)
|
|
return;
|
|
foreach (var villager in Villagers)
|
|
villager.SetFriendshipAll();
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
return;
|
|
}
|
|
|
|
var v = Villagers[VillagerIndex];
|
|
using var editor = new VillagerMemoryEditor(v);
|
|
if (editor.ShowDialog() == DialogResult.OK)
|
|
{ } // editor saves our changes
|
|
}
|
|
|
|
private void B_EditDIYTimer_Click(object sender, EventArgs e)
|
|
{
|
|
var v = Villagers[VillagerIndex];
|
|
using var editor = new VillagerDIYTimerEditor(v);
|
|
if (editor.ShowDialog() == DialogResult.OK)
|
|
{ } // editor saves our changes
|
|
}
|
|
|
|
private void B_MoveOutAllVillagers_Click(object sender, EventArgs e)
|
|
{
|
|
if (Loading)
|
|
return;
|
|
|
|
var prompt = WinFormsUtil.Prompt(MessageBoxButtons.OKCancel, MessageStrings.MsgMoveOutAll);
|
|
if (prompt != DialogResult.OK)
|
|
return;
|
|
|
|
foreach (var villager in Villagers)
|
|
villager.MovingOut = true;
|
|
CHK_VillagerMovingOut.Checked = true;
|
|
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
}
|
|
|
|
private void B_SetPhraseOriginal_Click(object sender, EventArgs e)
|
|
{
|
|
var internalName = GetCurrentVillagerInternalName();
|
|
TB_Catchphrase.Text = GameInfo.Strings.GetVillagerDefaultPhrase(internalName);
|
|
}
|
|
|
|
private void B_ReplaceVillager_Click(object sender, EventArgs e)
|
|
{
|
|
if (!Clipboard.ContainsText())
|
|
{
|
|
WinFormsUtil.Error(MessageStrings.MsgVillagerReplaceNoText);
|
|
return;
|
|
}
|
|
|
|
var internalName = Clipboard.GetText().Trim();
|
|
if (!VillagerResources.IsVillagerDataKnown(internalName))
|
|
{
|
|
var clip = internalName;
|
|
internalName = GameInfo.Strings.VillagerMap.FirstOrDefault(z => string.Equals(z.Value, internalName, StringComparison.InvariantCultureIgnoreCase)).Key;
|
|
if (internalName is null)
|
|
{
|
|
WinFormsUtil.Error(string.Format(MessageStrings.MsgVillagerReplaceUnknownName, clip));
|
|
return;
|
|
}
|
|
}
|
|
|
|
var index = VillagerIndex;
|
|
var villager = Villagers[index];
|
|
if (villager is not Villager2 v2)
|
|
{
|
|
WinFormsUtil.Error(MessageStrings.MsgVillagerReplaceOutdatedSaveFormat);
|
|
return;
|
|
}
|
|
|
|
var houses = SAV.Main.GetVillagerHouses();
|
|
var houseIndex = Array.FindIndex(houses, z => z.NPC1 == index);
|
|
var exist = new VillagerInfo(v2, houses[houseIndex]);
|
|
var replace = VillagerSwap.GetReplacementVillager(exist, internalName);
|
|
|
|
var nh = new VillagerHouse1(replace.House);
|
|
SAV.Main.SetVillagerHouse(nh, houseIndex);
|
|
var nv = new Villager2(replace.Villager);
|
|
LoadVillager(Villagers[index] = nv);
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
}
|
|
} |