Files
dockipelago/worlds/PokemonStadium/randomizer/stadium_randomizer.py
Jonathan Tinney 7971961166
Some checks failed
Analyze modified files / flake8 (push) Failing after 2m28s
Build / build-win (push) Has been cancelled
Build / build-ubuntu2204 (push) Has been cancelled
ctest / Test C++ ubuntu-latest (push) Has been cancelled
ctest / Test C++ windows-latest (push) Has been cancelled
Analyze modified files / mypy (push) Has been cancelled
Build and Publish Docker Images / Push Docker image to Docker Hub (push) Successful in 5m4s
Native Code Static Analysis / scan-build (push) Failing after 5m2s
type check / pyright (push) Successful in 1m7s
unittests / Test Python 3.11.2 ubuntu-latest (push) Failing after 16m23s
unittests / Test Python 3.12 ubuntu-latest (push) Failing after 28m19s
unittests / Test Python 3.13 ubuntu-latest (push) Failing after 14m49s
unittests / Test hosting with 3.13 on ubuntu-latest (push) Successful in 5m0s
unittests / Test Python 3.13 macos-latest (push) Has been cancelled
unittests / Test Python 3.11 windows-latest (push) Has been cancelled
unittests / Test Python 3.13 windows-latest (push) Has been cancelled
add schedule I, sonic 1/frontiers/heroes, spirit island
2026-04-02 23:46:36 -07:00

1542 lines
66 KiB
Python

