-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit ec6a8f2
Showing
27 changed files
with
2,886 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
using PKHeX.Core; | ||
using System.Runtime.InteropServices.JavaScript; | ||
using System.Collections.Generic; | ||
|
||
namespace PkCompletionist.Core; | ||
partial class Command | ||
{ | ||
public Command() | ||
{ | ||
LastCommand = this; | ||
} | ||
|
||
public static Command? LastCommand = null; | ||
|
||
List<string> Messages = new(); | ||
public SaveFile? savA = null; | ||
public SaveFile? savB = null; | ||
|
||
public void AddMessage(string msg) | ||
{ | ||
Messages.Add(msg); | ||
} | ||
|
||
public void AddError(string msg) | ||
{ | ||
AddMessage(msg); | ||
} | ||
|
||
public SaveFile? SetSavA(byte[] data) | ||
{ | ||
savA = SaveUtil.GetVariantSAV(data); | ||
if (savA == null) | ||
Messages.Add("Error: Failed to parse the content of the save file."); | ||
return savA; | ||
} | ||
public SaveFile? SetSavB(byte[] data) | ||
{ | ||
savB = SaveUtil.GetVariantSAV(data); | ||
if (savB == null) | ||
Messages.Add("Error: Failed to parse the content of the save file."); | ||
return savB; | ||
} | ||
|
||
[JSExport] | ||
public static string[] GetMessages() | ||
{ | ||
if (LastCommand == null) | ||
return System.Array.Empty<string>(); | ||
return LastCommand.Messages.ToArray(); | ||
} | ||
|
||
[JSExport] | ||
public static byte[] GetSavA() | ||
{ | ||
if (LastCommand?.savA == null) | ||
return System.Array.Empty<byte>(); | ||
return LastCommand.savA.Write(); | ||
} | ||
|
||
[JSExport] | ||
public static byte[] GetSavB() | ||
{ | ||
if (LastCommand?.savB == null) | ||
return System.Array.Empty<byte>(); | ||
return LastCommand.savB.Write(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using PKHeX.Core; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Runtime.InteropServices.JavaScript; | ||
|
||
namespace PkCompletionist.Core; | ||
|
||
partial class CompletionValidator : Command | ||
{ | ||
static public CompletionValidatorX? LastValidatorX = null; | ||
|
||
[JSExport] | ||
static public bool Execute(byte[] savData, bool living) | ||
{ | ||
var validator = new CompletionValidator(); | ||
var savA = validator.SetSavA(savData); | ||
if (savA == null) | ||
return false; | ||
|
||
var validatorX = validator.CreateValidatorX(savA, living); | ||
CompletionValidator.LastValidatorX = validatorX; | ||
|
||
validatorX.GenerateAll(); | ||
|
||
return true; | ||
} | ||
|
||
CompletionValidatorX CreateValidatorX(SaveFile savA, bool living) | ||
{ | ||
if (savA is SAV1) | ||
return new CompletionValidator1(this, (savA as SAV1)!, living); | ||
|
||
if (savA is SAV2) | ||
return new CompletionValidator2(this, (savA as SAV2)!, living); | ||
|
||
if (savA is SAV3) | ||
return new CompletionValidator3(this, (savA as SAV3)!, living); | ||
|
||
return new CompletionValidatorX(this, savA, living); | ||
} | ||
|
||
[JSExport] | ||
static public string[] GetLastObtainedStatus() | ||
{ | ||
if (LastValidatorX == null) | ||
return System.Array.Empty<string>(); | ||
|
||
string[] Res = new string[LastValidatorX.owned.Count * 3]; | ||
|
||
int i = 0; | ||
foreach (var Info in LastValidatorX.owned) | ||
{ | ||
Res[i] = Info.Key; | ||
List<string> obtained = new(); | ||
List<string> notObtained = new(); | ||
|
||
foreach (var Info2 in Info.Value) | ||
{ | ||
if (Info2.Value) | ||
obtained.Add(Info2.Key); | ||
else | ||
notObtained.Add(Info2.Key); | ||
} | ||
Res[i + 1] = System.String.Join(',', obtained); | ||
Res[i + 2] = System.String.Join(',', notObtained); | ||
i += 3; | ||
} | ||
return Res; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
using PKHeX.Core; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace PkCompletionist.Core; | ||
partial class CompletionValidatorX | ||
{ | ||
protected SaveFile sav; | ||
public Dictionary<string, Dictionary<string, bool>> owned = new (); | ||
protected bool living = false; | ||
protected List<int> unobtainableItems = new (); | ||
Command command; | ||
|
||
public CompletionValidatorX(Command command, SaveFile sav, bool living) | ||
{ | ||
this.command = command; | ||
this.sav = sav; | ||
this.living = living; | ||
} | ||
|
||
|
||
public void AddMessage(string msg) | ||
{ | ||
this.command.AddMessage(msg); | ||
} | ||
|
||
public virtual void GenerateAll() | ||
{ | ||
Generate_pokemon(); | ||
Generate_item(); | ||
} | ||
|
||
public virtual void Generate_pokemon() | ||
{ | ||
var ow = new Dictionary<string, bool>(); | ||
owned["pokemon"] = ow; | ||
|
||
if (this.living) | ||
{ | ||
var pkms = sav.GetAllPKM(); | ||
for (ushort i = 1; i <= sav.MaxSpeciesID; i++) | ||
ow[i.ToString()] = pkms.Any(pkm => pkm.Species == i); | ||
} | ||
else | ||
{ | ||
for (ushort i = 1; i <= sav.MaxSpeciesID; i++) | ||
ow[i.ToString()] = sav.GetCaught(i); | ||
} | ||
} | ||
|
||
public virtual void Generate_item() | ||
{ | ||
var ow = new Dictionary<string, bool>(); | ||
owned["item"] = ow; | ||
|
||
for (ushort i = 1; i <= sav.MaxItemID; i++) | ||
{ | ||
if (this.unobtainableItems.Contains(i)) | ||
continue; | ||
ow[i.ToString()] = SavUtils.HasItem(sav, i); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
using PKHeX.Core; | ||
using System.Linq; | ||
using System.Runtime.InteropServices.JavaScript; | ||
|
||
namespace PkCompletionist.Core; | ||
|
||
enum PK_EVENT | ||
{ | ||
Gen1_Mew, //Classic: Toys "R" Us Mew ᅠ https://projectpokemon.org/home/files/file/1791-classic-toys-r-us-mew/ | ||
Gen1_PikachuSurf, // manually created using info from bulbapedia | ||
Gen2_Mew, //Celebi Present Campaign, Shiny Mew, https://projectpokemon.org/home/files/file/4073-pcny-distribution-machine-savefiles/ | ||
Gen2_Celebi, //Celebi Tour Spain 2001, Celebi https://projectpokemon.org/home/forums/topic/40507-gen-2-celebi-tour-celebi/ | ||
Gen2_GSBall, | ||
Gen2_EggTicket, | ||
Gen2_BlueskyMail, | ||
Gen2_MirageMail, | ||
} | ||
|
||
partial class EventSimulator : Command | ||
{ | ||
[JSExport] | ||
public static bool Execute(string evtStr, byte[] savA) | ||
{ | ||
var simul = new EventSimulator(); | ||
if (simul.SetSavA(savA) == null) | ||
return false; | ||
|
||
if (evtStr == "*") | ||
simul.ExecAllEvents(); | ||
else | ||
{ | ||
if (!System.Enum.TryParse<PK_EVENT>(evtStr, out var evt)) | ||
{ | ||
simul.AddError("Error: Invalid event name."); | ||
return false; | ||
} | ||
var err = simul.ExecEvent(evt); | ||
if (err != null) | ||
{ | ||
simul.AddError(err); | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
|
||
void ExecAllEvents() | ||
{ | ||
foreach (PK_EVENT evt in System.Enum.GetValues(typeof(PK_EVENT))) | ||
{ | ||
var err = ExecEvent(evt); | ||
if (err != null) | ||
AddError(err); | ||
} | ||
} | ||
|
||
string? ExecEvent(PK_EVENT evt) | ||
{ | ||
if (savA?.Generation == 1) | ||
{ | ||
if (evt == PK_EVENT.Gen1_Mew) | ||
return SavUtils.AddPkm(savA, "Gen1_Mew.pk1"); | ||
if (evt == PK_EVENT.Gen1_PikachuSurf) | ||
return SavUtils.AddPkm(savA, "Gen1_PikachuSurf.pk1"); | ||
} | ||
|
||
if (savA?.Generation == 2) | ||
{ | ||
if (evt == PK_EVENT.Gen2_Mew) | ||
return SavUtils.AddPkm(savA, "Gen2_Mew.pk2"); | ||
|
||
if (evt == PK_EVENT.Gen2_Celebi) | ||
return SavUtils.AddPkm(savA, "Gen2_Celebi.pk2"); | ||
|
||
if (evt == PK_EVENT.Gen2_GSBall) | ||
{ | ||
SAV2? sav2 = savA as SAV2; | ||
if (sav2 == null) | ||
return "Error: The save file provided is not Generation 2."; | ||
|
||
var allPkms = sav2.GetAllPKM(); | ||
var celebi = allPkms.Any(pk => | ||
{ | ||
return pk.Species == 251 && pk.TID16 == sav2.TID16 && pk.OT_Name == sav2.OT; | ||
}); | ||
|
||
if (celebi || sav2.GetEventFlag(832) || sav2.GetEventFlag(190) || sav2.GetEventFlag(191) || sav2.GetEventFlag(192)) | ||
return "Error: You already obtained GS Ball."; | ||
|
||
var err = SavUtils.AddItem(sav2, 115 /*GS Ball*/); | ||
if (err != null) | ||
return err; | ||
|
||
sav2.SetEventFlag(832, true); | ||
} | ||
|
||
if (evt == PK_EVENT.Gen2_EggTicket) | ||
return SavUtils.AddItem(savA, 129 /*Egg Ticket*/); | ||
|
||
if (evt == PK_EVENT.Gen2_BlueskyMail) | ||
return SavUtils.AddItem(savA, 187 /*Bluesky Mail*/); | ||
|
||
if (evt == PK_EVENT.Gen2_MirageMail) | ||
return SavUtils.AddItem(savA, 189 /*Mirage Mail*/); | ||
} | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using PKHeX.Core; | ||
using System.Collections.Generic; | ||
using System.Runtime.InteropServices.JavaScript; | ||
|
||
namespace PkCompletionist.Core; | ||
|
||
partial class FlagAnalyzer : Command | ||
{ | ||
int changeRangeStart; | ||
int changeRangeEnd; | ||
|
||
[JSExport] | ||
public static bool Execute(byte[] savA, byte[] savB, int changeRangeStart, int changeRangeEnd) | ||
{ | ||
var simul = new FlagAnalyzer(changeRangeStart, changeRangeEnd); | ||
if (simul.SetSavA(savA) == null) | ||
return false; | ||
if (simul.SetSavB(savB) == null) | ||
return false; | ||
return simul.Execute(); | ||
} | ||
|
||
public FlagAnalyzer(int changeRangeStart, int changeRangeEnd) | ||
{ | ||
this.changeRangeStart = changeRangeStart; | ||
this.changeRangeEnd = changeRangeEnd; | ||
} | ||
|
||
public bool Execute() | ||
{ | ||
if(savA == null || savB == null) | ||
return false; | ||
|
||
byte[] savAData = savA.Data; | ||
byte[] savBData = savB.Data; | ||
|
||
if (savAData.Length != savBData.Length) | ||
{ | ||
AddError("this.sav1.Data.Length != this.sav2.Data.Length"); | ||
return false; | ||
} | ||
|
||
// ignore play time, checksum, for US version only | ||
List<int> toIgnore = new(); | ||
if(savA.Version == GameVersion.C) | ||
toIgnore = new() { 0x1252, 0x1253, 0x1254, 0x1255, 0x1F0D, 0x1F0E, 0x2052, 0x2053, 0x2054, 0x2055, 0x2D0D, 0x2D0E }; | ||
|
||
List<int> diffIdx = new List<int>(); | ||
for (var i = 0; i < savAData.Length; i++) | ||
{ | ||
if (savA.Version == GameVersion.C && toIgnore.IndexOf(i) != -1) | ||
continue; | ||
|
||
if (savAData[i] != savBData[i]) | ||
diffIdx.Add(i); | ||
} | ||
AddMessage($"Change count + 1: {diffIdx.Count + 1}"); | ||
|
||
for (var i = changeRangeStart; i < changeRangeEnd; i++) | ||
{ | ||
if (i >= diffIdx.Count) | ||
continue; | ||
|
||
int idx = diffIdx[i]; | ||
|
||
if (changeRangeEnd - changeRangeStart < 15) | ||
AddMessage($"this.sav1.Data[0x{idx:X}] = 0x{savBData[idx]:X} (old=0x{savAData[idx]:X})"); | ||
|
||
savAData[idx] = savBData[idx]; | ||
} | ||
this.savA.SetData(savAData, 0); | ||
return true; | ||
} | ||
} |
Oops, something went wrong.