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
13 changes: 13 additions & 0 deletions Documentation/11.-Bench-Sitting-Legends-Z-A.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Legends: Z-A: Bench Sitting

This guide covers bench sitting in Pokémon Legends: Z-A. This mode automates overworld spawns until a `StopCondition` is matched.

## Setup

1. Set `Overworld` -> `Mode` to `BenchSit`
2. Position your character as shown in the screenshot below:
![Character positioned facing bench](assets/bench-sit-position.jpg)

## Notes

The settings `StopOnMaxShiniesStored` and `OverworldSpawnCheck` are only used when the `StopCondition` contains records with `ShinyTarget` set to `AnyShiny`, `StarOnly`, or `SquareOnly`. Since there is a separate place in memory where the shinies are stored (maximum of 10), the bot doesn't have to save after each round.
13 changes: 13 additions & 0 deletions Documentation/12.-Wild-Zone-Entrance-Legends-Z-A.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Legends: Z-A: Wild Zone Entrance

This guide covers Wild Zone Entrance in Pokémon Legends: Z-A. This mode automates overworld spawns until a `StopCondition` is matched.

## Setup

1. Set `Overworld` -> `Mode` to `WildZoneEntrance`
2. Position your character as shown in the screenshot below:
![Character positioned facing the entrance](assets/wild-zone-entrance-position.jpg)

## Notes

The settings `StopOnMaxShiniesStored` and `OverworldSpawnCheck` are only used when the `StopCondition` contains records with `ShinyTarget` set to `AnyShiny`, `StarOnly`, or `SquareOnly`. Since there is a separate place in memory where the shinies are stored (maximum of 10), the bot doesn't have to save after each round.
9 changes: 9 additions & 0 deletions Documentation/13.-Fossil-Revive-Legends-Z-A.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Legends: Z-A: Revive Fossils

This guide covers reviving Fossils in Pokémon Legends: Z-A until a `StopCondition` is matched.

## Setup

1. Make sure to have atleast one of each species
2. Choose the Fossil species to revive or choose 'Any' if you want to revive all Fossils in your item bag.
3. Position your character at the scientist and start the bot
14 changes: 10 additions & 4 deletions Documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,16 @@ Welcome to the Sysbot.NET wiki!

## Sword/Shield

1. [Encounter Calyrex and Spectrier/Glastrier](7.-Encounter-Calyrex-and-Spectrier-Glastrier.md)
2. [Unlimited egg mode](8.-Unlimited-egg-mode-Sword-Shield.md)
3. [(beta) Den/raid](9.-(beta)-Den-raid.md)
7. [Encounter Calyrex and Spectrier/Glastrier](7.-Encounter-Calyrex-and-Spectrier-Glastrier.md)
8. [Unlimited egg mode](8.-Unlimited-egg-mode-Sword-Shield.md)
9. [(beta) Den/raid](9.-(beta)-Den-raid.md)

## Brilliant Diamond/Shining Pearl

10. [Eggs (including Unlimited egg mode)](10.-Eggs-(including-Unlimited-egg-mode)-Brilliant-Diamond-Shining-Pearl.md)
10. [Eggs (including Unlimited egg mode)](10.-Eggs-(including-Unlimited-egg-mode)-Brilliant-Diamond-Shining-Pearl.md)

## Legends: Z-A

11. [Bench Sitting](11.-Bench-Sitting-Legends-Z-A.md)
12. [Wild Zone Entrance](12.-Wild-Zone-Entrance-Legends-Z-A.md)
13. [Fossil reviving](13.-Fossil-Revive-Legends-Z-A.md)
Binary file added Documentation/assets/bench-sit-position.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ If this project does not suit your needs, you are welcome to use an alternative.

These routines are new compared to the original SysBot.NET.

#### Legends: Z-A

- Bench Sit
- Wild Zone Entrance
- Fossil reviving

#### Scarlet/Violet

