pkNX/pkNX.WinForms/Subforms/AreaEditor8a.cs
duckdoom4 56cb75340a Minor refactor
Rename all the interfaces to give them a more sensible name
Rename the Set<InterfaceName> extension methods to Import<InterfaceName>, since evenI got confused about it's purpose for a while. It's supposed to be used by the data importer to fill in missing properties from older generation data. This means it should actually not set every property that is part of the interface and 'set' is therefor a confusing name.
Update PokeDataUI to fix layout of new property names
2023-07-05 19:35:57 +02:00

172 lines
5.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using pkNX.Containers;
using pkNX.Game;
using pkNX.Randomization;
using pkNX.Structures;
using pkNX.Structures.FlatBuffers;
using pkNX.Structures.FlatBuffers.Arceus;
using static pkNX.Structures.Species;
using Util = pkNX.Randomization.Util;
namespace pkNX.WinForms.Subforms;
public partial class AreaEditor8a : Form
{
private readonly GameManagerPLA ROM;
private readonly GFPack Resident;
private readonly AreaSettingsTable Settings;
private readonly string[] AreaNames;
private ResidentArea Area;
private int AreaIndex;
private readonly bool Loading;
public AreaEditor8a(GameManagerPLA rom)
{
ROM = rom;
Resident = (GFPack)ROM.GetFile(GameFile.Resident);
var bin_settings = Resident.GetDataFullPath("bin/field/resident/AreaSettings.bin");
Settings = FlatBufferConverter.DeserializeFrom<AreaSettingsTable>(bin_settings);
AreaNames = Settings.Table.Select(z => z.Name).ToArray();
const string startingArea = "ha_area01";
(AreaIndex, Area) = LoadAreaByName(startingArea);
InitializeComponent();
PG_RandSettings.SelectedObject = EditUtil.Settings.Species;
Loading = true;
CB_Area.Items.AddRange(Settings.Table.Select(z => z.FriendlyAreaName).ToArray());
CB_Area.SelectedIndex = AreaIndex;
LoadArea();
Loading = false;
}
private (int index, ResidentArea area) LoadAreaByName(string name)
{
var index = Array.IndexOf(AreaNames, name);
var area = new ResidentArea(Resident, Settings.Find(name));
area.LoadInfo();
return (index, area);
}
private void CB_Map_SelectedIndexChanged(object sender, EventArgs e)
{
if (Loading)
return;
SaveArea();
(AreaIndex, Area) = LoadAreaByName(AreaNames[CB_Area.SelectedIndex]);
LoadArea();
}
private void B_Randomize_Click(object sender, EventArgs e)
{
SaveArea();
RandomizeArea(Area, (SpeciesSettings)PG_RandSettings.SelectedObject);
LoadArea();
System.Media.SystemSounds.Asterisk.Play();
}
private void RandomizeArea(ResidentArea area, SpeciesSettings settings)
{
var pt = ROM.Data.PersonalData;
var rand = new SpeciesRandomizer(ROM.Info, pt);
var hasForm = new HashSet<int>();
var banned = new HashSet<int>();
foreach (var pi in pt.Table.Cast<IPersonalMisc_SWSH>())
{
if (pi.IsPresentInGame)
{
banned.Remove(pi.DexIndexNational);
hasForm.Add(pi.DexIndexNational);
}
else if (!hasForm.Contains(pi.DexIndexNational))
{
banned.Add(pi.DexIndexNational);
}
}
settings.Legends = false; // Legendary encounter slot conditions require you to not have captured the Legendary in order to encounter them; ban altogether.
rand.Initialize(settings, banned.ToArray());
var formRand = pt.Table.Cast<IPersonalMisc_SWSH>()
.Where(z => z.IsPresentInGame && !(Legal.BattleExclusiveForms.Contains(z.DexIndexNational) || Legal.BattleFusions.Contains(z.DexIndexNational)))
.GroupBy(z => z.DexIndexNational)
.ToDictionary(z => z.Key, z => z.ToList());
var encounters = area.Encounters;
foreach (var table in encounters.Table)
{
foreach (var enc in table.Table)
{
if (enc.ShinyLock is not ShinyType.Random)
continue;
// to progress the story in Cobalt Coastlands, you are required to show Iscan a Dusclops; ensure one can be captured
if (enc.Species is (int)Dusclops && table.TableID is 7663383561364099763)
continue;
var spec = rand.GetRandomSpecies(enc.Species);
enc.Species = spec;
enc.Form = GetRandomForm(spec);
enc.ClearMoves();
}
}
int GetRandomForm(int spec)
{
if (!formRand.TryGetValue((ushort)spec, out var entries))
return 0;
var count = entries.Count;
return (Species)spec switch
{
Growlithe or Arcanine or Voltorb or Electrode or Typhlosion or Qwilfish or Samurott or Lilligant or Zorua or Zoroark or Braviary or Sliggoo or Goodra or Avalugg or Decidueye => 1,
Basculin => 2,
Kleavor => 0,
_ => Util.Random.Next(0, count),
};
}
}
private void LoadArea()
{
Debug.WriteLine($"Loading Area {AreaIndex}");
PG_AreaSettings.SelectedObject = Area.Settings;
Edit_Encounters.LoadTable(Area.Encounters.Table, Area.Settings.Encounters);
Edit_RegularSpawners.LoadTable(Area.Spawners.Table, Area.Settings.Spawners);
Edit_WormholeSpawners.LoadTable(Area.Wormholes.Table, Area.Settings.WormholeSpawners);
Edit_LandmarkSpawns.LoadTable(Area.LandItems.Table, Area.Settings.LandmarkItemSpawns);
}
private void SaveArea()
{
Debug.WriteLine($"Saving Area {AreaIndex}");
Area.SaveInfo();
}
private void B_Save_Click(object sender, EventArgs e)
{
Save = true;
Close();
}
private bool Save;
private void AreaEditor8a_FormClosing(object sender, FormClosingEventArgs e)
{
if (Save)
SaveArea();
else
Resident.CancelEdits();
}
}