Add landmark editor

This commit is contained in:
Kurt
2022-02-20 23:35:18 -08:00
parent bf8390fd2a
commit 22ede7da03
18 changed files with 434 additions and 13 deletions

View File

@@ -9,6 +9,7 @@ namespace pkNX.Randomization
/// Randomization settings when randomizing a <see cref="PersonalInfo"/>.
/// </summary>
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class PersonalRandSettings : RandSettings
{
private const string Moves = nameof(Moves);

View File

@@ -4,6 +4,7 @@
namespace pkNX.Randomization
{
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class LearnSettings
{
private const string General = nameof(General);

View File

@@ -5,6 +5,7 @@
namespace pkNX.Randomization
{
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class MovesetRandSettings
{
private const string Damage = nameof(Damage);

View File

@@ -10,6 +10,7 @@ namespace pkNX.Randomization
/// Settings for what Species are permitted during randomization.
/// </summary>
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class SpeciesSettings : RandSettings
{
private const string General = nameof(General);

View File

@@ -4,6 +4,7 @@
namespace pkNX.Randomization
{
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class TrainerRandSettings
{
private const string General = nameof(General);

View File

@@ -42,7 +42,8 @@ public sealed class PersonalInfoLA : PersonalInfo
public int AbilityH { get => FB.AbilityH; set => FB.AbilityH = (ushort)value; }
public override int EscapeRate { get => 0; set { } } // moved?
protected override int FormStatsIndex { get => 0; set { } }
public override int Color { get => FB.Color; set => FB.Color = (byte)value;} public bool IsPresentInGame { get => FB.IsPresentInGame; set => FB.IsPresentInGame = value; }
public override int Color { get => FB.Color; set => FB.Color = (byte)value; }
public bool IsPresentInGame { get => FB.IsPresentInGame; set => FB.IsPresentInGame = value; }
public override int BaseEXP { get => FB.BaseEXP; set => FB.BaseEXP = (ushort)value; }
public override int Height { get => FB.Height ; set => FB.Height = (ushort)value; }
public override int Weight { get => FB.Weight ; set => FB.Weight = (ushort)value; }

View File

@@ -82,7 +82,6 @@ public string NameSummary
}
}
for (var w1 = 0; w1 < 5; w1++)
{
for (var w2 = 0; w2 < 5; w2++)

View File

@@ -46,7 +46,7 @@ public PlacementParameters8a Parameters
public IEnumerable<PlacementLocation8a> GetIntersectingLocations(IReadOnlyList<PlacementLocation8a> locations, float bias)
{
var c = Parameters.Coordinates;
return GetIntersectingLocations(locations, bias, c, Scalar + bias);
return GetIntersectingLocations(locations, bias, c, Scalar);
}
private static IEnumerable<PlacementLocation8a> GetIntersectingLocations(IReadOnlyList<PlacementLocation8a> locations, float bias, PlacementV3f8a c, float scalar)
@@ -56,7 +56,7 @@ private static IEnumerable<PlacementLocation8a> GetIntersectingLocations(IReadOn
{
if (!loc.IsNamedPlace)
continue;
if (loc.IntersectsSphere(c.X, c.Y, c.Z, scalar))
if (loc.IntersectsSphere(c.X, c.Y, c.Z, scalar + bias))
result.Add(loc);
}
@@ -86,7 +86,7 @@ public string NameSummary
{
var map = GetNameMap();
if (map.TryGetValue(LandmarkItemNameID, out var name))
return $"\"{name}\"";
return $"\"{name}\" ({Field_00})";
return $"0x{LandmarkItemNameID:X16}";
}

View File

@@ -125,4 +125,10 @@ public static string GetSlotName(ulong slotId)
}
public string SlotName => GetSlotName(SlotID);
public void ClearMoves()
{
Move1 = Move2 = Move3 = Move4 = 0;
Move1Mastered = Move2Mastered = Move3Mastered = Move4Mastered = false;
}
}

View File

@@ -12,12 +12,12 @@ public static partial class Legal
public const int MaxBallID_8 = (int)Ball.Beast;
public const int MaxGameID_8 = (int)GameVersion.SH;
public const int MaxSpeciesID_8a = 898; // Calyrex
public const int MaxMoveID_8a = 826; // Eerie Spell
public const int MaxItemID_8a = 1607; // Reins of Unity
public const int MaxAbilityID_8a = 267; // As One
public const int MaxBallID_8a = (int)Ball.Beast;
public const int MaxGameID_8a = (int)GameVersion.SH;
internal const int MaxSpeciesID_8a = (int)Species.Enamorus;
internal const int MaxMoveID_8a = 850; // Take Heart
internal const int MaxItemID_8a = 1828; // Legend Plate
internal const int MaxBallID_8a = (int)Ball.LAOrigin;
internal const int MaxGameID_8a = (int)GameVersion.SP;
internal const int MaxAbilityID_8a = 267; // As One (Glastrier)
#region Met Locations
internal static readonly int[] Met_SWSH_0 =

View File

@@ -38,5 +38,18 @@ public enum Ball : byte
Sport = 24,
Dream = 25,
Beast = 26,
// Legends: Arceus
Strange = 27,
LAPoke = 28,
LAGreat = 29,
LAUltra = 30,
LAFeather = 31,
LAWing = 32,
LAJet = 33,
LAHeavy = 34,
LALeaden = 35,
LAGigaton = 36,
LAOrigin = 37,
}
}

View File

@@ -904,6 +904,13 @@ public enum Species : ushort
Glastrier,
Spectrier,
Calyrex,
Wyrdeer,
Kleavor,
Ursaluna,
Basculegion,
Sneasler,
Overqwil,
Enamorus,
MAX_COUNT,
}
}

View File

@@ -0,0 +1,100 @@
namespace pkNX.WinForms.Controls
{
partial class LandmarkEditor8a
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.B_HighEncounterChance = new System.Windows.Forms.Button();
this.PG_Encounters = new System.Windows.Forms.PropertyGrid();
this.CB_Encounters = new System.Windows.Forms.ComboBox();
this.L_ConfigName = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// B_HighEncounterChance
//
this.B_HighEncounterChance.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.B_HighEncounterChance.Location = new System.Drawing.Point(614, 0);
this.B_HighEncounterChance.Name = "B_HighEncounterChance";
this.B_HighEncounterChance.Size = new System.Drawing.Size(148, 23);
this.B_HighEncounterChance.TabIndex = 8;
this.B_HighEncounterChance.Text = "High Encounter Chance";
this.B_HighEncounterChance.UseVisualStyleBackColor = true;
this.B_HighEncounterChance.Click += new System.EventHandler(this.B_HighEncounterChance_Click);
//
// PG_Encounters
//
this.PG_Encounters.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.PG_Encounters.Location = new System.Drawing.Point(3, 38);
this.PG_Encounters.Name = "PG_Encounters";
this.PG_Encounters.Size = new System.Drawing.Size(759, 548);
this.PG_Encounters.TabIndex = 7;
//
// CB_Encounters
//
this.CB_Encounters.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend;
this.CB_Encounters.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
this.CB_Encounters.FormattingEnabled = true;
this.CB_Encounters.Location = new System.Drawing.Point(3, 15);
this.CB_Encounters.Name = "CB_Encounters";
this.CB_Encounters.Size = new System.Drawing.Size(174, 21);
this.CB_Encounters.TabIndex = 6;
this.CB_Encounters.SelectedIndexChanged += new System.EventHandler(this.CB_Encounters_SelectedIndexChanged);
//
// L_ConfigName
//
this.L_ConfigName.AutoSize = true;
this.L_ConfigName.Location = new System.Drawing.Point(3, 1);
this.L_ConfigName.Name = "L_ConfigName";
this.L_ConfigName.Size = new System.Drawing.Size(110, 13);
this.L_ConfigName.TabIndex = 9;
this.L_ConfigName.Text = "{Configured File Path}";
//
// EncounterTableEditor8a
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.L_ConfigName);
this.Controls.Add(this.B_HighEncounterChance);
this.Controls.Add(this.PG_Encounters);
this.Controls.Add(this.CB_Encounters);
this.Name = "EncounterTableEditor8a";
this.Size = new System.Drawing.Size(765, 589);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button B_HighEncounterChance;
private System.Windows.Forms.PropertyGrid PG_Encounters;
private System.Windows.Forms.ComboBox CB_Encounters;
private System.Windows.Forms.Label L_ConfigName;
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Linq;
using System.Windows.Forms;
using pkNX.Structures.FlatBuffers;
namespace pkNX.WinForms.Controls;
public partial class LandmarkEditor8a : UserControl
{
public LandmarkItemSpawn8a[] Spawners = Array.Empty<LandmarkItemSpawn8a>();
public LandmarkEditor8a() => InitializeComponent();
public void LoadTable(LandmarkItemSpawn8a[] table, string path)
{
Spawners = table;
if (table.Length == 0)
{
Visible = false;
return;
}
Visible = true;
L_ConfigName.Text = path;
var items = table.Select(z => new ComboItem(z.NameSummary.Replace("\"", ""), z)).ToArray();
CB_Encounters.DisplayMember = nameof(ComboItem.Text);
CB_Encounters.ValueMember = nameof(ComboItem.Value);
CB_Encounters.DataSource = new BindingSource(items, null);
CB_Encounters.SelectedIndex = 0;
}
private class ComboItem
{
public ComboItem(string text, LandmarkItemSpawn8a value)
{
Text = text;
Value = value;
}
public string Text { get; }
public LandmarkItemSpawn8a Value { get; }
}
private void CB_Encounters_SelectedIndexChanged(object sender, EventArgs e)
{
PG_Encounters.SelectedObject = (LandmarkItemSpawn8a)CB_Encounters.SelectedValue;
}
private void B_HighEncounterChance_Click(object sender, EventArgs e)
{
const int chance = 75;
foreach (var spawner in Spawners)
{
spawner.Field_04 = chance;
}
WinFormsUtil.Alert($"Changed all encounter chance to {chance}%.");
CB_Encounters_SelectedIndexChanged(sender, e);
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -454,9 +454,8 @@ public void DumpWilds()
File.WriteAllText(GetPath(wild, "allSpawnerTable.csv"), TableUtil.GetTable(allSpawners));
File.WriteAllText(GetPath(wild, "allWormholeTable.csv"), TableUtil.GetTable(allWormholes));
File.WriteAllText(GetPath(wild, "allLocationTable.csv"), TableUtil.GetTable(allLocations));
File.WriteAllText(GetPath(wild, "allLandItems.csv"), TableUtil.GetTable(allLandItems));
File.WriteAllText(GetPath(wild, "allLandMarks.csv"), TableUtil.GetTable(allLandMarks));
File.WriteAllText(GetPath(wild, "allLandMarkSpawns.csv"), TableUtil.GetTable(allLandMarks));
File.WriteAllText(GetPath(wild, "allLandMarkSpawns.csv"), TableUtil.GetTable(allLandItems));
File.WriteAllText(GetPath(wild, "allUnown.csv"), TableUtil.GetTable(allUnown));
File.WriteAllText(GetPath(wild, "allMkrg.csv"), TableUtil.GetTable(allMkrg));
File.WriteAllText(GetPath(wild, "allSearchItem.csv"), TableUtil.GetTable(allSearchItem));

View File

@@ -36,13 +36,18 @@ private void InitializeComponent()
this.Tab_Landmarks = new System.Windows.Forms.TabPage();
this.Tab_Randomize = new System.Windows.Forms.TabPage();
this.B_Save = new System.Windows.Forms.Button();
this.PG_RandSettings = new System.Windows.Forms.PropertyGrid();
this.Edit_Encounters = new pkNX.WinForms.Controls.EncounterTableEditor8a();
this.Edit_RegularSpawners = new pkNX.WinForms.Controls.PlacementSpawnerEditor8a();
this.Edit_WormholeSpawners = new pkNX.WinForms.Controls.PlacementSpawnerEditor8a();
this.Edit_LandmarkSpawns = new pkNX.WinForms.Controls.LandmarkEditor8a();
this.B_Randomize = new System.Windows.Forms.Button();
this.TC_Editor.SuspendLayout();
this.Tab_Encounters.SuspendLayout();
this.Tab_Regular.SuspendLayout();
this.Tab_Wormhole.SuspendLayout();
this.Tab_Landmarks.SuspendLayout();
this.Tab_Randomize.SuspendLayout();
this.SuspendLayout();
//
// CB_Area
@@ -101,6 +106,7 @@ private void InitializeComponent()
//
// Tab_Landmarks
//
this.Tab_Landmarks.Controls.Add(this.Edit_LandmarkSpawns);
this.Tab_Landmarks.Location = new System.Drawing.Point(4, 22);
this.Tab_Landmarks.Name = "Tab_Landmarks";
this.Tab_Landmarks.Size = new System.Drawing.Size(677, 455);
@@ -110,6 +116,8 @@ private void InitializeComponent()
//
// Tab_Randomize
//
this.Tab_Randomize.Controls.Add(this.B_Randomize);
this.Tab_Randomize.Controls.Add(this.PG_RandSettings);
this.Tab_Randomize.Location = new System.Drawing.Point(4, 22);
this.Tab_Randomize.Name = "Tab_Randomize";
this.Tab_Randomize.Padding = new System.Windows.Forms.Padding(3);
@@ -120,6 +128,7 @@ private void InitializeComponent()
//
// B_Save
//
this.B_Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.B_Save.Location = new System.Drawing.Point(633, 1);
this.B_Save.Name = "B_Save";
this.B_Save.Size = new System.Drawing.Size(75, 23);
@@ -128,6 +137,14 @@ private void InitializeComponent()
this.B_Save.UseVisualStyleBackColor = true;
this.B_Save.Click += new System.EventHandler(this.B_Save_Click);
//
// PG_RandSettings
//
this.PG_RandSettings.Dock = System.Windows.Forms.DockStyle.Fill;
this.PG_RandSettings.Location = new System.Drawing.Point(3, 3);
this.PG_RandSettings.Name = "PG_RandSettings";
this.PG_RandSettings.Size = new System.Drawing.Size(671, 449);
this.PG_RandSettings.TabIndex = 0;
//
// Edit_Encounters
//
this.Edit_Encounters.Dock = System.Windows.Forms.DockStyle.Fill;
@@ -152,6 +169,24 @@ private void InitializeComponent()
this.Edit_WormholeSpawners.Size = new System.Drawing.Size(677, 455);
this.Edit_WormholeSpawners.TabIndex = 2;
//
// Edit_LandmarkSpawns
//
this.Edit_LandmarkSpawns.Dock = System.Windows.Forms.DockStyle.Fill;
this.Edit_LandmarkSpawns.Location = new System.Drawing.Point(0, 0);
this.Edit_LandmarkSpawns.Name = "Edit_LandmarkSpawns";
this.Edit_LandmarkSpawns.Size = new System.Drawing.Size(677, 455);
this.Edit_LandmarkSpawns.TabIndex = 0;
//
// B_Randomize
//
this.B_Randomize.Location = new System.Drawing.Point(431, 3);
this.B_Randomize.Name = "B_Randomize";
this.B_Randomize.Size = new System.Drawing.Size(243, 23);
this.B_Randomize.TabIndex = 5;
this.B_Randomize.Text = "Randomize Current Map Encounters";
this.B_Randomize.UseVisualStyleBackColor = true;
this.B_Randomize.Click += new System.EventHandler(this.B_Randomize_Click);
//
// AreaEditor8a
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -167,6 +202,8 @@ private void InitializeComponent()
this.Tab_Encounters.ResumeLayout(false);
this.Tab_Regular.ResumeLayout(false);
this.Tab_Wormhole.ResumeLayout(false);
this.Tab_Landmarks.ResumeLayout(false);
this.Tab_Randomize.ResumeLayout(false);
this.ResumeLayout(false);
}
@@ -183,5 +220,8 @@ private void InitializeComponent()
private System.Windows.Forms.Button B_Save;
private Controls.PlacementSpawnerEditor8a Edit_RegularSpawners;
private Controls.PlacementSpawnerEditor8a Edit_WormholeSpawners;
private System.Windows.Forms.PropertyGrid PG_RandSettings;
private Controls.LandmarkEditor8a Edit_LandmarkSpawns;
private System.Windows.Forms.Button B_Randomize;
}
}

View File

@@ -1,10 +1,14 @@
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 Util = pkNX.Randomization.Util;
namespace pkNX.WinForms.Subforms;
@@ -35,6 +39,8 @@ public AreaEditor8a(GameManagerPLA rom)
InitializeComponent();
PG_RandSettings.SelectedObject = EditUtil.Settings.Species;
Loading = true;
CB_Area.Items.AddRange(AreaNames);
CB_Area.SelectedIndex = AreaIndex;
@@ -59,12 +65,75 @@ private void CB_Map_SelectedIndexChanged(object sender, EventArgs e)
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(ResidentArea8a 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<PersonalInfoLA>())
{
if (pi.IsPresentInGame)
{
banned.Remove(pi.Species);
hasForm.Add(pi.Species);
}
else if (!hasForm.Contains(pi.Species))
{
banned.Add(pi.Species);
}
}
rand.Initialize(settings, banned.ToArray());
var formRand = pt.Table
.Cast<PersonalInfoLA>()
.Where(z => z.IsPresentInGame && !(Legal.BattleExclusiveForms.Contains(z.Species) || Legal.BattleFusions.Contains(z.Species)))
.GroupBy(z => z.Species)
.ToDictionary(z => z.Key, z => z.ToList());
var encounters = area.Encounters;
foreach (var table in encounters)
{
foreach (var enc in table.Table)
{
if (enc.ShinyLock is not ShinyType8a.Random)
continue;
if (enc.Eligibility.ConditionID is not Condition8a.None)
continue;
var spec = rand.GetRandomSpecies(enc.Species);
enc.Species = spec;
enc.Form = GetRandomForm(spec);
enc.ClearMoves();
}
}
int GetRandomForm(int spec)
{
if (!formRand.TryGetValue(spec, out var entries))
return 0;
var count = entries.Count;
return Util.Random.Next(0, count);
}
}
private void LoadArea()
{
Debug.WriteLine($"Loading Area {AreaIndex}");
Edit_Encounters.LoadTable(Area.Encounters, Area.Settings.Encounters);
Edit_RegularSpawners.LoadTable(Area.Spawners, Area.Settings.Spawners);
Edit_WormholeSpawners.LoadTable(Area.Wormholes, Area.Settings.WormholeSpawners);
Edit_LandmarkSpawns.LoadTable(Area.LandItems, Area.Settings.LandmarkItemSpawns);
}
private void SaveArea()