- Encounters (Ruinous, Loyal Three, Gimmighoul, and static/new Paradox Pokémon in Area Zero)
Expand Down Expand Up @@ -40,6 +46,12 @@ Currently, the [latest](https://github.com/Eppin/sys-botbase/releases) version i

## Version compatibility

### Legends: Z-A

| Version | SysBot Release |
| :-----: | :---------------------------------------------------------------------------: |
| 1.0.1 | [xx.xx.xx.xxx](https://github.com/Eppin/Sysbot.NET/releases/tag/xx.xx.xx.xxx) |

### Scarlet/Violet

| Version | SysBot Release | Egg-mod Release |
Expand Down
2 changes: 1 addition & 1 deletion SysBot.Base/SysBot.Base.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="NLog" Version="5.5.0" />
<PackageReference Include="NLog" Version="5.5.1" />
<PackageReference Include="LibUsbDotNet" Version="2.2.75" />
</ItemGroup>

Expand Down
6 changes: 2 additions & 4 deletions SysBot.Pokemon.ConsoleApp/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using SysBot.Pokemon.ZA;

namespace SysBot.Pokemon.ConsoleApp;

Expand Down Expand Up @@ -63,10 +64,6 @@ private static void ExitNoConfig()
}
}

[JsonSerializable(typeof(ProgramConfig))]
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
public sealed partial class ProgramConfigContext : JsonSerializerContext;

public static class BotContainer
{
public static void RunBots(ProgramConfig prog)
Expand Down Expand Up @@ -114,6 +111,7 @@ private static void WaitForExit()
ProgramMode.BDSP => new PokeBotRunnerImpl<PB8>(prog.Hub, new BotFactory8BS()),
ProgramMode.LA => new PokeBotRunnerImpl<PA8>(prog.Hub, new BotFactory8LA()),
ProgramMode.SV => new PokeBotRunnerImpl<PK9>(prog.Hub, new BotFactory9SV()),
ProgramMode.ZA => new PokeBotRunnerImpl<PA9>(prog.Hub, new BotFactory9LZA()),
_ => throw new IndexOutOfRangeException("Unsupported mode."),
};

Expand Down
10 changes: 2 additions & 8 deletions SysBot.Pokemon.Discord/Commands/Management/EmbedModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,12 @@ private static (string Text, Embed? Embed) Embed(T? pkm, bool success)
return pkm switch
{
null => ("(no valid data to embed)", null),
PK8 pk8 => EmbedPk(pk8, success),
PB8 pb8 => EmbedPk(pb8, success),
PK9 pk9 => EmbedPk(pk9, success),
_ => ("(unsupported embed)", null)
_ => EmbedPk(pkm, success)
};
}

