Skip to content

Commit

Permalink
Merge branch 'main' into github-action
Browse files Browse the repository at this point in the history
  • Loading branch information
hanzi committed Oct 29, 2023
2 parents 37fd7e7 + bf06cc3 commit da9c47e
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ __pycache__
.venv
.idea
.vs
.vscode

*.gba
.last-requirements-check
Expand Down
11 changes: 10 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ The following `console` options will control how much data is displayed in the P
- `encounter_moves`
- `statistics`

### Save raw Pokémon data
### Save raw Pokémon data (.pk3)
The bot can dump individual Pokémon files (.pk3 format) to be managed/transferred in the [PKHeX save editor](https://github.com/kwsch/PKHeX).

The Pokémon are dumped to the `pokemon/` folder in your profile, in the following format:
Expand All @@ -334,6 +334,15 @@ The Pokémon are dumped to the `pokemon/` folder in your profile, in the followi

Feel free to share any rare/interesting .pk3 files in [#pkhexchange💱](https://discord.com/channels/1057088810950860850/1123523909745135616)!

### Automatically add Pokémon to PC storage (.pk3)
While auto-catch is currently still a work in progress, the following option automatically import encountered Pokémon into your PC storage.

Imported Pokémon will be placed into the first available PC slot, in a regular PokéBall.

If space is available in the PC, and the Pokémon was successfully imported, the bot will run from the encounter and continue to hunt.

`import_pk3` - enable automatic .pk3 import to PC storage

</details>

## `discord.yml` - Discord integration config
Expand Down
2 changes: 2 additions & 0 deletions modules/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@
type: boolean
custom:
type: boolean
import_pk3:
type: boolean
"""

discord_schema = """
Expand Down
2 changes: 1 addition & 1 deletion modules/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def write_pk(file: str, data: bytes) -> bool:
to write byte arrays out directly into a file
:param file: File to write to
:param date: Pokemon data to be written
:param data: Pokemon data to be written
:return: True if file was written to successfully, otherwise False (bool)
"""
try:
Expand Down
53 changes: 53 additions & 0 deletions modules/pc_storage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import math

from modules.console import console
from modules.game import get_symbol
from modules.gui import get_emulator, get_rom, set_message
from modules.memory import read_symbol, unpack_uint32
from modules.pokemon import Pokemon

# see pret/pokeemerald:include/pokemon_storage_system.h
TOTAL_BOXES_COUNT = 14
IN_BOX_ROWS = 5
IN_BOX_COLUMNS = 6
IN_BOX_COUNT = IN_BOX_ROWS * IN_BOX_COLUMNS


def _find_pokemon_storage_offset() -> tuple[int, int]:
if get_rom().game_title in ["POKEMON EMER", "POKEMON FIRE", "POKEMON LEAF"]:
offset = unpack_uint32(read_symbol("gPokemonStoragePtr"))
length = get_symbol("gPokemonStorage")[1]
else:
offset, length = get_symbol("gPokemonStorage")
return offset, length


def import_into_storage(data: bytes) -> bool:
data = data[:80]

# find first available spot offset
space_available = False
g_pokemon_storage = _find_pokemon_storage_offset()[0]
for i in range(IN_BOX_COUNT * TOTAL_BOXES_COUNT):
# the first 4 bytes are the current box
# first mon is stored at offset gPokemonStorage + 4
offset_to_check = 4 + i * 80
# if a spot is space_available, it is all 0
space_available = unpack_uint32(get_emulator().read_bytes(g_pokemon_storage + offset_to_check, 4)) == 0
if space_available:
available_offset = offset_to_check
break

pokemon = Pokemon(data)
if pokemon.is_valid and space_available:
box = math.floor(((available_offset / 80) / IN_BOX_COUNT) + 1)
message = f"Saved {pokemon.species.name} to PC box {box}!"
get_emulator().write_bytes(g_pokemon_storage + available_offset, data)
set_message(message)
console.print(message)
else:
message = f"Not enough room in PC to automatically import {pokemon.species.name}!"
set_message(message)
console.print(message)
return False
return True
10 changes: 8 additions & 2 deletions modules/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
from modules.colours import iv_colour, iv_sum_colour, sv_colour
from modules.config import config, force_manual_mode
from modules.console import console
from modules.files import read_file, write_file
from modules.files import read_file, write_file, write_pk
from modules.gui import set_message, get_emulator
from modules.memory import get_game_state, GameState
from modules.pc_storage import import_into_storage
from modules.pokemon import Pokemon
from modules.profiles import Profile
from modules.files import write_pk

custom_catch_filters = None
custom_hooks = None
Expand Down Expand Up @@ -658,6 +658,12 @@ def encounter_pokemon(pokemon: Pokemon) -> None:
filename_suffix = f"{state_tag}_{pokemon.species.safe_name}"
get_emulator().create_save_state(suffix=filename_suffix)

# TEMPORARY until auto-battle/auto-catch is done
# if the mon is saved and imported, no need to catch it by hand
if config["logging"]["import_pk3"]:
if import_into_storage(pokemon.data):
return

force_manual_mode()
get_emulator().set_speed_factor(1)
get_emulator().set_throttle(True)
Expand Down
4 changes: 4 additions & 0 deletions profiles/logging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ save_pk3:
all: false
shiny: true
custom: true

# Automatically load .pk3 file into PC storage
# `true`, `false`
import_pk3: false

0 comments on commit da9c47e

Please sign in to comment.