import random
from worlds.Files import APTokenTypes
from . import constants
from . import util
from .randomizePokemonBaseValues import BaseValuesRandomizer
from . import randomMovesetGenerator
from . import writeDisplayData
from .levelFunctions import levelExpCalculator
NOP = bytes([0x00,0x00,0x00,0x00])
class Randomizer():
def __init__(self, version="US_1.0", bst_factor=1, glc_trainer_factor=1, pokecup_trainer_factor=1, primecup_trainer_factor=1, petitcup_trainer_factor=1,
pikacup_trainer_factor=1, glc_rental_factor=1, pokecup_rental_factor=1, primecup_rental_factor=1, petitcup_rental_factor=1, pikacup_rental_factor=1,
rental_list_shuffle_factor=1, rls_glc_factor=1, rls_poke_factor=1, rls_prime_factor=1, rls_petit_factor=1, rls_pika_factor=1):
self.version = version
self.bst_factor = bst_factor
self.glc_trainer_factor = glc_trainer_factor
self.pokecup_trainer_factor = pokecup_trainer_factor
self.primecup_trainer_factor = primecup_trainer_factor
self.petitcup_trainer_factor = petitcup_trainer_factor
self.pikacup_trainer_factor = pikacup_trainer_factor
self.glc_rental_factor = glc_rental_factor
self.pokecup_rental_factor = pokecup_rental_factor
self.primecup_rental_factor = primecup_rental_factor
self.petitcup_rental_factor = petitcup_rental_factor
self.rental_list_shuffle_factor = rental_list_shuffle_factor
self.pikacup_rental_factor = pikacup_rental_factor
self.rls_glc_factor = rls_glc_factor
self.rls_poke_factor = rls_poke_factor
self.rls_prime_factor = rls_prime_factor
self.rls_petit_factor = rls_petit_factor
self.rls_pika_factor = rls_pika_factor
self.evs = []
self.ivs = []
for _ in range(0, 149):
self.evs.append(util.Util.random_int_set(0, 65535, 5))
self.ivs.append(util.Util.random_string_hex(4))
self.new_display_stats = []
self.bst_list = []
if(bst_factor == 1):
for i in range(149):
stats = constants.kanto_dex_names[i]['bst']
self.bst_list.append(stats)
self.new_display_stats.append(stats)
def disable_checksum(self, patch) -> None:
offset = constants.rom_offsets[self.version]["CheckSum1"]
patch.write_token(APTokenTypes.WRITE, offset, NOP)
offset = constants.rom_offsets[self.version]["CheckSum2"]
patch.write_token(APTokenTypes.WRITE, offset, NOP)
def randomize_base_stats(self, patch) -> None:
offset = constants.rom_offsets[self.version]["BaseStats"]
for i in range(149):
stats = constants.kanto_dex_names[i]['bst']
if self.bst_factor > 1:
randomized_base_stats = BaseValuesRandomizer.randomize_stats(stats, self.bst_factor)
# Convert to list of integers for BST processing
self.bst_list.append(list(randomized_base_stats))
# Store modified stats for display
self.new_display_stats.append(randomized_base_stats)
# Write the new randomized stats back
patch.write_token(APTokenTypes.WRITE, offset, bytes(randomized_base_stats))
else:
# store vanilla stats
self.bst_list.append(stats)
self.new_display_stats.append(stats)
# Move to the next Pokémon entry (skip 18 additional bytes)
offset += 23
def randomize_glc_trainer_pokemon_round1(self, patch) -> None:
offset = constants.rom_offsets[self.version]["GymCastle_Round1"]
for q in range(10):
team_count = 4 if q < 9 else 7
for _ in range(team_count):
new_team = random.sample(range(149), 6)
for s in range(6):
pokedex_num = new_team[s]
patch.write_token(APTokenTypes.WRITE, offset, bytes([pokedex_num + 1])) # Write Pokémon index
offset += 1
offset += 5 # Seek forward by 5 bytes
new_type = bytes.fromhex(constants.kanto_dex_names[pokedex_num]["type"])
patch.write_token(APTokenTypes.WRITE, offset, bytes(new_type)) # Write Pokémon type
offset += len(new_type)
offset += 1 # Seek forward by 1 byte
# Random moveset
bst = self.bst_list[pokedex_num]
factor = self.glc_trainer_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst, factor, new_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
offset += 4 # Seek forward by 4 bytes
exp = int.to_bytes(int(constants.kanto_dex_names[pokedex_num]["exp"]), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, exp)
offset += 3
for t in range(5):
ev = int.to_bytes(self.evs[pokedex_num][t], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, ev)
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[pokedex_num])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
offset += 6 # Seek forward by 6 bytes
new_stats = self.new_display_stats[pokedex_num]
evs = self.evs[pokedex_num]
ivs = self.ivs[pokedex_num]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(new_stats, evs, ivs, 50)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = constants.kanto_dex_names[pokedex_num]["name"].encode()
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name))
offset += len(pokemon_name)
# Check if a Nidoran is being written in to add their gender symbol
if pokedex_num == 28:
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("BE")) # Female symbol
offset += 1
pokemon_name += b" "
elif pokedex_num == 31:
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("A9")) # Male symbol
offset += 1
pokemon_name += b" "
# Fill in blank spaces to make the name 11 bytes long
if len(pokemon_name) < 11:
blanks = 11 - len(pokemon_name)
patch.write_token(APTokenTypes.WRITE, offset, b"\x00" * blanks)
offset += blanks
offset += 25 # Seek forward by 25 bytes
offset += 56 # Seek forward by 56 bytes
offset += 16 # Seek forward by 16 bytes
def randomize_pokecup_trainer_pokemon_round1(self, patch) -> None:
offset = constants.rom_offsets[self.version]["PokeCup_Round1"]
for q in range(4):
team_count = 8
for _ in range(team_count):
new_team = random.sample(range(149), 6)
for s in range(6):
pokedex_num = new_team[s]
patch.write_token(APTokenTypes.WRITE, offset, bytes([pokedex_num + 1])) # Write Pokémon index
offset += 1
offset += 5 # Seek forward by 5 bytes
new_type = bytes.fromhex(constants.kanto_dex_names[pokedex_num]["type"])
patch.write_token(APTokenTypes.WRITE, offset, bytes(new_type)) # Write Pokémon type
offset += len(new_type)
offset += 1 # Seek forward by 1 byte
# Random moveset
bst = self.bst_list[pokedex_num]
factor = self.pokecup_trainer_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst, factor, new_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
offset += 4 # Seek forward by 4 bytes
if(q == 0): #poke cup pokeball round 1, level 50
exp = int.to_bytes(int(constants.kanto_dex_names[pokedex_num]["exp"]), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, exp)
offset += 3
ivs_bytes = bytes.fromhex(self.ivs[pokedex_num])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
offset += 6 # Seek forward by 6 bytes
new_stats = self.new_display_stats[pokedex_num]
evs = self.evs[pokedex_num]
ivs = self.ivs[pokedex_num]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(new_stats, evs, ivs, 50)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
elif(q == 1): #poke cup great ball round 1, level 51
exp = int.to_bytes(int(levelExpCalculator.getExpValue(51, constants.kanto_dex_names[pokedex_num]["gr"])), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, exp)
offset += 3
ivs_bytes = bytes.fromhex(self.ivs[pokedex_num])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
offset += 6 # Seek forward by 6 bytes
new_stats = self.new_display_stats[pokedex_num]
evs = self.evs[pokedex_num]
ivs = self.ivs[pokedex_num]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(new_stats, evs, ivs, 51)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
elif(q == 2): #poke cup ultra ball round 1, mixed levels
exp = int.to_bytes(int(levelExpCalculator.getExpValue(constants.pokecupr1_ultra_levels[_][s], constants.kanto_dex_names[pokedex_num]["gr"])), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, exp)
offset += 3
ivs_bytes = bytes.fromhex(self.ivs[pokedex_num])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
offset += 6 # Seek forward by 6 bytes
new_stats = self.new_display_stats[pokedex_num]
evs = self.evs[pokedex_num]
ivs = self.ivs[pokedex_num]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(new_stats, evs, ivs, constants.pokecupr1_ultra_levels[_][s])
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
elif(q == 3): #poke cup master ball round 1, mixed levels
exp = int.to_bytes(int(levelExpCalculator.getExpValue(constants.pokecupr1_master_levels[_][s], constants.kanto_dex_names[pokedex_num]["gr"])), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, exp)
offset += 3
ivs_bytes = bytes.fromhex(self.ivs[pokedex_num])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
offset += 6 # Seek forward by 6 bytes
new_stats = self.new_display_stats[pokedex_num]
evs = self.evs[pokedex_num]
ivs = self.ivs[pokedex_num]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(new_stats, evs, ivs, constants.pokecupr1_master_levels[_][s])
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
for t in range(5):
ev = int.to_bytes(self.evs[pokedex_num][t], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, ev)
offset += 2
pokemon_name = constants.kanto_dex_names[pokedex_num]["name"].encode()
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name))
offset += len(pokemon_name)
# Check if a Nidoran is being written in to add their gender symbol
if pokedex_num == 28:
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("BE")) # Female symbol
offset += 1
pokemon_name += b" "
elif pokedex_num == 31:
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("A9")) # Male symbol
offset += 1
pokemon_name += b" "
# Fill in blank spaces to make the name 11 bytes long
if len(pokemon_name) < 11:
blanks = 11 - len(pokemon_name)
patch.write_token(APTokenTypes.WRITE, offset, b"\x00" * blanks)
offset += blanks
offset += 25 # Seek forward by 25 bytes
offset += 56 # Seek forward by 56 bytes
offset += 16 # Seek forward by 16 bytes
def randomize_primecup_trainer_pokemon_round1(self, patch) -> None:
offset = constants.rom_offsets[self.version]["PrimeCup_Round1"]
for q in range(4):
team_count = 8
for _ in range(team_count):
new_team = random.sample(range(149), 6)
for s in range(6):
pokedex_num = new_team[s]
patch.write_token(APTokenTypes.WRITE, offset, bytes([pokedex_num + 1])) # Write Pokémon index
offset += 1
offset += 5 # Seek forward by 5 bytes
new_type = bytes.fromhex(constants.kanto_dex_names[pokedex_num]["type"])
patch.write_token(APTokenTypes.WRITE, offset, bytes(new_type)) # Write Pokémon type
offset += len(new_type)
offset += 1 # Seek forward by 1 byte
# Random moveset
bst = self.bst_list[pokedex_num]
factor = self.primecup_trainer_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst, factor, new_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
offset += 4 # Seek forward by 4 bytes
exp = int.to_bytes(int(constants.prime_cup_list[pokedex_num]["exp"]), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, exp)
offset += 3
for t in range(5):
ev = int.to_bytes(self.evs[pokedex_num][t], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, ev)
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[pokedex_num])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
offset += 6 # Seek forward by 6 bytes
new_stats = self.new_display_stats[pokedex_num]
evs = self.evs[pokedex_num]
ivs = self.ivs[pokedex_num]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(new_stats, evs, ivs, 100)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = constants.kanto_dex_names[pokedex_num]["name"].encode()
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name))
offset += len(pokemon_name)
# Check if a Nidoran is being written in to add their gender symbol
if pokedex_num == 28:
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("BE")) # Female symbol
offset += 1
pokemon_name += b" "
elif pokedex_num == 31:
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("A9")) # Male symbol
offset += 1
pokemon_name += b" "
# Fill in blank spaces to make the name 11 bytes long
if len(pokemon_name) < 11:
blanks = 11 - len(pokemon_name)
patch.write_token(APTokenTypes.WRITE, offset, b"\x00" * blanks)
offset += blanks
offset += 25 # Seek forward by 25 bytes
offset += 56 # Seek forward by 56 bytes
offset += 16 # Seek forward by 16 bytes
def randomize_petitcup_trainer_pokemon_round1(self, patch) -> None:
offset = constants.rom_offsets[self.version]["PetitCup_Round1"]
team_count = 8
for _ in range(team_count):
new_team = random.sample(constants.petit_cup_list, 6)
for s in range(6):
#There is probably a much better way to do this, but oh well
#We break down each required aspect from a pokemon, save them to a variable, and then
#we do the bytes() command using the saved variable instead of the list because the list
#breaks for some reason idrk why
pokemonInfo = new_team[s]
currentPokeDexNum = pokemonInfo["DexNum"]
currentPokeType = pokemonInfo["type"]
currentPokeName = pokemonInfo["name"]
patch.write_token(APTokenTypes.WRITE, offset, int.to_bytes(currentPokeDexNum)) # Write Pokémon index
offset += 1
offset += 5 # Seek forward by 5 bytes
new_type = bytes.fromhex(currentPokeType)
patch.write_token(APTokenTypes.WRITE, offset, bytes(new_type)) # Write Pokémon type
offset += len(new_type)
offset += 1 # Seek forward by 1 byte
# Random moveset
bst = self.bst_list[currentPokeDexNum - 1]
factor = self.petitcup_trainer_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst, factor, new_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
offset += 4 # Seek forward by 4 bytes
exp = int.to_bytes(int(levelExpCalculator.getExpValue(constants.petitcupr1_levels[_][s], constants.kanto_dex_names[currentPokeDexNum-1]["gr"])), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, exp)
offset += 3
for t in range(5):
ev = int.to_bytes(self.evs[currentPokeDexNum-1][t], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, ev)
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[currentPokeDexNum-1])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
offset += 6 # Seek forward by 6 bytes
new_stats = self.new_display_stats[currentPokeDexNum - 1]
evs = self.evs[currentPokeDexNum-1]
ivs = self.ivs[currentPokeDexNum-1]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(new_stats, evs, ivs, constants.petitcupr1_levels[_][s])
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = currentPokeName.encode()
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name))
offset += len(pokemon_name)
# Check if a Nidoran is being written in to add their gender symbol
if (currentPokeDexNum == 29):
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("BE")) # Female symbol
offset += 1
pokemon_name += b" "
elif (currentPokeDexNum == 32):
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("A9")) # Male symbol
offset += 1
pokemon_name += b" "
# Fill in blank spaces to make the name 11 bytes long
if len(pokemon_name) < 11:
blanks = 11 - len(pokemon_name)
patch.write_token(APTokenTypes.WRITE, offset, b"\x00" * blanks)
offset += blanks
offset += 25 # Seek forward by 25 bytes
offset += 56 # Seek forward by 56 bytes
offset += 16 # Seek forward by 16 bytes
def randomize_pikacup_trainer_pokemon_round1(self, patch) -> None:
offset = constants.rom_offsets[self.version]["PikaCup_Round1"]
team_count = 8
for _ in range(team_count):
new_team = random.sample(constants.pika_cup_list, 6)
for s in range(6):
#There is probably a much better way to do this, but oh well
#We break down each required aspect from a pokemon, save them to a variable, and then
#we do the bytes() command using the saved variable instead of the list because the list
#breaks for some reason idrk why
pokemonInfo = new_team[s]
currentPokeDexNum = pokemonInfo["DexNum"]
currentPokeType = pokemonInfo["type"]
currentPokeName = pokemonInfo["name"]
patch.write_token(APTokenTypes.WRITE, offset, int.to_bytes(currentPokeDexNum)) # Write Pokémon index
offset += 1
offset += 5 # Seek forward by 5 bytes
new_type = bytes.fromhex(currentPokeType)
patch.write_token(APTokenTypes.WRITE, offset, bytes(new_type)) # Write Pokémon type
offset += len(new_type)
offset += 1 # Seek forward by 1 byte
# Random moveset
bst = self.bst_list[currentPokeDexNum - 1]
factor = self.pikacup_trainer_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst, factor, new_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
offset += 4 # Seek forward by 4 bytes
exp = int.to_bytes(int(levelExpCalculator.getExpValue(constants.pikacupr1_levels[_][s], constants.kanto_dex_names[currentPokeDexNum-1]["gr"])), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, exp)
offset += 3
for t in range(5):
ev = int.to_bytes(self.evs[currentPokeDexNum-1][t], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, ev)
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[currentPokeDexNum-1])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
offset += 6 # Seek forward by 6 bytes
new_stats = self.new_display_stats[currentPokeDexNum - 1]
evs = self.evs[currentPokeDexNum-1]
ivs = self.ivs[currentPokeDexNum-1]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(new_stats, evs, ivs, constants.pikacupr1_levels[_][s])
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = currentPokeName.encode()
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name))
offset += len(pokemon_name)
if (currentPokeDexNum == 29):
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("BE")) # Female symbol
offset += 1
pokemon_name += b" "
elif (currentPokeDexNum == 32):
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("A9")) # Male symbol
offset += 1
pokemon_name += b" "
# Fill in blank spaces to make the name 11 bytes long
if len(pokemon_name) < 11:
blanks = 11 - len(pokemon_name)
patch.write_token(APTokenTypes.WRITE, offset, b"\x00" * blanks)
offset += blanks
offset += 25 # Seek forward by 25 bytes
offset += 56 # Seek forward by 56 bytes
offset += 16 # Seek forward by 16 bytes
def randomize_glc_rentals_round1(self, patch) -> None:
#randomize rentals for GLC
offset = constants.rom_offsets[self.version]["Rentals_GymCastle_Round1"]
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
for j in range(149):
patch.write_token(APTokenTypes.WRITE, offset, bytes([j + 1])) # Write Dex number
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0008")) # Current HP
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("32")) # Level
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00")) # Status
offset += 1
pkm_type = bytes.fromhex(constants.kanto_dex_names[j]["type"])
patch.write_token(APTokenTypes.WRITE, offset, bytes(pkm_type)) # Type(s)
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
# Random moveset
bst_list = self.bst_list[j]
factor = self.glc_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("1110")) # Trainer ID
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.kanto_dex_names[j]["exp"]), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(exp_bytes)) # Experience
offset += 3
for k in range(5):
ev = int.to_bytes(self.evs[j][k], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[j])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("32")) # Level again
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[j]
evs = self.evs[j]
ivs = self.ivs[j]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 50)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = constants.kanto_dex_names[j]["name"].encode().ljust(11, b'\x00')
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name)) # Name
offset += 11
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("52414E444F000000")) # Trainer name (RANDO)
offset += 8
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000000000000000000000000000000000")) # Padding
offset += 17
def randomize_pokecup_rentals(self, patch) -> None:
#randomize pokemon in Poke Cup rental list
offset = constants.rom_offsets[self.version]["Rentals_PokeCup"]
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
for j in range(149):
patch.write_token(APTokenTypes.WRITE, offset, bytes([j + 1])) # Write Dex number
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0008")) # Current HP
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("32")) # Level
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00")) # Status
offset += 1
pkm_type = bytes.fromhex(constants.kanto_dex_names[j]["type"])
patch.write_token(APTokenTypes.WRITE, offset, bytes(pkm_type)) # Type(s)
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
# Random moveset
bst_list = constants.poke_cup_list[j]["bst"]
factor = self.pokecup_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("1110")) # Trainer ID
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.poke_cup_list[j]["exp"]), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(exp_bytes)) # Experience
offset += 3
for k in range(5):
ev = int.to_bytes(self.evs[j][k], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[j])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("32")) # Level again
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[j]
evs = self.evs[j]
ivs = self.ivs[j]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 50)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = constants.kanto_dex_names[j]["name"].encode().ljust(11, b'\x00')
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name)) # Name
offset += 11
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("52414E444F000000")) # Trainer name (RANDO)
offset += 8
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000000000000000000000000000000000")) # Padding
offset += 17
def randomize_primecup_rentals_round1(self, patch) -> None:
#randomize pokemon in Prime Cup rental list
offset = constants.rom_offsets[self.version]["Rentals_PrimeCup_Round1"]
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
for j in range(149):
patch.write_token(APTokenTypes.WRITE, offset, bytes([j + 1])) # Write Dex number
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0008")) # Current HP
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("64")) # Level
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00")) # Status
offset += 1
pkm_type = bytes.fromhex(constants.prime_cup_list[j]["type"])
patch.write_token(APTokenTypes.WRITE, offset, bytes(pkm_type)) # Type(s)
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
# Random moveset
bst_list = constants.prime_cup_list[j]["bst"]
factor = self.primecup_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("1110")) # Trainer ID
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.prime_cup_list[j]["exp"]), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(exp_bytes)) # Experience
offset += 3
for k in range(5):
ev = int.to_bytes(self.evs[j][k], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[j])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("64")) # Level again
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[j]
evs = self.evs[j]
ivs = self.ivs[j]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 100)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = constants.prime_cup_list[j]["name"].encode().ljust(11, b'\x00')
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name)) # Name
offset += 11
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("52414E444F000000")) # Trainer name (RANDO)
offset += 8
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000000000000000000000000000000000")) # Padding
offset += 17
def randomize_petitcup_rentals(self, patch) -> None:
#randomize pokemon in Petit Cup rental list
offset = constants.rom_offsets[self.version]["Rentals_PetitCup"]
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000002D"))
offset += 4
for j in range(45):
patch.write_token(APTokenTypes.WRITE, offset, bytes([constants.petit_cup_list[j]["DexNum"]])) # Write Dex number
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0008")) # Current HP
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("19")) # Level
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00")) # Status
offset += 1
pkm_type = bytes.fromhex(constants.petit_cup_list[j]["type"])
patch.write_token(APTokenTypes.WRITE, offset, bytes(pkm_type)) # Type(s)
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
# Random moveset
bst_list = constants.petit_cup_list[j]["bst"]
factor = self.petitcup_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("1110")) # Trainer ID
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.petit_cup_list[j]["exp"]), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(exp_bytes)) # Experience
offset += 3
currentPokeDexNum = constants.petit_cup_list[j]["DexNum"]
for k in range(5):
ev = int.to_bytes(self.evs[currentPokeDexNum-1][k], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[currentPokeDexNum-1])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("19")) # Level again
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[currentPokeDexNum-1]
evs = self.evs[currentPokeDexNum-1]
ivs = self.ivs[currentPokeDexNum-1]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 25)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = constants.petit_cup_list[j]["name"].encode().ljust(11, b'\x00')
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name)) # Name
offset += 11
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("52414E444F000000")) # Trainer name (RANDO)
offset += 8
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000000000000000000000000000000000")) # Padding
offset += 17
def randomize_pikacup_rentals(self, patch) -> None:
#randomize pokemon in Pika Cup rental list
offset = constants.rom_offsets[self.version]["Rentals_PikaCup"]
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000005B"))
offset += 4
for j in range(91):
patch.write_token(APTokenTypes.WRITE, offset, bytes([constants.pika_cup_list[j]["DexNum"]])) # Write Dex number
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0008")) # Current HP
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0F")) # Level
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00")) # Status
offset += 1
pkm_type = bytes.fromhex(constants.pika_cup_list[j]["type"])
patch.write_token(APTokenTypes.WRITE, offset, bytes(pkm_type)) # Type(s)
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
# Random moveset
bst_list = constants.pika_cup_list[j]["bst"]
factor = self.pikacup_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
patch.write_token(APTokenTypes.WRITE, offset, bytes([attack]))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("1110")) # Trainer ID
offset += 2
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.pika_cup_list[j]["exp"]), 3, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(exp_bytes)) # Experience
offset += 3
currentPokeDexNum = constants.pika_cup_list[j]["DexNum"]
for k in range(5):
ev = int.to_bytes(self.evs[currentPokeDexNum-1][k], 2, "big")
patch.write_token(APTokenTypes.WRITE, offset, bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[currentPokeDexNum-1])
patch.write_token(APTokenTypes.WRITE, offset, ivs_bytes)
offset += len(ivs_bytes)
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0F")) # Level again
offset += 1
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[currentPokeDexNum-1]
evs = self.evs[currentPokeDexNum-1]
ivs = self.ivs[currentPokeDexNum-1]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 15)
patch.write_token(APTokenTypes.WRITE, offset, bytes(disp))
offset += len(disp)
pokemon_name = constants.pika_cup_list[j]["name"].encode().ljust(11, b'\x00')
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_name)) # Name
offset += 11
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("52414E444F000000")) # Trainer name (RANDO)
offset += 8
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000000000000000000000000000000000")) # Padding
offset += 17
def shuffle_rentals(self, patch) -> None:
#Shuffle time
self.shuffle_glc(patch)
self.shuffle_poke(patch)
self.shuffle_prime(patch)
self.shuffle_petit(patch)
self.shuffle_pika(patch)
return patch
def shuffle_glc(self, patch) -> None:
#Gym Leader Castle
#Shuffle GLC Rental Table
offset = constants.rom_offsets[self.version]["Rentals_GymCastle_Round1"]
pokemon_holder = []
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
for j in range(149):
current_pokemon_bytearray = bytearray()
current_pokemon_bytearray.extend(bytes([j + 1]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("0008"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("32"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
pkm_type = bytes.fromhex(constants.kanto_dex_names[j]["type"])
current_pokemon_bytearray.extend(bytes(pkm_type))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
if self.glc_rental_factor > 1:
bst_list = self.bst_list[j]
factor = self.glc_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
else:
for attack in constants.GLC_list[j]["Moveset"]:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("1110"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.kanto_dex_names[j]["exp"]), 3, "big")
current_pokemon_bytearray.extend(bytes(exp_bytes))
offset += 3
for k in range(5):
ev = int.to_bytes(self.evs[j][k], 2, "big")
current_pokemon_bytearray.extend(bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[j])
current_pokemon_bytearray.extend(ivs_bytes)
offset += len(ivs_bytes)
current_pokemon_bytearray.extend(bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
current_pokemon_bytearray.extend(bytes.fromhex("32"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[j]
evs = self.evs[j]
ivs = self.ivs[j]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 50)
current_pokemon_bytearray.extend(bytes(disp))
offset += len(disp)
pokemon_name = constants.kanto_dex_names[j]["name"].encode().ljust(11, b'\x00')
current_pokemon_bytearray.extend(bytes(pokemon_name))
offset += 11
current_pokemon_bytearray.extend(bytes.fromhex("52414E444F000000"))
offset += 8
current_pokemon_bytearray.extend(bytes.fromhex("0000000000000000000000000000000000"))
offset += 17
pokemon_holder.append(bytearray(current_pokemon_bytearray))
#Shuffles order of rental pokemon
random.shuffle(pokemon_holder)
offset = constants.rom_offsets[self.version]["Rentals_GymCastle_Round1"]
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
while len(pokemon_holder) > 0:
#Get pokemon bytes from list
pokemon_to_add = pokemon_holder.pop(0)
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_to_add))
offset+= len(bytes(pokemon_to_add))
print("GLC rentals shuffled successfully")
def shuffle_poke(self, patch) -> None:
#Poke Cup
#Shuffle Poke Cup Rental Table
offset = constants.rom_offsets[self.version]["Rentals_PokeCup"]
pokemon_holder = []
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
for j in range(149):
current_pokemon_bytearray = bytearray()
current_pokemon_bytearray.extend(bytes([j + 1]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("0008"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("32"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
pkm_type = bytes.fromhex(constants.kanto_dex_names[j]["type"])
current_pokemon_bytearray.extend(bytes(pkm_type))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
if self.pokecup_rental_factor > 1:
bst_list = self.bst_list[j]
factor = self.pokecup_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
else:
for attack in constants.poke_cup_list[j]["Moveset"]:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("1110"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.kanto_dex_names[j]["exp"]), 3, "big")
current_pokemon_bytearray.extend(bytes(exp_bytes))
offset += 3
for k in range(5):
ev = int.to_bytes(self.evs[j][k], 2, "big")
current_pokemon_bytearray.extend(bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[j])
current_pokemon_bytearray.extend(ivs_bytes)
offset += len(ivs_bytes)
current_pokemon_bytearray.extend(bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
current_pokemon_bytearray.extend(bytes.fromhex("32"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[j]
evs = self.evs[j]
ivs = self.ivs[j]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 50)
current_pokemon_bytearray.extend(bytes(disp))
offset += len(disp)
pokemon_name = constants.kanto_dex_names[j]["name"].encode().ljust(11, b'\x00')
current_pokemon_bytearray.extend(bytes(pokemon_name))
offset += 11
current_pokemon_bytearray.extend(bytes.fromhex("52414E444F000000"))
offset += 8
current_pokemon_bytearray.extend(bytes.fromhex("0000000000000000000000000000000000"))
offset += 17
pokemon_holder.append(bytearray(current_pokemon_bytearray))
#Shuffles order of rental pokemon
random.shuffle(pokemon_holder)
offset = constants.rom_offsets[self.version]["Rentals_PokeCup"]
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
while len(pokemon_holder) > 0:
#Get pokemon bytes from list
pokemon_to_add = pokemon_holder.pop(0)
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_to_add))
offset+= len(bytes(pokemon_to_add))
print("Poke Cup rentals shuffled successfully")
def shuffle_prime(self, patch) -> None:
#Prime Cup
#Shuffle Prime Cup Rental Table
offset = constants.rom_offsets[self.version]["Rentals_PrimeCup_Round1"]
pokemon_holder = []
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
for j in range(149):
current_pokemon_bytearray = bytearray()
current_pokemon_bytearray.extend(bytes([j + 1]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("0008"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("64"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
pkm_type = bytes.fromhex(constants.kanto_dex_names[j]["type"])
current_pokemon_bytearray.extend(bytes(pkm_type))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
if self.primecup_rental_factor > 1:
bst_list = self.bst_list[j]
factor = self.primecup_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
else:
for attack in constants.prime_cup_list[j]["Moveset"]:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("1110"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.prime_cup_list[j]["exp"]), 3, "big")
current_pokemon_bytearray.extend(bytes(exp_bytes))
offset += 3
for k in range(5):
ev = int.to_bytes(self.evs[j][k], 2, "big")
current_pokemon_bytearray.extend(bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[j])
current_pokemon_bytearray.extend(ivs_bytes)
offset += len(ivs_bytes)
current_pokemon_bytearray.extend(bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
current_pokemon_bytearray.extend(bytes.fromhex("64"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[j]
evs = self.evs[j]
ivs = self.ivs[j]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 100)
current_pokemon_bytearray.extend(bytes(disp))
offset += len(disp)
pokemon_name = constants.kanto_dex_names[j]["name"].encode().ljust(11, b'\x00')
current_pokemon_bytearray.extend(bytes(pokemon_name))
offset += 11
current_pokemon_bytearray.extend(bytes.fromhex("52414E444F000000"))
offset += 8
current_pokemon_bytearray.extend(bytes.fromhex("0000000000000000000000000000000000"))
offset += 17
pokemon_holder.append(bytearray(current_pokemon_bytearray))
#Shuffles order of rental pokemon
random.shuffle(pokemon_holder)
offset = constants.rom_offsets[self.version]["Rentals_PrimeCup_Round1"]
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("00000095"))
offset += 4
while len(pokemon_holder) > 0:
#Get pokemon bytes from list
pokemon_to_add = pokemon_holder.pop(0)
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_to_add))
offset+= len(bytes(pokemon_to_add))
print("Prime Cup rentals shuffled successfully")
def shuffle_petit(self, patch) -> None:
#Petit Cup
#Shuffle Petit Cup Rental Table
offset = constants.rom_offsets[self.version]["Rentals_PetitCup"]
pokemon_holder = []
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000002D"))
offset += 4
for j in range(45):
current_pokemon_bytearray = bytearray()
current_pokemon_bytearray.extend(bytes([constants.petit_cup_list[j]["DexNum"]]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("0008"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("19"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
pkm_type = bytes.fromhex(constants.petit_cup_list[j]["type"])
current_pokemon_bytearray.extend(bytes(pkm_type))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
#If random moves are on
if self.petitcup_rental_factor > 1:
bst_list = constants.petit_cup_list[j]["bst"]
factor = self.petitcup_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
else:
for attack in constants.petit_cup_list[j]["Moveset"]:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("1110"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.petit_cup_list[j]["exp"]), 3, "big")
current_pokemon_bytearray.extend(bytes(exp_bytes))
offset += 3
currentPokeDexNum = constants.petit_cup_list[j]["DexNum"]
for k in range(5):
ev = int.to_bytes(self.evs[currentPokeDexNum-1][k], 2, "big")
current_pokemon_bytearray.extend(bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[currentPokeDexNum-1])
current_pokemon_bytearray.extend(ivs_bytes)
offset += len(ivs_bytes)
current_pokemon_bytearray.extend(bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
current_pokemon_bytearray.extend(bytes.fromhex("19"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[currentPokeDexNum-1]
evs = self.evs[currentPokeDexNum-1]
ivs = self.ivs[currentPokeDexNum-1]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 25)
current_pokemon_bytearray.extend(bytes(disp))
offset += len(disp)
pokemon_name = constants.petit_cup_list[j]["name"].encode().ljust(11, b'\x00')
current_pokemon_bytearray.extend(bytes(pokemon_name))
offset += 11
current_pokemon_bytearray.extend(bytes.fromhex("52414E444F000000"))
offset += 8
current_pokemon_bytearray.extend(bytes.fromhex("0000000000000000000000000000000000"))
offset += 17
pokemon_holder.append(bytearray(current_pokemon_bytearray))
#Shuffles order of rental pokemon
random.shuffle(pokemon_holder)
offset = constants.rom_offsets[self.version]["Rentals_PetitCup"]
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000002D"))
offset += 4
while len(pokemon_holder) > 0:
#Get pokemon bytes from list
pokemon_to_add = pokemon_holder.pop(0)
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_to_add))
offset+= len(bytes(pokemon_to_add))
print("Petit Cup rentals shuffled successfully")
def shuffle_pika(self, patch) -> None:
#Pika Cup
#Shuffle Pika Cup Rental Table
offset = constants.rom_offsets[self.version]["Rentals_PikaCup"]
pokemon_holder = []
# Write expected number of returned Pokémon
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000005B"))
offset += 4
for j in range(91):
current_pokemon_bytearray = bytearray()
current_pokemon_bytearray.extend(bytes([constants.pika_cup_list[j]["DexNum"]]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("0008"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("0F"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
pkm_type = bytes.fromhex(constants.pika_cup_list[j]["type"])
current_pokemon_bytearray.extend(bytes(pkm_type))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
if self.pikacup_rental_factor > 1:
bst_list = constants.pika_cup_list[j]["bst"]
factor = self.pikacup_rental_factor
new_attacks = randomMovesetGenerator.MovesetGenerator.get_random_moveset(bst_list, factor, pkm_type)
for attack in new_attacks:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
else:
for attack in constants.pika_cup_list[j]["Moveset"]:
current_pokemon_bytearray.extend(bytes([attack]))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("1110"))
offset += 2
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
exp_bytes = int.to_bytes(int(constants.pika_cup_list[j]["exp"]), 3, "big")
current_pokemon_bytearray.extend(bytes(exp_bytes))
offset += 3
currentPokeDexNum = constants.pika_cup_list[j]["DexNum"]
for k in range(5):
ev = int.to_bytes(self.evs[currentPokeDexNum-1][k], 2, "big")
current_pokemon_bytearray.extend(bytes(ev))
offset += 2
ivs_bytes = bytes.fromhex(self.ivs[currentPokeDexNum-1])
current_pokemon_bytearray.extend(ivs_bytes)
offset += len(ivs_bytes)
current_pokemon_bytearray.extend(bytes.fromhex("00000000"))
offset += 4 # I think setting these to 0 gives you the vanilla PP for moves
current_pokemon_bytearray.extend(bytes.fromhex("0F"))
offset += 1
current_pokemon_bytearray.extend(bytes.fromhex("00"))
offset += 1
stats = self.new_display_stats[currentPokeDexNum-1]
evs = self.evs[currentPokeDexNum-1]
ivs = self.ivs[currentPokeDexNum-1]
disp = writeDisplayData.DisplayDataWriter.write_gym_tower_display(stats, evs, ivs, 15)
current_pokemon_bytearray.extend(bytes(disp))
offset += len(disp)
pokemon_name = constants.pika_cup_list[j]["name"].encode().ljust(11, b'\x00')
current_pokemon_bytearray.extend(bytes(pokemon_name))
offset += 11
current_pokemon_bytearray.extend(bytes.fromhex("52414E444F000000"))
offset += 8
current_pokemon_bytearray.extend(bytes.fromhex("0000000000000000000000000000000000"))
offset += 17
pokemon_holder.append(bytearray(current_pokemon_bytearray))
#Shuffles order of rental pokemon
random.shuffle(pokemon_holder)
offset = constants.rom_offsets[self.version]["Rentals_PikaCup"]
patch.write_token(APTokenTypes.WRITE, offset, bytes.fromhex("0000005B"))
offset += 4
while len(pokemon_holder) > 0:
#Get pokemon bytes from list
pokemon_to_add = pokemon_holder.pop(0)
patch.write_token(APTokenTypes.WRITE, offset, bytes(pokemon_to_add))
offset+= len(bytes(pokemon_to_add))
print("Pika Cup rentals shuffled successfully")