mirror of
https://github.com/kwsch/pkNX.git
synced 2026-04-05 00:45:04 -05:00
File scoped namespaces NET6 for GUI handle nullable references add editorconfig (mostly for newline at end of file)
443 lines
15 KiB
C#
443 lines
15 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Windows.Forms;
|
|
using pkNX.Containers;
|
|
using pkNX.Game;
|
|
using pkNX.Randomization;
|
|
using pkNX.Structures;
|
|
using pkNX.Structures.FlatBuffers;
|
|
|
|
namespace pkNX.WinForms;
|
|
|
|
public sealed partial class GGWE : Form
|
|
{
|
|
private readonly EncounterArchive7b Tables;
|
|
private readonly GameManagerGG ROM;
|
|
private int entry = -1;
|
|
|
|
public GGWE(GameManagerGG rom, EncounterArchive7b obj)
|
|
{
|
|
InitializeComponent();
|
|
if (obj.EncounterTables.Length == 0 || obj.EncounterTables[0].GroundTable.Length == 0)
|
|
{
|
|
WinFormsUtil.Error("Bad data provided.", $"Unable to parse to {nameof(EncounterArchive7b)} data.");
|
|
Close();
|
|
}
|
|
|
|
ROM = rom;
|
|
|
|
var spec = rom.GetStrings(TextName.SpeciesNames);
|
|
var species = (string[])spec.Clone();
|
|
species[0] = "";
|
|
EncounterList.SpeciesNames = species;
|
|
var locs = rom.GetStrings(TextName.metlist_00000);
|
|
|
|
EL_Ground.Initialize();
|
|
EL_Water.Initialize();
|
|
EL_Old.Initialize();
|
|
EL_Good.Initialize();
|
|
EL_Super.Initialize();
|
|
EL_Sky.Initialize();
|
|
|
|
TC_Tables.Controls.Remove(Tab_Old);
|
|
TC_Tables.Controls.Remove(Tab_Good);
|
|
TC_Tables.Controls.Remove(Tab_Super);
|
|
EL_Old.OverworldSpawn = EL_Good.OverworldSpawn = EL_Super.OverworldSpawn = false;
|
|
L_Rank.Visible = NUD_RankMin.Visible = NUD_RankMax.Visible = false;
|
|
|
|
PG_Species.SelectedObject = EditUtil.Settings.Species;
|
|
|
|
Tables = obj;
|
|
LoadFile(locs);
|
|
|
|
EL_Ground.ShowForm = false;
|
|
EL_Water.ShowForm = false;
|
|
EL_Old.ShowForm = false;
|
|
EL_Good.ShowForm = false;
|
|
EL_Super.ShowForm = false;
|
|
EL_Sky.ShowForm = false;
|
|
CB_Location.SelectedIndex = 0;
|
|
}
|
|
|
|
public void LoadFile(string[] locationNames)
|
|
{
|
|
var locs = Tables.EncounterTables.Select(z => z.ZoneID);
|
|
var names = GetNames(locs, locationNames);
|
|
var dupeNamed = GetScreenedNames(names);
|
|
|
|
CB_Location.Items.Clear();
|
|
CB_Location.Items.AddRange(dupeNamed.ToArray());
|
|
}
|
|
|
|
private static IEnumerable<string> GetNames(IEnumerable<ulong> locs, string[] locationNames)
|
|
{
|
|
return locs
|
|
.Select(z => DictHash[z]) // loc internal name
|
|
.Select(z => LocIDTable[z]) // loc ID
|
|
.Select(z => locationNames[z]); // loc external name (pkmdata)
|
|
}
|
|
|
|
private static IEnumerable<string> GetScreenedNames(IEnumerable<string> names)
|
|
{
|
|
int ctr = 0;
|
|
string? prev = null;
|
|
foreach (var name in names)
|
|
{
|
|
if (name != prev)
|
|
{
|
|
ctr = 1;
|
|
yield return name;
|
|
}
|
|
else
|
|
{
|
|
ctr++;
|
|
yield return $"{name} ({ctr})";
|
|
}
|
|
prev = name;
|
|
}
|
|
}
|
|
|
|
private static readonly Dictionary<string, int> LocIDTable = new()
|
|
{
|
|
["forest001"] = 39,
|
|
["r004d0101"] = 40,
|
|
["r004d0102"] = 40,
|
|
["r004d0103"] = 40,
|
|
["r010d0101"] = 41,
|
|
["r010d0102"] = 41,
|
|
["r010r0101"] = 42,
|
|
["r011d0101"] = 43,
|
|
|
|
["r020d0101"] = 44,
|
|
["r020d0102"] = 44,
|
|
["r020d0103"] = 44,
|
|
["r020d0104_1"] = 44,
|
|
["r020d0104_2"] = 44,
|
|
["r020d0105_1"] = 44,
|
|
["r020d0105_2"] = 44,
|
|
["r023d0101"] = 45,
|
|
["r023d0102"] = 45,
|
|
["r023d0103"] = 45,
|
|
["road001"] = 3,
|
|
["road002_1"] = 4,
|
|
["road002_2"] = 4,
|
|
["road003"] = 5,
|
|
["road004_1"] = 6,
|
|
["road004_2"] = 6,
|
|
["road005"] = 7,
|
|
["road006"] = 8,
|
|
["road007"] = 9,
|
|
["road008"] = 10,
|
|
["road009"] = 11,
|
|
["road010_1"] = 12,
|
|
["road010_2"] = 12,
|
|
["road011_1"] = 13,
|
|
["road011_2"] = 13,
|
|
["road012"] = 14,
|
|
["road013"] = 15,
|
|
["road014"] = 16,
|
|
["road015_1"] = 17,
|
|
["road015_2"] = 17,
|
|
["road016_1"] = 18,
|
|
["road016_2"] = 18,
|
|
["road017"] = 19,
|
|
["road018_1"] = 20,
|
|
["road018_2"] = 20,
|
|
["road019"] = 21,
|
|
["road020"] = 22,
|
|
["road020_2"] = 22,
|
|
["road021"] = 23,
|
|
["road022"] = 24,
|
|
["road023"] = 25,
|
|
["road024"] = 26,
|
|
["road025"] = 27,
|
|
["t004d0101"] = 46,
|
|
["t004d0102"] = 46,
|
|
["t004d0103"] = 46,
|
|
["t005r0303"] = 47,
|
|
["t005r0304"] = 47,
|
|
["t005r0305"] = 47,
|
|
["t005r0306"] = 47,
|
|
["t009r0201"] = 51,
|
|
["t009r0202"] = 51,
|
|
["t009r0203"] = 51,
|
|
["t009r0204"] = 51,
|
|
["town001"] = 28,
|
|
["town002"] = 29,
|
|
["town003"] = 30,
|
|
["town004"] = 31,
|
|
["town005"] = 32,
|
|
["town006"] = 33,
|
|
["town007"] = 34,
|
|
["town008"] = 35,
|
|
["town009"] = 36,
|
|
};
|
|
|
|
private static readonly Dictionary<ulong, string> DictHash = LocIDTable
|
|
.Select(z => new KeyValuePair<ulong, string>(FnvHash.HashFnv1a_64(z.Key), z.Key))
|
|
.ToDictionary(z => z.Key, z => z.Value);
|
|
|
|
private void CB_Location_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
SaveEntry(entry);
|
|
entry = CB_Location.SelectedIndex;
|
|
var id = Tables.EncounterTables[entry].ZoneID;
|
|
var iname = LocIDTable.First(z => FnvHash.HashFnv1a_64(z.Key) == id).Key;
|
|
L_Hash.Text = Tables.EncounterTables[entry].ZoneID.ToString("X16") + " " + iname;
|
|
LoadEntry(entry);
|
|
}
|
|
|
|
private void LoadEntry(int i)
|
|
{
|
|
var arr = Tables.EncounterTables[i];
|
|
|
|
NUD_RankMin.Value = arr.TrainerRankMin;
|
|
NUD_RankMax.Value = arr.TrainerRankMax;
|
|
|
|
EL_Ground.LoadSlots(arr.GroundTable);
|
|
EL_Water.LoadSlots(arr.WaterTable);
|
|
EL_Old.LoadSlots(arr.OldRodTable);
|
|
EL_Good.LoadSlots(arr.GoodRodTable);
|
|
EL_Super.LoadSlots(arr.SuperRodTable);
|
|
EL_Sky.LoadSlots(arr.SkyTable);
|
|
|
|
EL_Ground.NUD_Min.Value = arr.GroundTableLevelMin;
|
|
EL_Ground.NUD_Max.Value = arr.GroundTableLevelMax;
|
|
EL_Ground.NUD_SpawnRate.Value = arr.GroundTableEncounterRate;
|
|
EL_Ground.NUD_Count.Value = arr.GroundSpawnCountMax;
|
|
EL_Ground.NUD_Duration.Value = arr.GroundSpawnDuration;
|
|
|
|
EL_Water.NUD_Min.Value = arr.WaterTableLevelMin;
|
|
EL_Water.NUD_Max.Value = arr.WaterTableLevelMax;
|
|
EL_Water.NUD_SpawnRate.Value = arr.WaterTableEncounterRate;
|
|
EL_Water.NUD_Count.Value = arr.WaterSpawnCountMax;
|
|
EL_Water.NUD_Duration.Value = arr.WaterSpawnDuration;
|
|
|
|
EL_Old.NUD_Min.Value = arr.OldRodTableLevelMin;
|
|
EL_Old.NUD_Max.Value = arr.OldRodTableLevelMax;
|
|
EL_Old.NUD_SpawnRate.Value = arr.OldRodTableEncounterRate;
|
|
|
|
EL_Good.NUD_Min.Value = arr.GoodRodTableLevelMin;
|
|
EL_Good.NUD_Max.Value = arr.GoodRodTableLevelMax;
|
|
EL_Good.NUD_SpawnRate.Value = arr.GoodRodTableEncounterRate;
|
|
|
|
EL_Super.NUD_Min.Value = arr.SuperRodTableLevelMin;
|
|
EL_Super.NUD_Max.Value = arr.SuperRodTableLevelMax;
|
|
EL_Super.NUD_SpawnRate.Value = arr.SuperRodTableEncounterRate;
|
|
|
|
EL_Sky.NUD_Min.Value = arr.SkyTableLevelMin;
|
|
EL_Sky.NUD_Max.Value = arr.SkyTableLevelMax;
|
|
EL_Sky.NUD_SpawnRate.Value = arr.SkyTableEncounterRate;
|
|
EL_Sky.NUD_Count.Value = arr.SkySpawnCountMax;
|
|
EL_Sky.NUD_Duration.Value = arr.SkySpawnDuration;
|
|
}
|
|
|
|
private void SaveEntry(int i)
|
|
{
|
|
if (i < 0)
|
|
return;
|
|
var arr = Tables.EncounterTables[i];
|
|
|
|
arr.TrainerRankMin = (int)NUD_RankMin.Value;
|
|
arr.TrainerRankMax = (int)NUD_RankMax.Value;
|
|
|
|
arr.GroundTableLevelMin = (int)EL_Ground.NUD_Min.Value;
|
|
arr.GroundTableLevelMax = (int)EL_Ground.NUD_Max.Value;
|
|
arr.GroundTableEncounterRate = (int)EL_Ground.NUD_SpawnRate.Value;
|
|
arr.GroundSpawnCountMax = (int)EL_Ground.NUD_Count.Value;
|
|
arr.GroundSpawnDuration = (int)EL_Ground.NUD_Duration.Value;
|
|
|
|
arr.WaterTableLevelMin = (int)EL_Water.NUD_Min.Value;
|
|
arr.WaterTableLevelMax = (int)EL_Water.NUD_Max.Value;
|
|
arr.WaterTableEncounterRate = (int)EL_Water.NUD_SpawnRate.Value;
|
|
arr.WaterSpawnCountMax = (int)EL_Water.NUD_Count.Value;
|
|
arr.WaterSpawnDuration = (int)EL_Water.NUD_Duration.Value;
|
|
|
|
arr.OldRodTableLevelMin = (int)EL_Old.NUD_Min.Value;
|
|
arr.OldRodTableLevelMax = (int)EL_Old.NUD_Max.Value;
|
|
arr.OldRodTableEncounterRate = (int)EL_Old.NUD_SpawnRate.Value;
|
|
|
|
arr.GoodRodTableLevelMin = (int)EL_Good.NUD_Min.Value;
|
|
arr.GoodRodTableLevelMax = (int)EL_Good.NUD_Max.Value;
|
|
arr.GoodRodTableEncounterRate = (int)EL_Good.NUD_SpawnRate.Value;
|
|
|
|
arr.SuperRodTableLevelMin = (int)EL_Super.NUD_Min.Value;
|
|
arr.SuperRodTableLevelMax = (int)EL_Super.NUD_Max.Value;
|
|
arr.SuperRodTableEncounterRate = (int)EL_Super.NUD_SpawnRate.Value;
|
|
|
|
arr.SkyTableLevelMin = (int)EL_Sky.NUD_Min.Value;
|
|
arr.SkyTableLevelMax = (int)EL_Sky.NUD_Max.Value;
|
|
arr.SkyTableEncounterRate = (int)EL_Sky.NUD_SpawnRate.Value;
|
|
arr.SkySpawnCountMax = (int)EL_Sky.NUD_Count.Value;
|
|
arr.SkySpawnDuration = (int)EL_Sky.NUD_Duration.Value;
|
|
|
|
EL_Ground.SaveCurrent();
|
|
EL_Water.SaveCurrent();
|
|
EL_Old.SaveCurrent();
|
|
EL_Good.SaveCurrent();
|
|
EL_Super.SaveCurrent();
|
|
EL_Sky.SaveCurrent();
|
|
}
|
|
|
|
private void B_Save_Click(object sender, EventArgs e)
|
|
{
|
|
SaveEntry(entry);
|
|
EL_Ground.SaveCurrent();
|
|
EL_Water.SaveCurrent();
|
|
EL_Old.SaveCurrent();
|
|
EL_Good.SaveCurrent();
|
|
EL_Super.SaveCurrent();
|
|
EL_Sky.SaveCurrent();
|
|
|
|
DialogResult = DialogResult.OK;
|
|
|
|
Close();
|
|
}
|
|
|
|
private void B_ModCount_Click(object sender, EventArgs e)
|
|
{
|
|
SaveEntry(entry);
|
|
foreach (var area in Tables.EncounterTables)
|
|
{
|
|
if (area.GroundSpawnCountMax != 0)
|
|
area.GroundSpawnCountMax = (int)NUD_ModCount.Value;
|
|
if (area.WaterSpawnCountMax != 0)
|
|
area.WaterSpawnCountMax = (int)NUD_ModCount.Value;
|
|
if (area.SkySpawnCountMax != 0)
|
|
area.SkySpawnCountMax = (int)NUD_ModCount.Value;
|
|
}
|
|
LoadEntry(entry);
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
}
|
|
|
|
private void B_ModRate_Click(object sender, EventArgs e)
|
|
{
|
|
SaveEntry(entry);
|
|
foreach (var area in Tables.EncounterTables)
|
|
{
|
|
if (area.GroundTableEncounterRate != 0)
|
|
area.GroundTableEncounterRate = (int)NUD_ModCount.Value;
|
|
if (area.WaterTableEncounterRate != 0)
|
|
area.WaterTableEncounterRate = (int)NUD_ModCount.Value;
|
|
if (area.SkyTableEncounterRate != 0)
|
|
area.SkyTableEncounterRate = (int)NUD_ModCount.Value;
|
|
}
|
|
LoadEntry(entry);
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
}
|
|
|
|
private void B_ModDuration_Click(object sender, EventArgs e)
|
|
{
|
|
SaveEntry(entry);
|
|
foreach (var area in Tables.EncounterTables)
|
|
{
|
|
if (area.GroundSpawnDuration != 0)
|
|
area.GroundSpawnDuration = (int)NUD_ModDuration.Value;
|
|
if (area.WaterSpawnDuration != 0)
|
|
area.WaterSpawnDuration = (int)NUD_ModDuration.Value;
|
|
if (area.SkySpawnDuration != 0)
|
|
area.SkySpawnDuration = (int)NUD_ModDuration.Value;
|
|
}
|
|
LoadEntry(entry);
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
}
|
|
|
|
private void B_RandAll_Click(object sender, EventArgs e)
|
|
{
|
|
SaveEntry(entry);
|
|
var settings = (SpeciesSettings)PG_Species.SelectedObject;
|
|
settings.Gen2 = settings.Gen3 = settings.Gen4 = settings.Gen5 = settings.Gen6 = settings.Gen7 = false;
|
|
var rand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
|
rand.Initialize(settings, 808, 809);
|
|
RandomizeWild(rand, CHK_FillEmpty.Checked, CHK_Level.Checked);
|
|
LoadEntry(entry);
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
}
|
|
|
|
private void RandomizeWild(SpeciesRandomizer rand, bool fill, bool boost)
|
|
{
|
|
var pt = ROM.Data.PersonalData;
|
|
bool IsGrassOrWater(int s) => pt[s].IsType(Types.Water) || pt[s].IsType(Types.Grass);
|
|
|
|
foreach (var area in Tables.EncounterTables)
|
|
{
|
|
if (boost)
|
|
{
|
|
area.GroundTableLevelMin = Legal.GetModifiedLevel(area.GroundTableLevelMin, (double)NUD_LevelBoost.Value);
|
|
area.GroundTableLevelMax = Legal.GetModifiedLevel(area.GroundTableLevelMax, (double)NUD_LevelBoost.Value);
|
|
|
|
area.WaterTableLevelMin = Legal.GetModifiedLevel(area.WaterTableLevelMin, (double)NUD_LevelBoost.Value);
|
|
area.WaterTableLevelMax = Legal.GetModifiedLevel(area.WaterTableLevelMax, (double)NUD_LevelBoost.Value);
|
|
|
|
area.SkyTableLevelMin = Legal.GetModifiedLevel(area.SkyTableLevelMin, (double)NUD_LevelBoost.Value);
|
|
area.SkyTableLevelMax = Legal.GetModifiedLevel(area.SkyTableLevelMax, (double)NUD_LevelBoost.Value);
|
|
}
|
|
ApplyRand(area.GroundTable);
|
|
ApplyRand(area.WaterTable);
|
|
ApplyRand(area.SkyTable);
|
|
|
|
ApplyRand(area.OldRodTable);
|
|
ApplyRand(area.GoodRodTable);
|
|
ApplyRand(area.SuperRodTable);
|
|
}
|
|
|
|
void ApplyRand(IList<EncounterSlot7b> slots)
|
|
{
|
|
if (slots[0].Species == 0)
|
|
return;
|
|
|
|
for (int i = 0; i < slots.Count; i++)
|
|
{
|
|
var s = slots[i];
|
|
if (s.Species == 0)
|
|
{
|
|
if (!fill)
|
|
continue;
|
|
s.Species = slots.FirstOrDefault(z => z.Species != 0)?.Species ?? rand.GetRandomSpecies();
|
|
}
|
|
|
|
s.Species = rand.GetRandomSpecies(s.Species);
|
|
s.Form = 0; // mega & alolan forms don't spawn :(
|
|
if (fill)
|
|
s.Probability = RandomScaledRates[slots.Count][i];
|
|
}
|
|
}
|
|
|
|
if (CHK_ForceType.Checked)
|
|
{
|
|
var table = Tables.EncounterTables[0];
|
|
var slots = table.GroundTable;
|
|
while (!slots.Any(z => IsGrassOrWater(z.Species)))
|
|
ApplyRand(slots);
|
|
}
|
|
}
|
|
|
|
public static readonly Dictionary<int, int[]> RandomScaledRates = new()
|
|
{
|
|
[01] = new[] { 100 },
|
|
[04] = new[] { 60, 30, 7, 3 },
|
|
[05] = new[] { 40, 30, 18, 10, 2 },
|
|
[10] = new[] { 20, 15, 15, 10, 10, 10, 10, 5, 4, 1 },
|
|
};
|
|
|
|
private void B_Dump_Click(object sender, EventArgs e)
|
|
{
|
|
var strings = GetEncounterTableSummary(ROM, Tables);
|
|
var result = string.Join(Environment.NewLine, strings);
|
|
Clipboard.SetText(result);
|
|
System.Media.SystemSounds.Asterisk.Play();
|
|
}
|
|
|
|
private static IEnumerable<string> GetEncounterTableSummary(GameManager rom, EncounterArchive7b table)
|
|
{
|
|
var locationNames = rom.GetStrings(TextName.metlist_00000);
|
|
var specs = rom.GetStrings(TextName.SpeciesNames);
|
|
|
|
var locs = table.EncounterTables.Select(z => z.ZoneID);
|
|
var names = GetNames(locs, locationNames);
|
|
var dupeNamed = GetScreenedNames(names).ToArray();
|
|
return EncounterTable7bUtil.GetLines(table, dupeNamed, specs);
|
|
}
|
|
}
|