Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion SysBot.Base/Control/SwitchRoutineExecutor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
Expand Down Expand Up @@ -35,6 +35,18 @@ public async Task PressAndHold(SwitchButton b, int hold, int delay, Cancellation
await Task.Delay(delay, token).ConfigureAwait(false);
}

public async Task PressAndHold(SwitchButton b, int delay, CancellationToken token)
{
await Connection.SendAsync(SwitchCommand.Hold(b, UseCRLF), token).ConfigureAwait(false);
await Task.Delay(delay, token).ConfigureAwait(false);
}

public async Task ReleaseHold(SwitchButton b, int delay, CancellationToken token)
{
await Connection.SendAsync(SwitchCommand.Release(b, UseCRLF), token).ConfigureAwait(false);
await Task.Delay(delay, token).ConfigureAwait(false);
}

public async Task DaisyChainCommands(int delay, IEnumerable<SwitchButton> buttons, CancellationToken token)
{
SwitchCommand.Configure(SwitchConfigureParameter.mainLoopSleepTime, delay, UseCRLF);
Expand Down
3 changes: 3 additions & 0 deletions SysBot.Pokemon/Actions/PokeRoutineType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public enum PokeRoutineType
/// <summary> Retrieves Floette until the criteria is satisfied. </summary>
EncounterFloette = 7_005,

/// <summary> Retrieves Diancie until the criteria is satisfied. </summary>
EncounterDiancie = 7_006,

/// <summary> Keeps running circles until all party members have the Partner mark. </summary>
PartnerMark = 7_050,

Expand Down
110 changes: 110 additions & 0 deletions SysBot.Pokemon/LZA/BotEncounter/EncounterBotDiancieLZA.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
namespace SysBot.Pokemon;

using PKHeX.Core;
using SysBot.Base;
using System;
using System.Threading;
using System.Threading.Tasks;
using static Base.SwitchButton;
using static Base.SwitchStick;

public class EncounterBotDiancieLZA(PokeBotState cfg, PokeTradeHub<PA9> hub) : EncounterBotLZA(cfg, hub)
{
private readonly ushort _diancie = (ushort)Species.Diancie;
private readonly ushort _carbink = (ushort)Species.Carbink;

protected override async Task EncounterLoop(SAV9ZA sav, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
await EnableAlwaysCatch(token).ConfigureAwait(false);

Log("Starting Diancie encounter sequence");
await SetStick(LEFT, 0, 30_000, 0_500, token).ConfigureAwait(false);
await ResetStick(token).ConfigureAwait(false);
await RepeatClick(A, 20_000, 100, token).ConfigureAwait(false);

Log("Catching Diancie");

var result = EncounterResult.Unknown;
while (result != EncounterResult.DiancieFound)
{
await PressAndHold(ZL, 0_250, token).ConfigureAwait(false);
await Click(ZR, 0_100, token).ConfigureAwait(false);
await ReleaseHold(ZL, 0_250, token).ConfigureAwait(false);

for (int slot = 0; slot < 3; slot++)
{
result = await LookupSlot(slot, token).ConfigureAwait(false);

if (result is EncounterResult.InvalidSpecies or EncounterResult.ResultFound)
{
return; // Exit the encounter loop entirely
}

if (result is EncounterResult.DiancieFound)
{
Log($"Diancie found in B1S{slot + 1}, rebooting the game...");
break;
}
}
}

await ReOpenGame(Hub.Config, token).ConfigureAwait(false);
await Task.Delay(10_000, token).ConfigureAwait(false);
}
}

public override async Task HardStop()
{
await ReleaseHold(ZL, 0_500, CancellationToken.None).ConfigureAwait(false);
await base.HardStop().ConfigureAwait(false);
}

private async Task<EncounterResult> LookupSlot(int slot, CancellationToken token)
{
(var pa9, var raw) = await ReadRawBoxPokemon(0, slot, token).ConfigureAwait(false);
if (pa9.Species > 0 && pa9.Species != _diancie && pa9.Species != _carbink)
{
Log($"Detected species {(Species)pa9.Species}, which shouldn't be possible. Only 'none', 'Carbink' or 'Diancie' are expected");
return EncounterResult.InvalidSpecies;
}

if (pa9.Species == _diancie && pa9.Valid && pa9.EncryptionConstant > 0)
{
var (stop, success) = await HandleEncounter(pa9, token, raw, true).ConfigureAwait(false);

if (success)
{
Log($"Your Pokémon has been received and placed in B1S{slot + 1}. Auto-save will do the rest!");
}

if (stop)
return EncounterResult.ResultFound;
}

return pa9.Species == _diancie
? EncounterResult.DiancieFound
: EncounterResult.NextSlot;
}

private async Task RepeatClick(SwitchButton button, int duration, int delay, CancellationToken token)
{
var endTime = DateTime.Now.AddMilliseconds(duration);

while (DateTime.Now < endTime)
{
await Click(button, delay, token).ConfigureAwait(false);
}
}

private enum EncounterResult
{
Unknown,

InvalidSpecies,
ResultFound,
DiancieFound,
NextSlot
}
}
14 changes: 14 additions & 0 deletions SysBot.Pokemon/LZA/BotEncounter/EncounterBotLZA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,18 @@ protected async Task ResetStick(CancellationToken token)
// If aborting the sequence, we might have the stick set at some position. Clear it just in case.
await SetStick(LEFT, 0, 0, 0_500, token).ConfigureAwait(false); // reset
}

