Skip to content
Merged
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
34 changes: 34 additions & 0 deletions Documentation/16.-Catch-Volcanion-Legends-Z-A.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Legends: Z-A: Catch Volcanion

This guide covers catching Volcanion until a `StopCondition` is met (e.g., shiny, specific IVs, etc.).

## Prerequisites

- Have access to the Volcanion encounter
- Position yourself in front of Volcanion

## Setup

1. Stand directly in front of Volcanion
2. **Important**: If you start the routine and the battle does not begin, take one more step forward
3. Once positioned correctly, **save your game**
4. Start the bot

## Catch Rate Cheat

- If you select **Master Ball**: No cheat needed (100% catch rate)
- If you select **any other ball**: Enable the 100% catch rate cheat

## How It Works

The bot will:
1. Initiate the battle with Volcanion
2. Attempt to catch Volcanion with your selected ball
3. Check if the caught Volcanion in B1S1 matches your stop conditions
4. If not, reset and repeat the process

## Tips

- Make sure your positioning is correct before starting (battle should begin immediately)
- Use stop conditions to target specific Volcanion (shiny, nature, IVs, etc.)
- Master Ball guarantees a catch without needing cheats
34 changes: 34 additions & 0 deletions Documentation/17.-Catch-Genesect-Legends-Z-A.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Legends: Z-A: Catch Genesect

This guide covers catching Genesect until a `StopCondition` is met (e.g., shiny, specific IVs, etc.).

## Prerequisites

- Have access to the Genesect encounter
- Position yourself in front of Genesect

## Setup

1. Stand directly in front of Genesect
2. **Important**: If you start the routine and the battle does not begin, take one more step forward
3. Once positioned correctly, **save your game**
4. Start the bot

## Catch Rate Cheat

- If you select **Master Ball**: No cheat needed (100% catch rate)
- If you select **any other ball**: Enable the 100% catch rate cheat

## How It Works

The bot will:
1. Initiate the battle with Genesect
2. Attempt to catch Genesect with your selected ball
3. Check if the caught Genesect in B1S1 matches your stop conditions
4. If not, reset and repeat the process

## Tips

- Make sure your positioning is correct before starting (battle should begin immediately)
- Use stop conditions to target specific Genesect (shiny, nature, IVs, etc.)
- Master Ball guarantees a catch without needing cheats
30 changes: 30 additions & 0 deletions Documentation/18.-Receive-Hoopa-Legends-Z-A.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Legends: Z-A: Receive Hoopa

This guide covers receiving Hoopa until a `StopCondition` is met (e.g., specific IVs, etc.).

## Prerequisites

- Have access to the Hoopa event/interactions

## Setup

1. Stand directly in front of the interaction that gives Hoopa
2. Make sure slot 1 of box 1 (B1S1) is empty
3. **Save your game**
4. Start the bot

## How It Works

The bot will:
1. Repeatedly advance dialogue/interactions to receive Hoopa
2. Check B1S1 for the received Hoopa
3. Validate Hoopa against your stop conditions
4. If no match is found, reset and repeat the process

Since Hoopa is available in B1S1 before the auto-save is triggered, this routine can run without any cheats needed.

## Tips

- Make sure you are positioned correctly before starting
- Keep B1S1 empty to avoid species mismatch errors
- Use stop conditions to target specific Hoopa (shiny, nature, IVs, etc.)
30 changes: 30 additions & 0 deletions Documentation/19.-Receive-Magearna-Legends-Z-A.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Legends: Z-A: Receive Magearna

This guide covers receiving Magearna until a `StopCondition` is met (e.g., specific IVs, etc.).

## Prerequisites

- Have access to the Magearna event/interactions

## Setup

1. Stand directly in front of the interaction that gives Magearna
2. Make sure slot 1 of box 1 (B1S1) is empty
3. **Save your game**
4. Start the bot

## How It Works

The bot will:
1. Repeatedly advance dialogue/interactions to receive Magearna
2. Check B1S1 for the received Magearna
3. Validate Magearna against your stop conditions
4. If no match is found, reset and repeat the process

