mirror of
https://github.com/kwsch/pkNX.git
synced 2026-08-20 01:14:12 -05:00
Remove unsupported games, split GameData
lack of interfaces and default interface implementations is killing me :) Split GameData so we can interact with changed data structures a little less weird; PLA Learnsets are too incompatible for direct edits with existing abstractions.
This commit is contained in:
@@ -52,252 +52,19 @@ internal void SaveAll()
|
||||
Cache.Remove(m.Key);
|
||||
}
|
||||
|
||||
public static IReadOnlyCollection<GameFileReference> GetMapping(GameVersion game)
|
||||
public static IReadOnlyCollection<GameFileReference> GetMapping(GameVersion game) => game switch
|
||||
{
|
||||
return game switch
|
||||
{
|
||||
GameVersion.SN => SN,
|
||||
GameVersion.MN => MN,
|
||||
GameVersion.US => US,
|
||||
GameVersion.UM => UM,
|
||||
GameVersion.XY => XY,
|
||||
GameVersion.GP => GG,
|
||||
GameVersion.GE => GG,
|
||||
GameVersion.GG => GG,
|
||||
GameVersion.SW => SWSH,
|
||||
GameVersion.SH => SWSH,
|
||||
GameVersion.SWSH => SWSH,
|
||||
GameVersion.PLA => PLA,
|
||||
GameVersion.ORASDEMO => AO,
|
||||
GameVersion.ORAS => AO,
|
||||
GameVersion.SMDEMO => SMDEMO,
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
#region Games
|
||||
private static readonly GameFileReference[] XY =
|
||||
{
|
||||
new(005, GameFile.MoveSprites),
|
||||
new(012, GameFile.Encounters),
|
||||
new(038, GameFile.TrainerData),
|
||||
new(039, GameFile.TrainerClass),
|
||||
new(040, GameFile.TrainerPoke),
|
||||
new(041, GameFile.MapGameRegion),
|
||||
new(042, GameFile.MapMatrix),
|
||||
|
||||
new(072, GameFile.GameText0),
|
||||
new(073, GameFile.GameText1),
|
||||
new(074, GameFile.GameText2),
|
||||
new(075, GameFile.GameText3),
|
||||
new(076, GameFile.GameText4),
|
||||
new(077, GameFile.GameText5),
|
||||
new(078, GameFile.GameText6),
|
||||
new(079, GameFile.GameText7),
|
||||
new(080, GameFile.StoryText0),
|
||||
new(081, GameFile.StoryText1),
|
||||
new(082, GameFile.StoryText2),
|
||||
new(083, GameFile.StoryText3),
|
||||
new(084, GameFile.StoryText4),
|
||||
new(085, GameFile.StoryText5),
|
||||
new(086, GameFile.StoryText6),
|
||||
new(087, GameFile.StoryText7),
|
||||
|
||||
new(104, GameFile.Wallpaper),
|
||||
new(165, GameFile.TitleScreen),
|
||||
new(203, GameFile.FacilityPokeNormal),
|
||||
new(204, GameFile.FacilityTrainerNormal),
|
||||
new(205, GameFile.FacilityPokeSuper),
|
||||
new(206, GameFile.FacilityTrainerSuper),
|
||||
new(212, GameFile.MoveStats),
|
||||
new(213, GameFile.EggMoves),
|
||||
new(214, GameFile.Learnsets),
|
||||
new(215, GameFile.Evolutions),
|
||||
new(216, GameFile.MegaEvolutions),
|
||||
new(218, GameFile.PersonalStats),
|
||||
new(220, GameFile.ItemStats),
|
||||
GameVersion.GP => GG,
|
||||
GameVersion.GE => GG,
|
||||
GameVersion.GG => GG,
|
||||
GameVersion.SW => SWSH,
|
||||
GameVersion.SH => SWSH,
|
||||
GameVersion.SWSH => SWSH,
|
||||
GameVersion.PLA => PLA,
|
||||
_ => null,
|
||||
};
|
||||
|
||||
private static readonly GameFileReference[] AO =
|
||||
{
|
||||
new(013, GameFile.Encounters),
|
||||
new(036, GameFile.TrainerData),
|
||||
new(037, GameFile.TrainerClass),
|
||||
new(038, GameFile.TrainerPoke),
|
||||
new(039, GameFile.MapGameRegion),
|
||||
new(040, GameFile.MapMatrix),
|
||||
|
||||
new(071, GameFile.GameText0),
|
||||
new(072, GameFile.GameText1),
|
||||
new(073, GameFile.GameText2),
|
||||
new(074, GameFile.GameText3),
|
||||
new(075, GameFile.GameText4),
|
||||
new(076, GameFile.GameText5),
|
||||
new(077, GameFile.GameText6),
|
||||
new(078, GameFile.GameText7),
|
||||
new(079, GameFile.StoryText0),
|
||||
new(080, GameFile.StoryText1),
|
||||
new(081, GameFile.StoryText2),
|
||||
new(082, GameFile.StoryText3),
|
||||
new(083, GameFile.StoryText4),
|
||||
new(084, GameFile.StoryText5),
|
||||
new(085, GameFile.StoryText6),
|
||||
new(086, GameFile.StoryText7),
|
||||
|
||||
new(103, GameFile.Wallpaper),
|
||||
new(152, GameFile.TitleScreen),
|
||||
new(182, GameFile.FacilityPokeNormal),
|
||||
new(183, GameFile.FacilityTrainerNormal),
|
||||
new(184, GameFile.FacilityPokeSuper),
|
||||
new(185, GameFile.FacilityTrainerSuper),
|
||||
new(189, GameFile.MoveStats),
|
||||
new(190, GameFile.EggMoves),
|
||||
new(191, GameFile.Learnsets),
|
||||
new(192, GameFile.Evolutions),
|
||||
new(193, GameFile.MegaEvolutions),
|
||||
new(195, GameFile.PersonalStats),
|
||||
new(197, GameFile.ItemStats),
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Gen7
|
||||
private static readonly GameFileReference[] SMDEMO =
|
||||
{
|
||||
new(011, GameFile.MoveStats),
|
||||
new(012, GameFile.EggMoves),
|
||||
new(013, GameFile.Learnsets),
|
||||
new(014, GameFile.Evolutions),
|
||||
new(015, GameFile.MegaEvolutions),
|
||||
new(017, GameFile.PersonalStats),
|
||||
new(019, GameFile.ItemStats),
|
||||
|
||||
new(030, GameFile.GameText0),
|
||||
new(031, GameFile.GameText1),
|
||||
new(032, GameFile.GameText2),
|
||||
new(033, GameFile.GameText3),
|
||||
new(034, GameFile.GameText4),
|
||||
new(035, GameFile.GameText5),
|
||||
new(036, GameFile.GameText6),
|
||||
new(037, GameFile.GameText7),
|
||||
new(038, GameFile.GameText8),
|
||||
new(039, GameFile.GameText9),
|
||||
new(040, GameFile.StoryText0),
|
||||
new(041, GameFile.StoryText1),
|
||||
new(042, GameFile.StoryText2),
|
||||
new(043, GameFile.StoryText3),
|
||||
new(044, GameFile.StoryText4),
|
||||
new(045, GameFile.StoryText5),
|
||||
new(046, GameFile.StoryText6),
|
||||
new(047, GameFile.StoryText7),
|
||||
new(048, GameFile.StoryText8),
|
||||
new(049, GameFile.StoryText9),
|
||||
|
||||
new(076, GameFile.ZoneData),
|
||||
new(091, GameFile.WorldData),
|
||||
|
||||
new(101, GameFile.TrainerClass),
|
||||
new(102, GameFile.TrainerData),
|
||||
new(103, GameFile.TrainerPoke),
|
||||
};
|
||||
|
||||
private static readonly GameFileReference[] SM =
|
||||
{
|
||||
new(011, GameFile.MoveStats),
|
||||
new(012, GameFile.EggMoves),
|
||||
new(013, GameFile.Learnsets),
|
||||
new(014, GameFile.Evolutions),
|
||||
new(015, GameFile.MegaEvolutions),
|
||||
new(017, GameFile.PersonalStats),
|
||||
new(019, GameFile.ItemStats),
|
||||
|
||||
new(030, GameFile.GameText0),
|
||||
new(031, GameFile.GameText1),
|
||||
new(032, GameFile.GameText2),
|
||||
new(033, GameFile.GameText3),
|
||||
new(034, GameFile.GameText4),
|
||||
new(035, GameFile.GameText5),
|
||||
new(036, GameFile.GameText6),
|
||||
new(037, GameFile.GameText7),
|
||||
new(038, GameFile.GameText8),
|
||||
new(039, GameFile.GameText9),
|
||||
new(040, GameFile.StoryText0),
|
||||
new(041, GameFile.StoryText1),
|
||||
new(042, GameFile.StoryText2),
|
||||
new(043, GameFile.StoryText3),
|
||||
new(044, GameFile.StoryText4),
|
||||
new(045, GameFile.StoryText5),
|
||||
new(046, GameFile.StoryText6),
|
||||
new(047, GameFile.StoryText7),
|
||||
new(048, GameFile.StoryText8),
|
||||
new(049, GameFile.StoryText9),
|
||||
|
||||
new(077, GameFile.ZoneData),
|
||||
new(091, GameFile.WorldData),
|
||||
|
||||
new(104, GameFile.TrainerClass),
|
||||
new(105, GameFile.TrainerData),
|
||||
new(106, GameFile.TrainerPoke),
|
||||
|
||||
new(155, GameFile.EncounterStatic),
|
||||
|
||||
new(267, GameFile.Pickup),
|
||||
|
||||
new(277, GameFile.FacilityPokeNormal),
|
||||
new(278, GameFile.FacilityTrainerNormal),
|
||||
new(279, GameFile.FacilityPokeSuper),
|
||||
new(280, GameFile.FacilityTrainerSuper),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Ultra Sun & Ultra Moon
|
||||
/// </summary>
|
||||
private static readonly GameFileReference[] UU =
|
||||
{
|
||||
new(011, GameFile.MoveStats),
|
||||
new(012, GameFile.EggMoves),
|
||||
new(013, GameFile.Learnsets),
|
||||
new(014, GameFile.Evolutions),
|
||||
new(015, GameFile.MegaEvolutions),
|
||||
new(017, GameFile.PersonalStats),
|
||||
new(019, GameFile.ItemStats),
|
||||
|
||||
new(030, GameFile.GameText0),
|
||||
new(031, GameFile.GameText1),
|
||||
new(032, GameFile.GameText2),
|
||||
new(033, GameFile.GameText3),
|
||||
new(034, GameFile.GameText4),
|
||||
new(035, GameFile.GameText5),
|
||||
new(036, GameFile.GameText6),
|
||||
new(037, GameFile.GameText7),
|
||||
new(038, GameFile.GameText8),
|
||||
new(039, GameFile.GameText9),
|
||||
new(040, GameFile.StoryText0),
|
||||
new(041, GameFile.StoryText1),
|
||||
new(042, GameFile.StoryText2),
|
||||
new(043, GameFile.StoryText3),
|
||||
new(044, GameFile.StoryText4),
|
||||
new(045, GameFile.StoryText5),
|
||||
new(046, GameFile.StoryText6),
|
||||
new(047, GameFile.StoryText7),
|
||||
new(048, GameFile.StoryText8),
|
||||
new(049, GameFile.StoryText9),
|
||||
|
||||
new(077, GameFile.ZoneData),
|
||||
new(091, GameFile.WorldData),
|
||||
|
||||
new(105, GameFile.TrainerClass),
|
||||
new(106, GameFile.TrainerData),
|
||||
new(107, GameFile.TrainerPoke),
|
||||
|
||||
new(159, GameFile.EncounterStatic),
|
||||
|
||||
new(271, GameFile.Pickup),
|
||||
|
||||
new(281, GameFile.FacilityPokeNormal),
|
||||
new(282, GameFile.FacilityTrainerNormal),
|
||||
new(283, GameFile.FacilityPokeSuper),
|
||||
new(284, GameFile.FacilityTrainerSuper),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Let's Go Pikachu & Let's Go Eevee
|
||||
@@ -446,7 +213,7 @@ public static IReadOnlyCollection<GameFileReference> GetMapping(GameVersion game
|
||||
new(GameFile.StoryText9, 10, "bin", "message", "Trad_Chinese", "script"),
|
||||
|
||||
new(GameFile.ItemStats, ContainerType.SingleFile, "bin", "pml", "item", "item.dat"),
|
||||
new(GameFile.Evolutions, "bin", "pml", "evolution"),
|
||||
new(GameFile.Evolutions, ContainerType.SingleFile, "bin", "pml", "evolution", "evolution_data_total.evobin"),
|
||||
new(GameFile.PersonalStats, ContainerType.SingleFile, "bin", "pml", "personal", "personal_data_total.perbin"),
|
||||
new(GameFile.MoveStats, "bin", "pml", "waza"),
|
||||
new(GameFile.EncounterStatic, ContainerType.SingleFile, "bin", "pokemon", "data", "poke_event_encount.bin"),
|
||||
@@ -490,12 +257,5 @@ public static IReadOnlyCollection<GameFileReference> GetMapping(GameVersion game
|
||||
// pretty much everything is obviously named :)
|
||||
};
|
||||
#endregion
|
||||
|
||||
#region Split Versions
|
||||
private static readonly GameFileReference[] SN = SM.Concat(new[] {new GameFileReference(082, GameFile.Encounters)}).ToArray();
|
||||
private static readonly GameFileReference[] MN = SM.Concat(new[] {new GameFileReference(083, GameFile.Encounters)}).ToArray();
|
||||
private static readonly GameFileReference[] US = UU.Concat(new[] {new GameFileReference(082, GameFile.Encounters)}).ToArray();
|
||||
private static readonly GameFileReference[] UM = UU.Concat(new[] {new GameFileReference(083, GameFile.Encounters)}).ToArray();
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
using pkNX.Structures;
|
||||
|
||||
namespace pkNX.Game
|
||||
{
|
||||
/// <summary>
|
||||
/// Cached data reusable by multiple editors.
|
||||
/// </summary>
|
||||
public class GameData
|
||||
{
|
||||
public PersonalTable PersonalData { get; internal set; }
|
||||
public DataCache<MegaEvolutionSet[]> MegaEvolutionData { get; internal set; }
|
||||
namespace pkNX.Game;
|
||||
|
||||
public string[][] GameText { get; internal set; }
|
||||
public DataCache<IMove> MoveData { get; internal set; }
|
||||
public DataCache<EvolutionSet> EvolutionData { get; internal set; }
|
||||
public DataCache<Learnset> LevelUpData { get; internal set; }
|
||||
public DataCache<EggMoves> EggMoves { get; internal set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Cached data reusable by multiple editors.
|
||||
/// </summary>
|
||||
public class GameData
|
||||
{
|
||||
public PersonalTable PersonalData { get; internal set; }
|
||||
public DataCache<MegaEvolutionSet[]> MegaEvolutionData { get; internal set; }
|
||||
|
||||
public DataCache<IMove> MoveData { get; internal set; }
|
||||
public DataCache<EvolutionSet> EvolutionData { get; internal set; }
|
||||
public DataCache<Learnset> LevelUpData { get; internal set; }
|
||||
}
|
||||
|
||||
13
pkNX.Game/GameData8a.cs
Normal file
13
pkNX.Game/GameData8a.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using pkNX.Structures;
|
||||
using pkNX.Structures.FlatBuffers;
|
||||
|
||||
namespace pkNX.Game;
|
||||
|
||||
public class GameData8a
|
||||
{
|
||||
public PersonalTable PersonalData { get; internal set; }
|
||||
|
||||
public DataCache<Waza8a> MoveData { get; internal set; }
|
||||
public DataCache<EvolutionSet8a> EvolutionData { get; internal set; }
|
||||
public DataCache<Learnset8aMeta> LevelUpData { get; internal set; }
|
||||
}
|
||||
@@ -38,11 +38,6 @@ public int Language
|
||||
/// </summary>
|
||||
public GameVersion Game => ROM.Game;
|
||||
|
||||
/// <summary>
|
||||
/// Generally useful game data that can be used by multiple editors.
|
||||
/// </summary>
|
||||
public GameData Data { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="GameManager"/> for the input <see cref="GameLocation"/> with initial <see cref="Language"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using pkNX.Containers;
|
||||
using pkNX.Structures;
|
||||
@@ -14,6 +13,11 @@ public class GameManagerGG : GameManager
|
||||
private const string Pikachu = "010003F003A34000";
|
||||
private const string Eevee = "0100187003A36000";
|
||||
|
||||
/// <summary>
|
||||
/// Generally useful game data that can be used by multiple editors.
|
||||
/// </summary>
|
||||
public GameData Data { get; protected set; }
|
||||
|
||||
protected override void SetMitm()
|
||||
{
|
||||
var basePath = Path.GetDirectoryName(ROM.RomFS);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using pkNX.Containers;
|
||||
using pkNX.Structures;
|
||||
using pkNX.Structures.FlatBuffers;
|
||||
|
||||
namespace pkNX.Game
|
||||
@@ -11,6 +13,11 @@ public class GameManagerPLA : GameManager
|
||||
private string PathNPDM => Path.Combine(PathExeFS, "main.npdm");
|
||||
private string TitleID => BitConverter.ToUInt64(File.ReadAllBytes(PathNPDM), 0x470).ToString("X16");
|
||||
|
||||
/// <summary>
|
||||
/// Generally useful game data that can be used by multiple editors.
|
||||
/// </summary>
|
||||
public GameData8a Data { get; protected set; }
|
||||
|
||||
protected override void SetMitm()
|
||||
{
|
||||
var basePath = Path.GetDirectoryName(ROM.RomFS);
|
||||
@@ -19,8 +26,6 @@ protected override void SetMitm()
|
||||
FileMitm.SetRedirect(basePath, redirect);
|
||||
}
|
||||
|
||||
private Learnset8a Learn;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -29,36 +34,44 @@ public override void Initialize()
|
||||
ResetText();
|
||||
|
||||
// initialize common structures
|
||||
var personal = GetFile(GameFile.PersonalStats)[0];
|
||||
var learn = this[GameFile.Learnsets][0];
|
||||
Learn = FlatBufferConverter.DeserializeFrom<Learnset8a>(learn);
|
||||
|
||||
var move = this[GameFile.MoveStats];
|
||||
((FolderContainer)move).Initialize();
|
||||
//Data = new GameData
|
||||
//{
|
||||
// MoveData = new DataCache<IMove>(move)
|
||||
// {
|
||||
// Create = FlatBufferConverter.DeserializeFrom<Waza8a>,
|
||||
// Write = z => FlatBufferConverter.SerializeFrom((Waza8a)z),
|
||||
// },
|
||||
// LevelUpData = new DataCache<Learnset>(Array.Empty<Learnset>())
|
||||
// {
|
||||
// Create = z => new Learnset8(z),
|
||||
// Write = z => z.Write(),
|
||||
// },
|
||||
//
|
||||
// // folders
|
||||
// PersonalData = new PersonalTable(personal, Game),
|
||||
// EvolutionData = new DataCache<EvolutionSet>(GetFilteredFolder(GameFile.Evolutions))
|
||||
// {
|
||||
// Create = data => new EvolutionSet8(data),
|
||||
// Write = evo => evo.Write(),
|
||||
// },
|
||||
//};
|
||||
ResetData();
|
||||
}
|
||||
|
||||
public void ResetMoves() => GetFilteredFolder(GameFile.MoveStats);
|
||||
private void ResetData()
|
||||
{
|
||||
var pbin = this[GameFile.PersonalStats][0];
|
||||
var personal = FlatBufferConverter.DeserializeFrom<PersonalTableLA>(pbin);
|
||||
var evos = this[GameFile.Evolutions][0];
|
||||
var evoTable = FlatBufferConverter.DeserializeFrom<EvolutionTable8>(evos);
|
||||
var learn = this[GameFile.Learnsets][0];
|
||||
var learnTable = FlatBufferConverter.DeserializeFrom<Learnset8a>(learn);
|
||||
|
||||
Data = new GameData8a
|
||||
{
|
||||
// Folders
|
||||
MoveData = GetMoves(),
|
||||
|
||||
// Custom
|
||||
PersonalData = new PersonalTable(personal.Table.Select(z => new PersonalInfoLA(z)).ToArray(), 905),
|
||||
|
||||
// Single Files
|
||||
LevelUpData = new DataCache<Learnset8aMeta>(learnTable.Table),
|
||||
EvolutionData = new DataCache<EvolutionSet8a>(evoTable.Table),
|
||||
};
|
||||
}
|
||||
|
||||
private DataCache<Waza8a> GetMoves()
|
||||
{
|
||||
var move = this[GameFile.MoveStats];
|
||||
((FolderContainer)move).Initialize();
|
||||
return new DataCache<Waza8a>(move)
|
||||
{
|
||||
Create = FlatBufferConverter.DeserializeFrom<Waza8a>,
|
||||
Write = FlatBufferConverter.SerializeFrom,
|
||||
};
|
||||
}
|
||||
|
||||
public void ResetMoves() => Data.MoveData.ClearAll();
|
||||
|
||||
public void ResetText()
|
||||
{
|
||||
@@ -69,9 +82,11 @@ protected override void Terminate()
|
||||
{
|
||||
// Store Personal Data back in the file. Let the container detect if it is modified.
|
||||
var personal = this[GameFile.PersonalStats];
|
||||
//personal[0] = Data.PersonalData.Table.SelectMany(z => z.Write()).ToArray();
|
||||
personal[0] = FlatBufferConverter.SerializeFrom(new PersonalTableLA { Table = Data.PersonalData.Table.Cast<PersonalInfoLA>().Select(z => z.FB).ToArray() } );
|
||||
var learn = this[GameFile.Learnsets];
|
||||
//learn[0] = Learn.Entries.SelectMany(z => z.Write()).ToArray();
|
||||
learn[0] = FlatBufferConverter.SerializeFrom(new Learnset8a { Table = Data.LevelUpData.LoadAll() });
|
||||
var evos = this[GameFile.Evolutions];
|
||||
evos[0] = FlatBufferConverter.SerializeFrom(new EvolutionTable8 { Table = Data.EvolutionData.LoadAll() });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,10 @@ public class GameManagerSWSH : GameManager
|
||||
private string npdmPath => Path.Combine(PathExeFS, "main.npdm");
|
||||
private string TitleID => BitConverter.ToUInt64(File.ReadAllBytes(npdmPath), 0x290).ToString("X16");
|
||||
|
||||
/// <summary>
|
||||
/// Generally useful game data that can be used by multiple editors.
|
||||
/// </summary>
|
||||
public GameData Data { get; protected set; }
|
||||
|
||||
protected override void SetMitm()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
|
||||
namespace pkNX.Structures.FlatBuffers;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="PersonalInfo"/> class with values from the <see cref="GameVersion.PLA"/> games.
|
||||
/// </summary>
|
||||
public sealed class PersonalInfoLA : PersonalInfo
|
||||
{
|
||||
public PersonalInfoLAfb FB { get; }
|
||||
public PersonalInfoLA(PersonalInfoLAfb fb) => FB = fb;
|
||||
|
||||
public override byte[] Write() => Array.Empty<byte>();
|
||||
|
||||
public override int HP { get => FB.Stat_HP ; set => FB.Stat_HP = (byte)value; }
|
||||
public override int ATK { get => FB.Stat_ATK; set => FB.Stat_ATK = (byte)value; }
|
||||
public override int DEF { get => FB.Stat_DEF; set => FB.Stat_DEF = (byte)value; }
|
||||
public override int SPE { get => FB.Stat_SPE; set => FB.Stat_SPE = (byte)value; }
|
||||
public override int SPA { get => FB.Stat_SPA; set => FB.Stat_SPA = (byte)value; }
|
||||
public override int SPD { get => FB.Stat_SPD; set => FB.Stat_SPD = (byte)value; }
|
||||
public override int Type1 { get => FB.Type1; set => FB.Type1 = (byte)value; }
|
||||
public override int Type2 { get => FB.Type2; set => FB.Type2 = (byte)value; }
|
||||
public override int CatchRate { get => FB.CatchRate; set => FB.CatchRate = (byte)value; }
|
||||
public override int EvoStage { get => FB.EvoStage; set => FB.EvoStage = (byte)value; }
|
||||
public override int EV_HP { get => FB.EV_HP ; set => FB.EV_HP = (byte)value; }
|
||||
public override int EV_ATK { get => FB.EV_ATK; set => FB.EV_ATK = (byte)value; }
|
||||
public override int EV_DEF { get => FB.EV_DEF; set => FB.EV_DEF = (byte)value; }
|
||||
public override int EV_SPE { get => FB.EV_SPE; set => FB.EV_SPE = (byte)value; }
|
||||
public override int EV_SPA { get => FB.EV_SPA; set => FB.EV_SPA = (byte)value; }
|
||||
public override int EV_SPD { get => FB.EV_SPD; set => FB.EV_SPD = (byte)value; }
|
||||
public int Item1 { get => FB.Item1; set => FB.Item1 = (ushort)value; }
|
||||
public int Item2 { get => FB.Item2; set => FB.Item2 = (ushort)value; }
|
||||
public int Item3 { get => FB.Item3; set => FB.Item3 = (ushort)value; }
|
||||
public override int Gender { get => FB.Gender; set => FB.Gender = (byte)value; }
|
||||
public override int HatchCycles { get => 0; set { } }
|
||||
public override int BaseFriendship { get => FB.BaseFriendship; set => FB.BaseFriendship = (byte)value; }
|
||||
public override int EXPGrowth { get => FB.EXPGrowth; set => FB.EXPGrowth = (byte)value; }
|
||||
public override int EggGroup1 { get => FB.EggGroup1; set => FB.EggGroup1 = (byte)value; }
|
||||
public override int EggGroup2 { get => FB.EggGroup2; set => FB.EggGroup2 = (byte)value; }
|
||||
public int Ability1 { get => FB.Ability1; set => FB.Ability1 = (ushort)value; }
|
||||
public int Ability2 { get => FB.Ability2; set => FB.Ability2 = (ushort)value; }
|
||||
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 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; }
|
||||
|
||||
public override int[] Items
|
||||
{
|
||||
get => new[] { Item1, Item2, Item3 };
|
||||
set
|
||||
{
|
||||
if (value.Length != 3) return;
|
||||
Item1 = value[0];
|
||||
Item2 = value[1];
|
||||
Item3 = value[2];
|
||||
}
|
||||
}
|
||||
|
||||
public override int[] Abilities
|
||||
{
|
||||
get => new[] { Ability1, Ability2, AbilityH };
|
||||
set
|
||||
{
|
||||
if (value.Length != 3) return;
|
||||
Ability1 = value[0];
|
||||
Ability2 = value[1];
|
||||
AbilityH = value[2];
|
||||
}
|
||||
}
|
||||
|
||||
public int HatchSpecies { get => FB.HatchSpecies; set => FB.HatchSpecies = (ushort)value; }
|
||||
public int LocalFormIndex { get => FB.LocalFormIndex; set => FB.LocalFormIndex = (ushort)value; } // local region base form
|
||||
public int Species { get => FB.Species; set => FB.Species = (ushort)value; }
|
||||
public int Form { get => FB.Form; set => FB.Form = (ushort)value; }
|
||||
public int DexIndexHisui { get => FB.DexIndexHisui ; set => FB.DexIndexHisui = (ushort)value; }
|
||||
public int DexIndexLocal1 { get => FB.DexIndexLocal1; set => FB.DexIndexLocal1 = (ushort)value; }
|
||||
public int DexIndexLocal2 { get => FB.DexIndexLocal2; set => FB.DexIndexLocal2 = (ushort)value; }
|
||||
public int DexIndexLocal3 { get => FB.DexIndexLocal3; set => FB.DexIndexLocal3 = (ushort)value; }
|
||||
public int DexIndexLocal4 { get => FB.DexIndexLocal4; set => FB.DexIndexLocal4 = (ushort)value; }
|
||||
public int DexIndexLocal5 { get => FB.DexIndexLocal5; set => FB.DexIndexLocal5 = (ushort)value; }
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public class PersonalInfoLAfb
|
||||
{
|
||||
[FlatBufferItem(00)] public ushort Species { get; set; } // ushort
|
||||
[FlatBufferItem(01)] public ushort Form { get; set; } // ushort
|
||||
[FlatBufferItem(02)] public byte IsPresentInGame { get; set; } // byte
|
||||
[FlatBufferItem(02)] public bool IsPresentInGame { get; set; } // byte
|
||||
[FlatBufferItem(03)] public byte Type1 { get; set; } // byte
|
||||
[FlatBufferItem(04)] public byte Type2 { get; set; } // byte
|
||||
[FlatBufferItem(05)] public ushort Ability1 { get; set; } // ushort
|
||||
@@ -97,11 +97,11 @@ public static byte[] GetBin(PersonalTableLA table)
|
||||
return data;
|
||||
}
|
||||
|
||||
public static PersonalInfoLA[] FromArceus(PersonalTableLA table)
|
||||
public static PersonalInfoLA_Bin[] FromArceus(PersonalTableLA table)
|
||||
{
|
||||
var max = table.Table.Max(z => z.Species);
|
||||
var baseForms = new PersonalInfoLA[max + 1];
|
||||
var formTable = new List<PersonalInfoLA>();
|
||||
var baseForms = new PersonalInfoLA_Bin[max + 1];
|
||||
var formTable = new List<PersonalInfoLA_Bin>();
|
||||
|
||||
for (int i = 0; i <= max; i++)
|
||||
{
|
||||
@@ -117,9 +117,9 @@ public static PersonalInfoLA[] FromArceus(PersonalTableLA table)
|
||||
}
|
||||
|
||||
// ugly converter to be a data-backed object
|
||||
private static PersonalInfoLA GetObj(PersonalInfoLAfb e, List<PersonalInfoLAfb> forms, ushort max, List<PersonalInfoLA> formTable, int f = 0)
|
||||
private static PersonalInfoLA_Bin GetObj(PersonalInfoLAfb e, List<PersonalInfoLAfb> forms, ushort max, List<PersonalInfoLA_Bin> formTable, int f = 0)
|
||||
{
|
||||
var result = new PersonalInfoLA(new byte[PersonalInfoLA.SIZE])
|
||||
var result = new PersonalInfoLA_Bin(new byte[PersonalInfoLA_Bin.SIZE])
|
||||
{
|
||||
HP = e.Stat_HP,
|
||||
ATK = e.Stat_ATK,
|
||||
@@ -134,7 +134,7 @@ private static PersonalInfoLA GetObj(PersonalInfoLAfb e, List<PersonalInfoLAfb>
|
||||
Ability1 = e.Ability1,
|
||||
Ability2 = e.Ability2,
|
||||
AbilityH = e.AbilityH,
|
||||
IsPresentInGame = e.IsPresentInGame == 1,
|
||||
IsPresentInGame = e.IsPresentInGame,
|
||||
Item1 = e.Item1,
|
||||
Item2 = e.Item2,
|
||||
Height = e.Height,
|
||||
|
||||
@@ -5,11 +5,11 @@ namespace pkNX.Structures
|
||||
/// <summary>
|
||||
/// <see cref="PersonalInfo"/> class with values from the <see cref="GameVersion.PLA"/> games.
|
||||
/// </summary>
|
||||
public sealed class PersonalInfoLA : PersonalInfo
|
||||
public sealed class PersonalInfoLA_Bin : PersonalInfo
|
||||
{
|
||||
public const int SIZE = 0xB0;
|
||||
|
||||
public PersonalInfoLA(byte[] data)
|
||||
public PersonalInfoLA_Bin(byte[] data)
|
||||
{
|
||||
Data = data;
|
||||
LoadTMHM();
|
||||
|
||||
@@ -46,7 +46,6 @@ private static int GetEntrySize(GameVersion format)
|
||||
GameVersion.ORAS => PersonalInfoORAS.SIZE,
|
||||
GameVersion.SM or GameVersion.USUM or GameVersion.GP or GameVersion.GE or GameVersion.GG => PersonalInfoSM.SIZE,
|
||||
GameVersion.SW or GameVersion.SH or GameVersion.SWSH => PersonalInfoSWSH.SIZE,
|
||||
GameVersion.PLA => PersonalInfoLA.SIZE,
|
||||
_ => -1
|
||||
};
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public void DumpPokeInfo()
|
||||
|
||||
var lrd = ROM.GetFile(GameFile.Learnsets)[0];
|
||||
var lr = FlatBufferConverter.DeserializeFrom<Learnset8a>(lrd);
|
||||
var evd = ROM.GetFilteredFolder(GameFile.Evolutions)[0];
|
||||
var evd = ROM.GetFile(GameFile.Evolutions)[0];
|
||||
var ev = FlatBufferConverter.DeserializeFrom<EvolutionTable8>(evd);
|
||||
var pt = GetPersonal();
|
||||
var altForms = pt.GetFormList(s, pt.MaxSpeciesID);
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using pkNX.Game;
|
||||
|
||||
namespace pkNX.WinForms.Controls
|
||||
{
|
||||
internal class EditorAO : EditorBase
|
||||
{
|
||||
protected internal EditorAO(GameManager rom) : base(rom) { }
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@ namespace pkNX.WinForms.Controls
|
||||
{
|
||||
internal class EditorGG : EditorBase
|
||||
{
|
||||
protected internal EditorGG(GameManager rom) : base(rom) { }
|
||||
private readonly GameData Data;
|
||||
protected internal EditorGG(GameManagerGG rom) : base(rom) => Data = rom.Data;
|
||||
|
||||
public void EditCommon()
|
||||
{
|
||||
@@ -50,7 +51,7 @@ public void EditTrainers()
|
||||
TrainerClass = ROM.GetFilteredFolder(GameFile.TrainerClass),
|
||||
};
|
||||
editor.Initialize();
|
||||
using var form = new BTTE(ROM, editor);
|
||||
using var form = new BTTE(Data, editor, ROM);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
editor.CancelEdits();
|
||||
@@ -62,13 +63,13 @@ public void EditTrainers()
|
||||
{
|
||||
var editor = new PokeEditor
|
||||
{
|
||||
Evolve = ROM.Data.EvolutionData,
|
||||
Learn = ROM.Data.LevelUpData,
|
||||
Mega = ROM.Data.MegaEvolutionData,
|
||||
Personal = ROM.Data.PersonalData,
|
||||
Evolve = Data.EvolutionData,
|
||||
Learn = Data.LevelUpData,
|
||||
Mega = Data.MegaEvolutionData,
|
||||
Personal = Data.PersonalData,
|
||||
TMHM = Legal.TMHM_GG,
|
||||
};
|
||||
using var form = new PokeDataUI(editor, ROM);
|
||||
using var form = new PokeDataUI(editor, ROM, Data);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
editor.CancelEdits();
|
||||
@@ -109,7 +110,7 @@ public void EditMoves()
|
||||
}
|
||||
|
||||
cache.Save();
|
||||
ROM.Data.MoveData.ClearAll(); // force reload if used again
|
||||
Data.MoveData.ClearAll(); // force reload if used again
|
||||
}
|
||||
|
||||
public void EditGift()
|
||||
@@ -124,13 +125,13 @@ void Randomize()
|
||||
{
|
||||
var spec = EditUtil.Settings.Species;
|
||||
spec.Gen2 = spec.Gen3 = spec.Gen4 = spec.Gen5 = spec.Gen6 = spec.Gen7 = false;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec);
|
||||
foreach (var t in objs)
|
||||
{
|
||||
t.Species = (Species)srand.GetRandomSpecies((int)t.Species);
|
||||
t.Form = frand.GetRandomForme((int)t.Species, false, false, true, false, ROM.Data.PersonalData.Table);
|
||||
t.Form = frand.GetRandomForme((int)t.Species, false, false, true, false, Data.PersonalData.Table);
|
||||
t.Nature = Nature.Random25;
|
||||
t.Gender = FixedGender.Random;
|
||||
t.Shiny = Shiny.Random;
|
||||
@@ -160,14 +161,14 @@ void Randomize()
|
||||
{
|
||||
var spec = EditUtil.Settings.Species;
|
||||
spec.Gen2 = spec.Gen3 = spec.Gen4 = spec.Gen5 = spec.Gen6 = spec.Gen7 = false;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec, 808, 809); // can only catch 1-151 in wild
|
||||
foreach (var t in objs)
|
||||
{
|
||||
t.Species = (Species)srand.GetRandomSpecies((int)t.Species);
|
||||
t.RequiredSpecies = (Species)srand.GetRandomSpecies((int)t.Species);
|
||||
t.Form = frand.GetRandomForme((int)t.Species, false, false, true, false, ROM.Data.PersonalData.Table);
|
||||
t.Form = frand.GetRandomForme((int)t.Species, false, false, true, false, Data.PersonalData.Table);
|
||||
t.RequiredForm = 0; // can't catch wild alolan forms
|
||||
t.Nature = Nature.Random - 1;
|
||||
t.Gender = FixedGender.Random;
|
||||
@@ -198,14 +199,14 @@ void Randomize()
|
||||
{
|
||||
var spec = EditUtil.Settings.Species;
|
||||
spec.Gen2 = spec.Gen3 = spec.Gen4 = spec.Gen5 = spec.Gen6 = spec.Gen7 = false;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec);
|
||||
for (int i = 2; i < objs.Length; i++) // skip starters
|
||||
{
|
||||
var t = objs[i];
|
||||
t.Species = (Species)srand.GetRandomSpecies((int)t.Species);
|
||||
t.Form = frand.GetRandomForme((int)t.Species, false, false, true, false, ROM.Data.PersonalData.Table);
|
||||
t.Form = frand.GetRandomForme((int)t.Species, false, false, true, false, Data.PersonalData.Table);
|
||||
t.Nature = Nature.Random25;
|
||||
t.Gender = FixedGender.Random;
|
||||
t.Shiny = Shiny.Random;
|
||||
@@ -231,7 +232,7 @@ private void PopWildEdit(GameFile type)
|
||||
var data = file[0];
|
||||
var obj = FlatBufferConverter.DeserializeFrom<EncounterArchive7b>(data);
|
||||
|
||||
using var form = new GGWE(ROM, obj);
|
||||
using var form = new GGWE((GameManagerGG)ROM, obj);
|
||||
if (form.ShowDialog() != DialogResult.OK)
|
||||
return;
|
||||
|
||||
@@ -273,7 +274,7 @@ public void EditTM()
|
||||
}
|
||||
|
||||
var moves = list.GetMoves();
|
||||
var allowed = Legal.GetAllowedMoves(ROM.Game, ROM.Data.MoveData.Length);
|
||||
var allowed = Legal.GetAllowedMoves(ROM.Game, Data.MoveData.Length);
|
||||
var names = ROM.GetStrings(TextName.MoveNames);
|
||||
using var editor = new TMList(moves, allowed, names);
|
||||
editor.ShowDialog();
|
||||
@@ -332,7 +333,7 @@ private void EditShop(bool shop2)
|
||||
if (!shop2)
|
||||
{
|
||||
var table = shop.Shop1;
|
||||
var names = table.Select((z, i) => $"{(z.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray();
|
||||
var names = table.Select((z, _) => $"{(z.LGPE.TryGetValue(z.Hash, out var shopName) ? shopName : z.Hash.ToString("X"))}").ToArray();
|
||||
var cache = new DirectCache<Shop1>(table);
|
||||
using var form = new GenericEditor<Shop1>(cache, names, $"{nameof(Shop1)} Editor", Randomize);
|
||||
form.ShowDialog();
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using pkNX.Game;
|
||||
|
||||
namespace pkNX.WinForms.Controls
|
||||
{
|
||||
internal class EditorORASDEMO : EditorBase
|
||||
{
|
||||
protected internal EditorORASDEMO(GameManager rom) : base(rom) { }
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,13 @@ namespace pkNX.WinForms.Controls;
|
||||
|
||||
internal class EditorPLA : EditorBase
|
||||
{
|
||||
protected internal EditorPLA(GameManager rom) : base(rom) => CheckOodleDllPresence();
|
||||
private readonly GameData8a Data;
|
||||
|
||||
protected internal EditorPLA(GameManagerPLA rom) : base(rom)
|
||||
{
|
||||
Data = rom.Data;
|
||||
CheckOodleDllPresence();
|
||||
}
|
||||
|
||||
private static void CheckOodleDllPresence()
|
||||
{
|
||||
@@ -136,14 +142,14 @@ static string GetDetail(EventEncount8a z, string[] names)
|
||||
|
||||
void Randomize(IEnumerable<EventEncount8a> arr)
|
||||
{
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new { Species = i, Present = ((PersonalInfoLA)z).IsPresentInGame })
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
|
||||
var spec = EditUtil.Settings.Species;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec, ban);
|
||||
foreach (var entry in arr)
|
||||
{
|
||||
@@ -153,7 +159,7 @@ void Randomize(IEnumerable<EventEncount8a> arr)
|
||||
if (t.Form != 0 || t.Species is (int)Species.Arceus) // Keep boss battles same?
|
||||
continue;
|
||||
t.Species = srand.GetRandomSpecies(t.Species);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, ROM.Data.PersonalData.Table);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, Data.PersonalData.Table);
|
||||
t.Nature = (int)Nature.Serious;
|
||||
t.Gender = (int)FixedGender.Random;
|
||||
t.ShinyLock = ShinyType8a.Random;
|
||||
@@ -178,21 +184,21 @@ public void EditGift()
|
||||
|
||||
void Randomize(IEnumerable<PokeAdd8a> arr)
|
||||
{
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new { Species = i, Present = ((PersonalInfoLA)z).IsPresentInGame })
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
|
||||
var spec = EditUtil.Settings.Species;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec, ban);
|
||||
foreach (var t in arr)
|
||||
{
|
||||
if (t.Form != 0 || t.Species is (int)Species.Arceus) // Keep boss battles same?
|
||||
continue;
|
||||
t.Species = srand.GetRandomSpecies(t.Species);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, ROM.Data.PersonalData.Table);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, Data.PersonalData.Table);
|
||||
t.Nature = NatureType8a.Random;
|
||||
t.Gender = (int)FixedGender.Random;
|
||||
t.ShinyLock = ShinyType8a.Random;
|
||||
@@ -244,7 +250,7 @@ public void EditMoves()
|
||||
}
|
||||
|
||||
cache.Save();
|
||||
ROM.Data.MoveData.ClearAll(); // force reload if used again
|
||||
Data.MoveData.ClearAll(); // force reload if used again
|
||||
}
|
||||
|
||||
public void EditItems()
|
||||
|
||||
@@ -55,20 +55,13 @@ public IEnumerable<Button> GetControls(int width, int height)
|
||||
|
||||
public void Close() => ROM.SaveAll(true);
|
||||
|
||||
private static EditorBase? GetEditor(GameManager ROM)
|
||||
private static EditorBase? GetEditor(GameManager ROM) => ROM switch
|
||||
{
|
||||
var g = ROM.Game;
|
||||
if (GameVersion.XY.Contains(g)) return new EditorXY(ROM);
|
||||
if (g == GameVersion.ORASDEMO) return new EditorORASDEMO(ROM);
|
||||
if (GameVersion.ORAS.Contains(g)) return new EditorAO(ROM);
|
||||
if (g == GameVersion.SMDEMO) return new EditorSMDEMO(ROM);
|
||||
if (GameVersion.SM.Contains(g)) return new EditorSM(ROM);
|
||||
if (GameVersion.USUM.Contains(g)) return new EditorUU(ROM);
|
||||
if (GameVersion.GG.Contains(g)) return new EditorGG(ROM);
|
||||
if (GameVersion.SWSH.Contains(g)) return new EditorSWSH(ROM);
|
||||
if (GameVersion.PLA.Contains(g)) return new EditorPLA(ROM);
|
||||
return null;
|
||||
}
|
||||
GameManagerGG gg => new EditorGG(gg),
|
||||
GameManagerSWSH swsh => new EditorSWSH(swsh),
|
||||
GameManagerPLA pla => new EditorPLA(pla),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
public static EditorBase? GetEditor(string loc, int language)
|
||||
{
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using pkNX.Game;
|
||||
|
||||
namespace pkNX.WinForms.Controls
|
||||
{
|
||||
internal class EditorSM : EditorBase
|
||||
{
|
||||
protected internal EditorSM(GameManager rom) : base(rom) { }
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using pkNX.Game;
|
||||
|
||||
namespace pkNX.WinForms.Controls
|
||||
{
|
||||
internal class EditorSMDEMO : EditorBase
|
||||
{
|
||||
protected internal EditorSMDEMO(GameManager rom) : base(rom) { }
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@ namespace pkNX.WinForms.Controls
|
||||
{
|
||||
internal class EditorSWSH : EditorBase
|
||||
{
|
||||
protected internal EditorSWSH(GameManager rom) : base(rom) { }
|
||||
private readonly GameData Data;
|
||||
protected internal EditorSWSH(GameManagerSWSH rom) : base(rom) => Data = rom.Data;
|
||||
|
||||
public void EditCommon()
|
||||
{
|
||||
@@ -51,7 +52,7 @@ public void EditTrainers()
|
||||
TrainerClass = ROM.GetFilteredFolder(GameFile.TrainerClass),
|
||||
};
|
||||
editor.Initialize();
|
||||
using var form = new BTTE(ROM, editor);
|
||||
using var form = new BTTE(Data, editor, ROM);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
editor.CancelEdits();
|
||||
@@ -63,13 +64,13 @@ public void EditTrainers()
|
||||
{
|
||||
var editor = new PokeEditor
|
||||
{
|
||||
Evolve = ROM.Data.EvolutionData,
|
||||
Learn = ROM.Data.LevelUpData,
|
||||
Mega = ROM.Data.MegaEvolutionData,
|
||||
Personal = ROM.Data.PersonalData,
|
||||
Evolve = Data.EvolutionData,
|
||||
Learn = Data.LevelUpData,
|
||||
Mega = Data.MegaEvolutionData,
|
||||
Personal = Data.PersonalData,
|
||||
TMHM = Legal.TMHM_SWSH,
|
||||
};
|
||||
using var form = new PokeDataUI(editor, ROM);
|
||||
using var form = new PokeDataUI(editor, ROM, Data);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
editor.CancelEdits();
|
||||
@@ -143,7 +144,7 @@ public void NotWorking_EditTM()
|
||||
}
|
||||
|
||||
var moves = list.GetMoves();
|
||||
var allowed = Legal.GetAllowedMoves(ROM.Game, ROM.Data.MoveData.Length);
|
||||
var allowed = Legal.GetAllowedMoves(ROM.Game, Data.MoveData.Length);
|
||||
var names = ROM.GetStrings(TextName.MoveNames);
|
||||
using var editor = new TMList(moves, allowed, names);
|
||||
editor.ShowDialog();
|
||||
@@ -218,7 +219,7 @@ private void PopWildEdit(string file)
|
||||
h = FlatBufferConverter.DeserializeFrom<EncounterArchive8>(hdo);
|
||||
}
|
||||
|
||||
using var form = new SSWE(ROM, s, h);
|
||||
using var form = new SSWE((GameManagerSWSH)ROM, s, h);
|
||||
form.ShowDialog();
|
||||
if (!form.Modified)
|
||||
return;
|
||||
@@ -245,21 +246,21 @@ public void EditRaids()
|
||||
|
||||
void Randomize()
|
||||
{
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new {Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame})
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
|
||||
var spec = EditUtil.Settings.Species;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec, ban);
|
||||
foreach (var t in arr)
|
||||
{
|
||||
foreach (var p in t.Entries)
|
||||
{
|
||||
p.Species = srand.GetRandomSpecies(p.Species);
|
||||
p.Form = frand.GetRandomForme(p.Species, false, false, true, true, ROM.Data.PersonalData.Table);
|
||||
p.Form = frand.GetRandomForme(p.Species, false, false, true, true, Data.PersonalData.Table);
|
||||
p.Ability = 4; // "A4" -- 1, 2, or H
|
||||
p.Gender = 0; // random
|
||||
p.IsGigantamax = false; // don't allow gmax flag on non-gmax species
|
||||
@@ -350,21 +351,21 @@ public void EditStatic()
|
||||
void Randomize()
|
||||
{
|
||||
int[] PossibleHeldItems = Legal.GetRandomItemList(ROM.Game);
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new {Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame})
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
|
||||
var spec = EditUtil.Settings.Species;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec, ban);
|
||||
foreach (var t in encounters)
|
||||
{
|
||||
if (t.Species is >= (int)Species.Zacian and <= (int)Species.Eternatus) // Eternatus crashes when changed, keep Zacian and Zamazenta to make final boss battle fair
|
||||
continue;
|
||||
t.Species = srand.GetRandomSpecies(t.Species);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, ROM.Data.PersonalData.Table);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, Data.PersonalData.Table);
|
||||
t.Ability = Randomization.Util.Random.Next(1, 4); // 1, 2, or H
|
||||
t.HeldItem = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)];
|
||||
t.Nature = (int)Nature.Random25;
|
||||
@@ -467,7 +468,7 @@ public void EditMoves()
|
||||
}
|
||||
|
||||
cache.Save();
|
||||
ROM.Data.MoveData.ClearAll(); // force reload if used again
|
||||
Data.MoveData.ClearAll(); // force reload if used again
|
||||
}
|
||||
|
||||
public void EditRental()
|
||||
@@ -531,14 +532,14 @@ public void EditGift()
|
||||
void Randomize()
|
||||
{
|
||||
int[] PossibleHeldItems = Legal.GetRandomItemList(ROM.Game);
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new {Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame})
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
|
||||
var spec = EditUtil.Settings.Species;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec, ban);
|
||||
foreach (var t in gifts)
|
||||
{
|
||||
@@ -546,12 +547,12 @@ void Randomize()
|
||||
if (t.CanGigantamax || t.Species == (int)Species.Kubfu)
|
||||
{
|
||||
t.Species = Legal.GigantamaxForms[Randomization.Util.Random.Next(Legal.GigantamaxForms.Length)];
|
||||
t.Form = (byte)(t.Species is (int)Species.Pikachu or (int)Species.Meowth ? 0 : frand.GetRandomForme(t.Species, false, false, false, false, ROM.Data.PersonalData.Table)); // Pikachu & Meowth altforms can't gmax
|
||||
t.Form = (byte)(t.Species is (int)Species.Pikachu or (int)Species.Meowth ? 0 : frand.GetRandomForme(t.Species, false, false, false, false, Data.PersonalData.Table)); // Pikachu & Meowth altforms can't gmax
|
||||
}
|
||||
else
|
||||
{
|
||||
t.Species = srand.GetRandomSpecies(t.Species);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, ROM.Data.PersonalData.Table);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, Data.PersonalData.Table);
|
||||
}
|
||||
|
||||
t.Ability = Randomization.Util.Random.Next(1, 4); // 1, 2, or H
|
||||
@@ -620,20 +621,20 @@ public void EditTrade()
|
||||
void Randomize()
|
||||
{
|
||||
int[] PossibleHeldItems = Legal.GetRandomItemList(ROM.Game);
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new {Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame})
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
|
||||
var spec = EditUtil.Settings.Species;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec, ban);
|
||||
foreach (var t in trades)
|
||||
{
|
||||
// what you receive
|
||||
t.Species = srand.GetRandomSpecies(t.Species);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, ROM.Data.PersonalData.Table);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, Data.PersonalData.Table);
|
||||
t.AbilityNumber = (byte)Randomization.Util.Random.Next(1, 4); // 1, 2, or H
|
||||
t.Ball = (Ball)Randomization.Util.Random.Next(1, EncounterTrade8.BallToItem.Length);
|
||||
t.HeldItem = PossibleHeldItems[Randomization.Util.Random.Next(PossibleHeldItems.Length)];
|
||||
@@ -646,7 +647,7 @@ void Randomize()
|
||||
|
||||
// what you trade
|
||||
t.RequiredSpecies = srand.GetRandomSpecies(t.RequiredSpecies);
|
||||
t.RequiredForm = (byte)frand.GetRandomForme(t.RequiredSpecies, false, false, true, true, ROM.Data.PersonalData.Table);
|
||||
t.RequiredForm = (byte)frand.GetRandomForme(t.RequiredSpecies, false, false, true, true, Data.PersonalData.Table);
|
||||
t.RequiredNature = (int)Nature.Random25; // any
|
||||
}
|
||||
}
|
||||
@@ -671,20 +672,20 @@ public void EditDynamaxAdv()
|
||||
|
||||
void Randomize()
|
||||
{
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
int[] ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new { Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame })
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
|
||||
var spec = EditUtil.Settings.Species;
|
||||
var srand = new SpeciesRandomizer(ROM.Info, ROM.Data.PersonalData);
|
||||
var frand = new FormRandomizer(ROM.Data.PersonalData);
|
||||
var srand = new SpeciesRandomizer(ROM.Info, Data.PersonalData);
|
||||
var frand = new FormRandomizer(Data.PersonalData);
|
||||
srand.Initialize(spec, ban);
|
||||
foreach (var t in table)
|
||||
{
|
||||
// what you receive
|
||||
t.Species = srand.GetRandomSpecies(t.Species);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, ROM.Data.PersonalData.Table);
|
||||
t.Form = (byte)frand.GetRandomForme(t.Species, false, false, true, true, Data.PersonalData.Table);
|
||||
t.Ability = (uint)Randomization.Util.Random.Next(1, 4); // 1, 2, or H
|
||||
t.Move0 = t.Move1 = t.Move2 = t.Move3 = 0;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
using System.Windows.Forms;
|
||||
using pkNX.Game;
|
||||
|
||||
namespace pkNX.WinForms.Controls
|
||||
{
|
||||
internal class EditorUU : EditorBase
|
||||
{
|
||||
protected internal EditorUU(GameManager rom) : base(rom) { }
|
||||
|
||||
public void TestButton()
|
||||
{
|
||||
using var form = new Form();
|
||||
form.ShowDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using pkNX.Game;
|
||||
|
||||
namespace pkNX.WinForms.Controls
|
||||
{
|
||||
internal class EditorXY : EditorBase
|
||||
{
|
||||
protected internal EditorXY(GameManager rom) : base(rom) { }
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ public partial class BTTE : Form
|
||||
|
||||
private readonly PersonalTable Personal;
|
||||
private readonly GameManager Game;
|
||||
private readonly GameData Data;
|
||||
private readonly TrainerEditor Trainers;
|
||||
|
||||
private readonly string[] abilitylist;
|
||||
@@ -38,15 +39,16 @@ public partial class BTTE : Form
|
||||
|
||||
private readonly CheckBox[] AIBits;
|
||||
|
||||
public BTTE(GameManager game, TrainerEditor editor)
|
||||
public BTTE(GameData data, TrainerEditor editor, GameManager game)
|
||||
{
|
||||
Game = game;
|
||||
Data = data;
|
||||
Trainers = editor;
|
||||
InitializeComponent();
|
||||
pba = new[] { PB_Team1, PB_Team2, PB_Team3, PB_Team4, PB_Team5, PB_Team6 };
|
||||
|
||||
Stats.Personal = Personal = game.Data.PersonalData;
|
||||
Game = game;
|
||||
Trainers = editor;
|
||||
learn = new LearnsetRandomizer(game.Info, game.Data.LevelUpData.LoadAll(), Personal);
|
||||
Stats.Personal = Personal = data.PersonalData;
|
||||
learn = new LearnsetRandomizer(game.Info, data.LevelUpData.LoadAll(), Personal);
|
||||
|
||||
AltForms = new byte[Personal.TableLength]
|
||||
.Select(_ => Enumerable.Range(0, 32).Select(i => i.ToString()).ToArray()).ToArray();
|
||||
@@ -540,7 +542,7 @@ private void B_HighAttack_Click(object sender, EventArgs e)
|
||||
pkm.Species = CB_Species.SelectedIndex;
|
||||
pkm.Level = (int)NUD_Level.Value;
|
||||
pkm.Form = CB_Forme.SelectedIndex;
|
||||
var movedata = Game.Data.MoveData.LoadAll();
|
||||
var movedata = Data.MoveData.LoadAll();
|
||||
var moves = learn.GetHighPoweredMoves(movedata, pkm.Species, pkm.Form, 4);
|
||||
SetMoves(moves);
|
||||
}
|
||||
@@ -581,7 +583,7 @@ private void B_Randomize_Click(object sender, EventArgs e)
|
||||
|
||||
private TrainerRandomizer GetRandomizer()
|
||||
{
|
||||
var moves = Game.Data.MoveData.LoadAll();
|
||||
var moves = Data.MoveData.LoadAll();
|
||||
var rmove = new MoveRandomizer(Game.Info, moves, Personal);
|
||||
int[] banned = Legal.GetBannedMoves(Game.Info.Game, moves.Length);
|
||||
rmove.Initialize((MovesetRandSettings)PG_Moves.SelectedObject, banned);
|
||||
@@ -589,7 +591,7 @@ private TrainerRandomizer GetRandomizer()
|
||||
|
||||
if (Game.Info.SWSH)
|
||||
{
|
||||
var pt = Game.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
ban = pt.Table.Take(Game.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new {Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame})
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
@@ -599,7 +601,7 @@ private TrainerRandomizer GetRandomizer()
|
||||
var rform = new FormRandomizer(Personal);
|
||||
rspec.Initialize((SpeciesSettings)PG_Species.SelectedObject, ban);
|
||||
learn.Moves = moves;
|
||||
var evos = Game.Data.EvolutionData;
|
||||
var evos = Data.EvolutionData;
|
||||
var trand = new TrainerRandomizer(Game.Info, Personal, Trainers.LoadAll(), evos.LoadAll())
|
||||
{
|
||||
ClassCount = CB_Trainer_Class.Items.Count,
|
||||
|
||||
@@ -13,10 +13,10 @@ namespace pkNX.WinForms
|
||||
public sealed partial class GGWE : Form
|
||||
{
|
||||
private readonly EncounterArchive7b Tables;
|
||||
private readonly GameManager ROM;
|
||||
private readonly GameManagerGG ROM;
|
||||
private int entry = -1;
|
||||
|
||||
public GGWE(GameManager rom, EncounterArchive7b obj)
|
||||
public GGWE(GameManagerGG rom, EncounterArchive7b obj)
|
||||
{
|
||||
InitializeComponent();
|
||||
if (obj.EncounterTables.Length == 0 || obj.EncounterTables[0].GroundTable.Length == 0)
|
||||
|
||||
@@ -15,11 +15,13 @@ namespace pkNX.WinForms
|
||||
public partial class PokeDataUI : Form
|
||||
{
|
||||
private readonly bool Loaded;
|
||||
private readonly GameData Data;
|
||||
|
||||
public PokeDataUI(PokeEditor editor, GameManager rom)
|
||||
public PokeDataUI(PokeEditor editor, GameManager rom, GameData data)
|
||||
{
|
||||
ROM = rom;
|
||||
Editor = editor;
|
||||
Data = data;
|
||||
InitializeComponent();
|
||||
|
||||
helditem_boxes = new[] { CB_HeldItem1, CB_HeldItem2, CB_HeldItem3 };
|
||||
@@ -37,7 +39,7 @@ public PokeDataUI(PokeEditor editor, GameManager rom)
|
||||
species[0] = "---";
|
||||
abilities[0] = items[0] = movelist[0] = "";
|
||||
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
cPersonal = pt[0];
|
||||
cLearnset = Editor.Learn[0];
|
||||
cEvos = Editor.Evolve[0];
|
||||
@@ -520,7 +522,7 @@ private void B_RandEvo_Click(object sender, EventArgs e)
|
||||
|
||||
if (ROM.Info.SWSH)
|
||||
{
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new {Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame})
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
@@ -556,7 +558,7 @@ private void B_EvolveEveryLevel_Click(object sender, EventArgs e)
|
||||
|
||||
if (ROM.Info.SWSH)
|
||||
{
|
||||
var pt = ROM.Data.PersonalData;
|
||||
var pt = Data.PersonalData;
|
||||
ban = pt.Table.Take(ROM.Info.MaxSpeciesID + 1)
|
||||
.Select((z, i) => new {Species = i, Present = ((PersonalInfoSWSH)z).IsPresentInGame})
|
||||
.Where(z => !z.Present).Select(z => z.Species).ToArray();
|
||||
@@ -575,7 +577,7 @@ private void B_RandLearn_Click(object sender, EventArgs e)
|
||||
var settings = (LearnSettings)PG_Learn.SelectedObject;
|
||||
var moveset = (MovesetRandSettings)PG_Move.SelectedObject;
|
||||
var rand = new LearnsetRandomizer(ROM.Info, Editor.Learn.LoadAll(), Editor.Personal);
|
||||
var moves = ROM.Data.MoveData.LoadAll();
|
||||
var moves = Data.MoveData.LoadAll();
|
||||
int[] banned = Legal.GetBannedMoves(ROM.Info.Game, moves.Length);
|
||||
rand.Initialize(moves, settings, moveset, banned);
|
||||
rand.Execute();
|
||||
@@ -594,7 +596,7 @@ private void B_LearnExpand_Click(object sender, EventArgs e)
|
||||
}
|
||||
var moveset = (MovesetRandSettings)PG_Move.SelectedObject;
|
||||
var rand = new LearnsetRandomizer(ROM.Info, Editor.Learn.LoadAll(), Editor.Personal);
|
||||
rand.Initialize(ROM.Data.MoveData.LoadAll(), settings, moveset);
|
||||
rand.Initialize(Data.MoveData.LoadAll(), settings, moveset);
|
||||
rand.ExecuteExpandOnly();
|
||||
LoadIndex(CB_Species.SelectedIndex);
|
||||
System.Media.SystemSounds.Asterisk.Play();
|
||||
@@ -605,7 +607,7 @@ private void B_LearnMetronome_Click(object sender, EventArgs e)
|
||||
var settings = (LearnSettings)PG_Learn.SelectedObject;
|
||||
var moveset = (MovesetRandSettings)PG_Move.SelectedObject;
|
||||
var rand = new LearnsetRandomizer(ROM.Info, Editor.Learn.LoadAll(), Editor.Personal);
|
||||
rand.Initialize(ROM.Data.MoveData.LoadAll(), settings, moveset);
|
||||
rand.Initialize(Data.MoveData.LoadAll(), settings, moveset);
|
||||
rand.ExecuteMetronome();
|
||||
LoadIndex(CB_Species.SelectedIndex);
|
||||
System.Media.SystemSounds.Asterisk.Play();
|
||||
|
||||
@@ -15,12 +15,12 @@ public sealed partial class SSWE : Form
|
||||
{
|
||||
private readonly EncounterArchive8 Symbols;
|
||||
private readonly EncounterArchive8 Hidden;
|
||||
private readonly GameManager ROM;
|
||||
private readonly GameManagerSWSH ROM;
|
||||
private ulong entry;
|
||||
|
||||
private readonly EncounterList8[] SL;
|
||||
|
||||
public SSWE(GameManager rom, EncounterArchive8 sym, EncounterArchive8 hid)
|
||||
public SSWE(GameManagerSWSH rom, EncounterArchive8 sym, EncounterArchive8 hid)
|
||||
{
|
||||
InitializeComponent();
|
||||
Symbols = sym;
|
||||
|
||||
Reference in New Issue
Block a user