private static (string Text, Embed? Embed) EmbedPk(PKM pkm, bool success)
private static (string Text, Embed? Embed) EmbedPk(T pk, bool success)
{
if (pkm is not T pk)
throw new Exception();

var url = OutputExtensions<T>.PokeImage(pk, false, false);

var is1of100 = (Species)pk.Species is Species.Dunsparce or Species.Tandemaus;
Expand Down
6 changes: 3 additions & 3 deletions SysBot.Pokemon.Discord/Helpers/ReusableActions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Discord;
using Discord;
using Discord.WebSocket;
using PKHeX.Core;
using SysBot.Base;
Expand All @@ -14,15 +14,15 @@ public static class ReusableActions
{
public static async Task SendPKMAsync(this IMessageChannel channel, PKM pkm, string msg = "")
{
var tmp = Path.Combine(Path.GetTempPath(), Util.CleanFileName(pkm.FileName));
var tmp = Path.Combine(Path.GetTempPath(), PathUtil.CleanFileName(pkm.FileName));
File.WriteAllBytes(tmp, pkm.DecryptedPartyData);
await channel.SendFileAsync(tmp, msg).ConfigureAwait(false);
File.Delete(tmp);
}

public static async Task SendPKMAsync(this IUser user, PKM pkm, string msg = "")
{
var tmp = Path.Combine(Path.GetTempPath(), Util.CleanFileName(pkm.FileName));
var tmp = Path.Combine(Path.GetTempPath(), PathUtil.CleanFileName(pkm.FileName));
File.WriteAllBytes(tmp, pkm.DecryptedPartyData);
await user.SendFileAsync(tmp, msg).ConfigureAwait(false);
File.Delete(tmp);
Expand Down
8 changes: 4 additions & 4 deletions SysBot.Pokemon.Discord/SysBot.Pokemon.Discord.csproj
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.17.4" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageReference Include="PKHeX.Core" Version="25.5.18" />
<PackageReference Include="Discord.Net" Version="3.18.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.10" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.10" />
<PackageReference Include="PKHeX.Core" Version="25.11.7" />
<ProjectReference Include="..\SysBot.Base\SysBot.Base.csproj" />
<ProjectReference Include="..\SysBot.Pokemon\SysBot.Pokemon.csproj" />
</ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions SysBot.Pokemon.Twitch/SysBot.Pokemon.Twitch.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="PKHeX.Core" Version="25.5.18" />
<PackageReference Include="TwitchLib.Client" Version="3.3.1" />
<PackageReference Include="PKHeX.Core" Version="25.11.7" />
<PackageReference Include="TwitchLib.Client" Version="3.4.0" />
</ItemGroup>

<ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions SysBot.Pokemon.WinForms/InitUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public static void InitializeStubs(ProgramMode mode)
ProgramMode.BDSP => new SAV8BS(),
ProgramMode.LA => new SAV8LA(),
ProgramMode.SV => new SAV9SV(),
ProgramMode.ZA => new SAV9ZA(),
_ => throw new System.ArgumentOutOfRangeException(nameof(mode)),
};

Expand Down
6 changes: 2 additions & 4 deletions SysBot.Pokemon.WinForms/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using SysBot.Pokemon.ZA;

namespace SysBot.Pokemon.WinForms;

Expand Down Expand Up @@ -81,6 +82,7 @@ public Main()
ProgramMode.BDSP => new PokeBotRunnerImpl<PB8>(cfg.Hub, new BotFactory8BS()),
ProgramMode.LA => new PokeBotRunnerImpl<PA8>(cfg.Hub, new BotFactory8LA()),
ProgramMode.SV => new PokeBotRunnerImpl<PK9>(cfg.Hub, new BotFactory9SV()),
ProgramMode.ZA => new PokeBotRunnerImpl<PA9>(cfg.Hub, new BotFactory9LZA()),
_ => throw new IndexOutOfRangeException("Unsupported mode."),
};

Expand Down Expand Up @@ -185,10 +187,6 @@ private void SaveCurrentConfig()
File.WriteAllText(Program.ConfigPath, lines);
}

[JsonSerializable(typeof(ProgramConfig))]
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
public sealed partial class ProgramConfigContext : JsonSerializerContext { }