Since Magearna is available in B1S1 before the auto-save is triggered, this routine can run without any cheats needed.

## Tips

- Make sure you are positioned correctly before starting
- Keep B1S1 empty to avoid species mismatch errors
- Use stop conditions to target specific Magearna (shiny, nature, IVs, etc.)
34 changes: 34 additions & 0 deletions Documentation/20.-Catch-Marshadow-Legends-Z-A.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Legends: Z-A: Catch Marshadow

This guide covers catching Marshadow until a `StopCondition` is met (e.g., shiny, specific IVs, etc.).

## Prerequisites

- Have access to the Marshadow encounter
- Position yourself in front of Marshadow

## Setup

1. Stand directly in front of Marshadow
2. **Important**: If you start the routine and the battle does not begin, take one more step forward
3. Once positioned correctly, **save your game**
4. Start the bot

## Catch Rate Cheat

- If you select **Master Ball**: No cheat needed (100% catch rate)
- If you select **any other ball**: Enable the 100% catch rate cheat

## How It Works

The bot will:
1. Initiate the battle with Marshadow
2. Attempt to catch Marshadow with your selected ball
3. Check if the caught Marshadow in B1S1 matches your stop conditions
4. If not, reset and repeat the process

## Tips

- Make sure your positioning is correct before starting (battle should begin immediately)
- Use stop conditions to target specific Marshadow (shiny, nature, IVs, etc.)
- Master Ball guarantees a catch without needing cheats
7 changes: 6 additions & 1 deletion Documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@ Welcome to the Sysbot.NET wiki!
12. [Wild Zone Entrance](12.-Wild-Zone-Entrance-Legends-Z-A.md)
13. [Fossil reviving](13.-Fossil-Revive-Legends-Z-A.md)
14. [Receiving Floette](14.-Receive-Floette-Legends-Z-A.md)
15. [Catch Diancie](15.-Catch-Diancie-Legends-Z-A.md)
15. [Catch Diancie](15.-Catch-Diancie-Legends-Z-A.md)
16. [Catch Volcanion](16.-Catch-Volcanion-Legends-Z-A.md)
17. [Catch Genesect](17.-Catch-Genesect-Legends-Z-A.md)
18. [Receive Hoopa](18.-Receive-Hoopa-Legends-Z-A.md)
19. [Receive Magearna](19.-Receive-Magearna-Legends-Z-A.md)
20. [Catch Marshadow](20.-Catch-Marshadow-Legends-Z-A.md)
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ These routines are new compared to the original SysBot.NET.
- Fossil reviving
- Receiving Floette
- Catching Diancie
- Catching Volcanion
- Catching Genesect
- Receiving Hoopa
- Receiving Magearna
- Catching Marshadow

#### Scarlet/Violet

Expand Down
2 changes: 1 addition & 1 deletion SysBot.Pokemon/Actions/PokeRoutineExecutorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace SysBot.Pokemon;

