diff --git a/modules/encounter.py b/modules/encounter.py index b9f52626..a0d036f7 100644 --- a/modules/encounter.py +++ b/modules/encounter.py @@ -3,7 +3,7 @@ from modules.files import save_pk3 from modules.gui.desktop_notification import desktop_notification from modules.pokemon_storage import get_pokemon_storage -from modules.pokemon import Pokemon +from modules.pokemon import Pokemon, get_battle_type_flags, BattleTypeFlag from modules.stats import total_stats @@ -29,8 +29,10 @@ def encounter_pokemon(pokemon: Pokemon) -> None: context.message = f"Encountered a {pokemon.species.name} with a shiny value of {pokemon.shiny_value:,}!" + battle_type_flags = get_battle_type_flags() + # TODO temporary until auto-catch is ready - if pokemon.is_shiny or custom_found: + if pokemon.is_shiny or custom_found or BattleTypeFlag.ROAMER in battle_type_flags: if pokemon.is_shiny: if not config.logging.save_pk3.all and config.logging.save_pk3.shiny: save_pk3(pokemon) @@ -50,6 +52,15 @@ def encounter_pokemon(pokemon: Pokemon) -> None: alert_title = "Custom filter triggered!" alert_message = f"Found a {pokemon.species.name} that matched one of your filters. ({custom_filter_result})" + + elif BattleTypeFlag.ROAMER in battle_type_flags: + state_tag = "roamer" + console.print("[bold pink]Roaming Pokemon found!") + context.message = f"Roaming Pokemon found! Bot has been switched to manual mode so you can catch it." + + alert_title = "Roaming Pokemon found!" + alert_message = f"Encountered a roaming {pokemon.species.name}." + else: state_tag = "" alert_title = None diff --git a/modules/gui/create_profile_screen.py b/modules/gui/create_profile_screen.py index e865e66e..371c518b 100644 --- a/modules/gui/create_profile_screen.py +++ b/modules/gui/create_profile_screen.py @@ -190,6 +190,7 @@ def handle_selected_file(selection: list[str]) -> None: "*.ss7", "*.ss8", "*.ss9", + "*.sav", ] ], title="Load Existing Save", diff --git a/modules/items.py b/modules/items.py index 2dcdb418..3224ba0b 100644 --- a/modules/items.py +++ b/modules/items.py @@ -171,8 +171,14 @@ def has_space_for(self, item: Item) -> bool: if len(pocket) < pocket_size: return True + # In FireRed/LeafGreen, you can always put 999 items in a stack. In RSE, this only works for berries. + if context.rom.game_title in ["POKEMON FIRE", "POKEMON LEAF"] or item.pocket == ItemPocket.Berries: + stack_size = 999 + else: + stack_size = 99 + for slot in pocket: - if slot.item == item and slot.quantity < 99: + if slot.item == item and slot.quantity < stack_size: return True return False @@ -243,7 +249,7 @@ def has_space_for(self, item: Item) -> bool: return True for slot in self.items: - if slot.item == item and slot.quantity < 99: + if slot.item == item and slot.quantity < 999: return True return False diff --git a/modules/pokemon.py b/modules/pokemon.py index 2f15e3c0..9f38289a 100644 --- a/modules/pokemon.py +++ b/modules/pokemon.py @@ -1511,7 +1511,42 @@ def get_opponent() -> Pokemon: class BattleTypeFlag(Flag, boundary=KEEP): - BATTLE_TYPE_TRAINER = 1 << 3 + DOUBLE = 1 << 0 + LINK = 1 << 1 + IS_MASTER = 1 << 2 + TRAINER = 1 << 3 + FIRST_BATTLE = 1 << 4 + LINK_IN_BATTLE = 1 << 5 + MULTI = 1 << 6 + SAFARI = 1 << 7 + BATTLE_TOWER = 1 << 8 + WALLY_TUTORIAL = 1 << 9 + ROAMER = 1 << 10 + EREADER_TRAINER = 1 << 11 + KYOGRE_GROUDON = 1 << 12 + LEGENDARY = 1 << 13 + REGI = 1 << 14 + TWO_OPPONENTS = 1 << 15 + DOME = 1 << 16 + PALACE = 1 << 17 + ARENA = 1 << 18 + FACTORY = 1 << 19 + PIKE = 1 << 20 + PYRAMID = 1 << 21 + INGAME_PARTNER = 1 << 22 + TOWER_LINK_MULTI = 1 << 23 + RECORDED = 1 << 24 + RECORDED_LINK = 1 << 25 + TRAINER_HILL = 1 << 26 + SECRET_BASE = 1 << 27 + GROUDON = 1 << 28 + KYOGRE = 1 << 29 + RAYQUAZA = 1 << 30 + RECORDED_IS_MASTER = 1 << 31 + + +def get_battle_type_flags() -> BattleTypeFlag: + return BattleTypeFlag(unpack_uint32(read_symbol("gBattleTypeFlags"))) def opponent_changed() -> bool: @@ -1524,11 +1559,10 @@ def opponent_changed() -> bool: try: global last_opid opponent_pid = read_symbol("gEnemyParty", size=4) - g_battle_type_flags = read_symbol("gBattleTypeFlags", size=4) if ( opponent_pid != last_opid and opponent_pid != b"\x00\x00\x00\x00" - and (BattleTypeFlag.BATTLE_TYPE_TRAINER not in BattleTypeFlag(unpack_uint32(g_battle_type_flags))) + and (BattleTypeFlag.TRAINER not in get_battle_type_flags()) ): last_opid = opponent_pid return True diff --git a/modules/web/http_example.html b/modules/web/http_example.html index 06e4ba89..2db781f9 100644 --- a/modules/web/http_example.html +++ b/modules/web/http_example.html @@ -274,7 +274,7 @@

Event Log

*/ function handlePartyChange(data) { - for (let index = 0; index < 6; index++) { + for (let index = 0; index < data.length; index++) { const listEntry = document.getElementById("party" + index); const nameParts = []; @@ -305,7 +305,14 @@

Event Log

hpBarColoured.style.backgroundColor = "#080"; } hpBar.append(hpBarColoured); - listEntry.append(hpBar); + + const expBar = document.createElement("div"); + expBar.className = "exp-bar"; + const expBarColoured = document.createElement("div"); + expBarColoured.style.width = `${data[index].exp_fraction_to_next_level * 100}%`; + expBar.append(expBarColoured); + + listEntry.append(hpBar, expBar); } } @@ -646,14 +653,25 @@

Current Encounter

margin-bottom: .5rem; } - .party-entry .hp-bar { - height: 3px; + .party-entry .hp-bar, .party-entry .exp-bar { width: 200px; background-color: #ddd; + border: 1px #888 solid; + } + + .party-entry .hp-bar { + height: 5px; + margin-top: 2px; + } + + .party-entry .exp-bar { + height: 3px; + margin-top: 1px; } - .party-entry .hp-bar div { + .party-entry .hp-bar div, .party-entry .exp-bar div { height: 100%; + background-color: #5ae; } .encounter-container { diff --git a/modules/web/pokemon.d.ts b/modules/web/pokemon.d.ts index ba72ffbc..7d1ce40f 100644 --- a/modules/web/pokemon.d.ts +++ b/modules/web/pokemon.d.ts @@ -45,7 +45,7 @@ export type Type = { index: number; // English name of this type. - name: string; + name: TypeName; kind: "???" | "Physical" | "Special"; }