protected async Task EnableAlwaysCatch(CancellationToken token)
{
Log("Enable 100% catch rate cheat", false);
// Source: https://gbatemp.net/threads/pokemon-legends-z-a-cheat-database.675579/

// Original cheat:
/*
* [№56. 100% Catch Rate]
* 040A0000 00447448 52800028
*/

await SwitchConnection.WriteBytesMainAsync(BitConverter.GetBytes(0x52800028), 0x00447448, token);
}
}
2 changes: 2 additions & 0 deletions SysBot.Pokemon/LZA/BotFactory9LZA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public sealed class BotFactory9LZA : BotFactory<PA9>
{
public override PokeRoutineExecutorBase CreateBot(PokeTradeHub<PA9> hub, PokeBotState cfg) => cfg.NextRoutineType switch
{
PokeRoutineType.EncounterDiancie => new EncounterBotDiancieLZA(cfg, hub),
PokeRoutineType.EncounterFloette => new EncounterBotFloetteLZA(cfg, hub),
PokeRoutineType.EncounterOverworld => new EncounterBotOverworldScannerLZA(cfg, hub),
PokeRoutineType.FossilBot => new EncounterBotFossilLZA(cfg, hub),
Expand All @@ -18,6 +19,7 @@ public sealed class BotFactory9LZA : BotFactory<PA9>

public override bool SupportsRoutine(PokeRoutineType type) => type switch
{
PokeRoutineType.EncounterDiancie => true,
PokeRoutineType.EncounterFloette => true,
PokeRoutineType.EncounterOverworld => true,
PokeRoutineType.FossilBot => true,
Expand Down
12 changes: 6 additions & 6 deletions SysBot.Pokemon/LZA/Vision/PokeDataOffsetsLZA.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ namespace SysBot.Pokemon;
/// </summary>
public class PokeDataOffsetsLZA
{
public const string ZAGameVersion = "2.0.0";
public const string ZAGameVersion = "2.0.1";
public const string LegendsZAID = "0100F43008C44000";

public IReadOnlyList<long> BoxStartPokemonPointer { get; } = [0x6105710, 0xB0, 0x978, 0x0];
public IReadOnlyList<long> MyStatusPointer { get; } = [0x6105710, 0x80, 0x100];
public IReadOnlyList<long> KItemPointer { get; } = [0x6105670, 0x30, 0x08, 0x460];
public IReadOnlyList<long> KOverworldPointer { get; } = [0x6105670, 0x30, 0x08, 0x9E0];
public IReadOnlyList<long> KStoredShinyEntityPointer { get; } = [0x6105670, 0x30, 0x08, 0x1660];
public IReadOnlyList<long> BoxStartPokemonPointer { get; } = [0x610A710, 0xB0, 0x978, 0x0];
public IReadOnlyList<long> MyStatusPointer { get; } = [0x610A710, 0x80, 0x100];
public IReadOnlyList<long> KItemPointer { get; } = [0x610A670, 0x30, 0x08, 0x480];
public IReadOnlyList<long> KOverworldPointer { get; } = [0x610A670, 0x30, 0x08, 0xA00];
public IReadOnlyList<long> KStoredShinyEntityPointer { get; } = [0x610A670, 0x30, 0x08, 0x1680];

public const uint KItemKey = 0x21C9BD44;
public const uint KOverworldKey = 0x5E8E1711;
Expand Down
6 changes: 3 additions & 3 deletions SysBot.Pokemon/Settings/FolderSettings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel;
using System.ComponentModel;
using System.IO;

namespace SysBot.Pokemon;
Expand All @@ -10,10 +10,10 @@ public class FolderSettings : IDumper
public override string ToString() => "Folder / Dumping Settings";

[Category(FeatureToggle), Description("When enabled, dumps any received PKM files (trade results) to the DumpFolder.")]
public bool Dump { get; set; }
public bool Dump { get; set; } = false;

[Category(FeatureToggle), Description("When enabled, dumps any raw/encrypted received PKM files (trade results) to the DumpFolder.")]
public bool DumpRaw { get; set; }
public bool DumpRaw { get; set; } = true;

[Category(FeatureToggle), Description("When enabled with previous option, dumps only any received Shiny PKM files (trade results) to the DumpFolder.")]
public bool DumpShinyOnly { get; set; }
Expand Down
Loading