public abstract class PokeRoutineExecutorBase : SwitchRoutineExecutor<PokeBotState>
{
public const decimal BotbaseVersion = 2.4m;
public const decimal BotbaseVersion = 2.5m;

protected PokeRoutineExecutorBase(IConsoleBotManaged<IConsoleConnection, IConsoleConnectionAsync> cfg) : base(cfg)
{
Expand Down
15 changes: 15 additions & 0 deletions SysBot.Pokemon/Actions/PokeRoutineType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ public enum PokeRoutineType
/// <summary> Retrieves Diancie until the criteria is satisfied. </summary>
EncounterDiancie = 7_006,

/// <summary> Retrieves Volcanion until the criteria is satisfied. </summary>
EncounterVolcanion = 7_007,

/// <summary> Retrieves Genesect until the criteria is satisfied. </summary>
EncounterGenesect = 7_008,

/// <summary> Retrieves Magearna until the criteria is satisfied. </summary>
EncounterMagearna = 7_009,

/// <summary> Retrieves Marshadow until the criteria is satisfied. </summary>
EncounterMarshadow = 7_010,

/// <summary> Retrieves Hoopa until the criteria is satisfied. </summary>
EncounterHoopa = 7_011,

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

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

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

public class EncounterBotGenesectLZA(PokeBotState cfg, PokeTradeHub<PA9> hub) : EncounterBotLZA(cfg, hub)
{
private const ushort GenesectSpecies = (ushort)Species.Genesect;

private const int EncounterTimeoutSeconds = 46;
private const int MashDurationMs = 26_000;
private const int MashDelayMs = 100;
private const int ReopenDelayMs = 10_000;

protected override async Task EncounterLoop(SAV9ZA sav, CancellationToken token)
{
while (!token.IsCancellationRequested)
{
var deadline = DateTime.Now.AddSeconds(EncounterTimeoutSeconds);

await EnableAlwaysCatch(token).ConfigureAwait(false);

Log("Starting Genesect encounter sequence");
await SetStick(LEFT, 0, 30_000, 0_500, token).ConfigureAwait(false);
await ResetStick(token).ConfigureAwait(false);
await RepeatClick(A, MashDurationMs, MashDelayMs, token).ConfigureAwait(false);

Log($"Catching Genesect, wait till [{deadline}] before we force a game restart", false);

await SetStick(LEFT, 0, 30_000, 1_000, token).ConfigureAwait(false);
await ResetStick(token).ConfigureAwait(false);

var result = await TryEncounterUntilDeadline(deadline, token).ConfigureAwait(false);

if (result is EncounterResult.InvalidSpecies or EncounterResult.ResultFound)
return;

if (result == EncounterResult.Timeout)
Log("Force restart of the game...");

await ReOpenGame(Hub.Config, token).ConfigureAwait(false);
await Task.Delay(ReopenDelayMs, 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> TryEncounterUntilDeadline(DateTime deadline, CancellationToken token)
{
while (DateTime.Now <= deadline && !token.IsCancellationRequested)
{
await RunEncounterInput(token).ConfigureAwait(false);

var result = await LookupSlot(token).ConfigureAwait(false);
if (result is EncounterResult.InvalidSpecies or EncounterResult.ResultFound)
return result;

if (result == EncounterResult.GenesectFound)
{
Log("Genesect found in B1S1, rebooting the game...");
return result;
}
}

return EncounterResult.Timeout;
}

private async Task RunEncounterInput(CancellationToken token)
{
await PressAndHold(ZL, 0_250, token).ConfigureAwait(false);
await Click(ZR, 0_100, token).ConfigureAwait(false);
await ReleaseHold(ZL, 0_250, token).ConfigureAwait(false);
}

private async Task<EncounterResult> LookupSlot(CancellationToken token)
{
var (pa9, raw) = await ReadRawBoxPokemon(0, 0, token).ConfigureAwait(false);

if (pa9.Species > 0 && pa9.Species != GenesectSpecies)
{
Log($"Detected species {(Species)pa9.Species}, which shouldn't be possible. Only 'none' or 'Genesect' are expected");
return EncounterResult.InvalidSpecies;
}

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

if (success)
Log("Your Pokemon has been received and placed in B1S1. Auto-save will do the rest!");

if (stop)
return EncounterResult.ResultFound;
}

return pa9.Species == GenesectSpecies
? EncounterResult.GenesectFound
: EncounterResult.NextSlot;
}

private async Task RepeatClick(SwitchButton button, int durationMs, int delayMs, CancellationToken token)
{
var endUtc = DateTime.UtcNow.AddMilliseconds(durationMs);

while (DateTime.UtcNow < endUtc && !token.IsCancellationRequested)
await Click(button, delayMs, token).ConfigureAwait(false);
}

private enum EncounterResult
{
InvalidSpecies,
ResultFound,
GenesectFound,
NextSlot,
Timeout
}
}
Loading
Loading