private void B_Start_Click(object sender, EventArgs e)
{
SaveCurrentConfig();
Expand Down
4 changes: 2 additions & 2 deletions SysBot.Pokemon.WinForms/SysBot.Pokemon.WinForms.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="PKHeX.Core" Version="25.5.18" />
<PackageReference Include="System.Resources.Extensions" Version="9.0.5" />
<PackageReference Include="PKHeX.Core" Version="25.11.7" />
<PackageReference Include="System.Resources.Extensions" Version="9.0.10" />
</ItemGroup>

<ItemGroup>
Expand Down
10 changes: 5 additions & 5 deletions SysBot.Pokemon.YouTube/SysBot.Pokemon.YouTube.csproj
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="Google.Apis" Version="1.69.0" />
<PackageReference Include="Google.Apis.Auth" Version="1.69.0" />
<PackageReference Include="Google.Apis.Core" Version="1.69.0" />
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.69.0.3764" />
<PackageReference Include="Google.Apis" Version="1.72.0" />
<PackageReference Include="Google.Apis.Auth" Version="1.72.0" />
<PackageReference Include="Google.Apis.Core" Version="1.72.0" />
<PackageReference Include="Google.Apis.YouTube.v3" Version="1.70.0.3847" />
<PackageReference Include="Google.Apis.YouTubePartner.v1" Version="1.35.1.1334" />
<PackageReference Include="PKHeX.Core" Version="25.5.18" />
<PackageReference Include="PKHeX.Core" Version="25.11.7" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion SysBot.Pokemon.Z3/SysBot.Pokemon.Z3.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="PKHeX.Core" Version="25.5.18" />
<PackageReference Include="PKHeX.Core" Version="25.11.7" />
</ItemGroup>

<ItemGroup>
Expand Down
37 changes: 32 additions & 5 deletions SysBot.Pokemon/Actions/PokeRoutineExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@
using System.Threading;
using System.Threading.Tasks;
using static SysBot.Base.SwitchButton;
using static System.Buffers.Binary.BinaryPrimitives;

namespace SysBot.Pokemon;

public abstract class PokeRoutineExecutor<T> : PokeRoutineExecutorBase where T : PKM, new()
public abstract class PokeRoutineExecutor<T>(IConsoleBotManaged<IConsoleConnection, IConsoleConnectionAsync> cfg)
: PokeRoutineExecutorBase(cfg) where T : PKM, new()
{
protected PokeRoutineExecutor(IConsoleBotManaged<IConsoleConnection, IConsoleConnectionAsync> cfg) : base(cfg)
{
}

public abstract Task<T> ReadPokemon(ulong offset, CancellationToken token);
public abstract Task<T> ReadPokemon(ulong offset, int size, CancellationToken token);
public abstract Task<T> ReadPokemonPointer(IEnumerable<long> jumps, int size, CancellationToken token);
Expand Down Expand Up @@ -115,6 +113,7 @@ public void DumpPokemon(string folder, string subfolder, PKM pk, byte[] bytes)
{
PK8 pk8 => StopConditionSettings.HasMark(pk8, out var mark) ? $"{mark.ToString().Replace("Mark", "")}Mark - " : "",
PK9 pk9 => StopConditionSettings.HasMark(pk9, out var mark) ? $"{mark.ToString().Replace("Mark", "")}Mark - " : "",
PA9 pa9 => StopConditionSettings.HasMark(pa9, out var mark) ? $"{mark.ToString().Replace("Mark", "")}Mark - " : "",
_ => markType
};

Expand All @@ -128,6 +127,8 @@ public void DumpPokemon(string folder, string subfolder, PKM pk, byte[] bytes)
filetype += "pa8";
if (pk is PK9)
filetype += "pk9";
if (pk is PA9)
filetype += "pa9";

if (!Directory.Exists(folder))
{
Expand Down Expand Up @@ -342,4 +343,30 @@ private async Task BlockUser(CancellationToken token)
await Click(A, 1_100, token).ConfigureAwait(false);
await Click(A, 1_100, token).ConfigureAwait(false);
}

public async Task<byte[]> ReadEncryptedBlock(ulong keyAddress, uint blockKey, CancellationToken token)
{
const int warningSize = 1_024 * 10; // 10 KB

var header = await SwitchConnection.ReadBytesAbsoluteAsync(keyAddress, 5, token).ConfigureAwait(false);
header = DecryptBlock(blockKey, header);

var size = ReadUInt32LittleEndian(header.AsSpan()[1..]);

if (size > warningSize) Log($"Retrieving {size/1024} KB (this may take a while, using WiFi, use USB if available)");

var data = await SwitchConnection.ReadBytesAbsoluteAsync(keyAddress, 5 + (int)size, token).ConfigureAwait(false);
var res = DecryptBlock(blockKey, data)[5..];

return res;
}

public static byte[] DecryptBlock(uint key, byte[] block)
{
var rng = new SCXorShift32(key);
for (var i = 0; i < block.Length; i++)
block[i] = (byte)(block[i] ^ rng.Next());

return block;
}
}
3 changes: 2 additions & 1 deletion SysBot.Pokemon/BDSP/BotEncounter/EncounterBotBS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace SysBot.Pokemon;

using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Base;
Expand Down Expand Up @@ -95,7 +96,7 @@ public override async Task HardStop()

if (!StopConditionSettings.EncounterFound(pk, Hub.Config.StopConditions, null))
{
if (folder.Equals("egg") && Hub.Config.StopConditions.ShinyTarget is TargetShinyType.AnyShiny or TargetShinyType.StarOnly or TargetShinyType.SquareOnly && pk.IsShiny)
if (folder.Equals("egg") && Hub.Config.StopConditions.SearchConditions.Any(sc => sc.IsEnabled && pk.IsShiny && sc.ShinyTarget is TargetShinyType.AnyShiny or TargetShinyType.StarOnly or TargetShinyType.SquareOnly))
Hub.LogEmbed(pk, false);

return (false, false);
Expand Down
Loading
Loading