Fix exploration and battle system state management bugs
- Fixed exploration bug: prevent multiple \!explore when encounter is active - Fixed battle bug: prevent starting multiple battles from exploration encounters - Enforced exploration encounter workflow: must choose fight/capture/flee before exploring again - Fixed \!gym challenge to use player's current location instead of requiring location parameter - Added proper state management to prevent race conditions - Improved user experience with clear error messages for active encounters 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3c628c7f51
commit
d05b2ead53
3 changed files with 92 additions and 19 deletions
|
|
@ -52,6 +52,12 @@ class BattleSystem(BaseModule):
|
|||
self.send_message(channel, f"{nickname}: You're already in battle! Use !attack <move> or !flee.")
|
||||
return
|
||||
|
||||
# Check if already in gym battle
|
||||
gym_battle = await self.database.get_active_gym_battle(player["id"])
|
||||
if gym_battle:
|
||||
self.send_message(channel, f"{nickname}: You're already in a gym battle! Finish your gym battle first.")
|
||||
return
|
||||
|
||||
# Get player's active pet
|
||||
pets = await self.database.get_player_pets(player["id"], active_only=True)
|
||||
if not pets:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class Exploration(BaseModule):
|
|||
"""Handles exploration, travel, location, weather, and wild commands"""
|
||||
|
||||
def get_commands(self):
|
||||
return ["explore", "travel", "location", "where", "weather", "wild", "catch", "capture"]
|
||||
return ["explore", "travel", "location", "where", "weather", "wild", "catch", "capture", "flee"]
|
||||
|
||||
async def handle_command(self, channel, nickname, command, args):
|
||||
if command == "explore":
|
||||
|
|
@ -22,6 +22,8 @@ class Exploration(BaseModule):
|
|||
await self.cmd_wild(channel, nickname, args)
|
||||
elif command in ["catch", "capture"]:
|
||||
await self.cmd_catch(channel, nickname)
|
||||
elif command == "flee":
|
||||
await self.cmd_flee_encounter(channel, nickname)
|
||||
|
||||
async def cmd_explore(self, channel, nickname):
|
||||
"""Explore current location"""
|
||||
|
|
@ -29,6 +31,18 @@ class Exploration(BaseModule):
|
|||
if not player:
|
||||
return
|
||||
|
||||
# Check if player has an active encounter that must be resolved first
|
||||
if player["id"] in self.bot.active_encounters:
|
||||
current_encounter = self.bot.active_encounters[player["id"]]
|
||||
self.send_message(channel, f"{nickname}: You already have an active encounter with a wild {current_encounter['species_name']}! You must choose to !battle, !catch, or !flee before exploring again.")
|
||||
return
|
||||
|
||||
# Check if player is in an active battle
|
||||
active_battle = await self.game_engine.battle_engine.get_active_battle(player["id"])
|
||||
if active_battle:
|
||||
self.send_message(channel, f"{nickname}: You're currently in battle! Finish your battle before exploring.")
|
||||
return
|
||||
|
||||
encounter = await self.game_engine.explore_location(player["id"])
|
||||
|
||||
if encounter["type"] == "error":
|
||||
|
|
@ -51,7 +65,7 @@ class Exploration(BaseModule):
|
|||
|
||||
self.send_message(channel,
|
||||
f"🐾 {nickname}: A wild Level {pet['level']} {pet['species_name']} ({type_str}) appeared in {encounter['location']}!")
|
||||
self.send_message(channel, f"Choose your action: !battle to fight it, or !catch to try catching it directly!")
|
||||
self.send_message(channel, f"Choose your action: !battle to fight it, !catch to try catching it directly, or !flee to escape!")
|
||||
|
||||
async def cmd_travel(self, channel, nickname, args):
|
||||
"""Travel to a different location"""
|
||||
|
|
@ -196,6 +210,13 @@ class Exploration(BaseModule):
|
|||
|
||||
# Check if player is in an active battle
|
||||
active_battle = await self.game_engine.battle_engine.get_active_battle(player["id"])
|
||||
gym_battle = await self.database.get_active_gym_battle(player["id"])
|
||||
|
||||
if gym_battle:
|
||||
# Can't catch pets during gym battles
|
||||
self.send_message(channel, f"{nickname}: You can't catch pets during gym battles! Focus on the challenge!")
|
||||
return
|
||||
|
||||
if active_battle:
|
||||
# Catching during battle
|
||||
wild_pet = active_battle["wild_pet"]
|
||||
|
|
@ -297,4 +318,36 @@ class Exploration(BaseModule):
|
|||
"""Display level up information (shared with battle system)"""
|
||||
from .battle_system import BattleSystem
|
||||
battle_system = BattleSystem(self.bot, self.database, self.game_engine)
|
||||
await battle_system.handle_level_up_display(channel, nickname, exp_result)
|
||||
await battle_system.handle_level_up_display(channel, nickname, exp_result)
|
||||
|
||||
async def cmd_flee_encounter(self, channel, nickname):
|
||||
"""Flee from an active encounter without battling"""
|
||||
player = await self.require_player(channel, nickname)
|
||||
if not player:
|
||||
return
|
||||
|
||||
# Check if player has an active encounter to flee from
|
||||
if player["id"] not in self.bot.active_encounters:
|
||||
self.send_message(channel, f"{nickname}: You don't have an active encounter to flee from!")
|
||||
return
|
||||
|
||||
# Check if player is in an active battle - can't flee from exploration if in battle
|
||||
active_battle = await self.game_engine.battle_engine.get_active_battle(player["id"])
|
||||
if active_battle:
|
||||
self.send_message(channel, f"{nickname}: You're in battle! Use the battle system's !flee command to escape combat.")
|
||||
return
|
||||
|
||||
# Check if player is in a gym battle
|
||||
gym_battle = await self.database.get_active_gym_battle(player["id"])
|
||||
if gym_battle:
|
||||
self.send_message(channel, f"{nickname}: You're in a gym battle! Use !forfeit to leave the gym challenge.")
|
||||
return
|
||||
|
||||
# Get encounter details for message
|
||||
encounter = self.bot.active_encounters[player["id"]]
|
||||
|
||||
# Remove the encounter
|
||||
del self.bot.active_encounters[player["id"]]
|
||||
|
||||
self.send_message(channel, f"💨 {nickname}: You fled from the wild {encounter['species_name']}! You can now explore again.")
|
||||
self.send_message(channel, f"💡 Use !explore to search for another encounter!")
|
||||
|
|
@ -66,7 +66,7 @@ class GymBattles(BaseModule):
|
|||
f" Status: {status} | Next difficulty: {difficulty}")
|
||||
|
||||
self.send_message(channel,
|
||||
f"💡 Use '!gym challenge \"<gym name>\"' to battle!")
|
||||
f"💡 Use '!gym challenge' to battle (gym name optional if only one gym in location)!")
|
||||
|
||||
async def cmd_gym_list_all(self, channel, nickname):
|
||||
"""List all gyms across all locations"""
|
||||
|
|
@ -97,10 +97,6 @@ class GymBattles(BaseModule):
|
|||
|
||||
async def cmd_gym_challenge(self, channel, nickname, args):
|
||||
"""Challenge a gym"""
|
||||
if not args:
|
||||
self.send_message(channel, f"{nickname}: Specify a gym to challenge! Example: !gym challenge \"Forest Guardian\"")
|
||||
return
|
||||
|
||||
player = await self.require_player(channel, nickname)
|
||||
if not player:
|
||||
return
|
||||
|
|
@ -111,19 +107,37 @@ class GymBattles(BaseModule):
|
|||
self.send_message(channel, f"{nickname}: You are not in a valid location! Use !travel to go somewhere first.")
|
||||
return
|
||||
|
||||
gym_name = " ".join(self.normalize_input(args)).strip('"')
|
||||
# Get available gyms in current location
|
||||
available_gyms = await self.database.get_gyms_in_location(location["id"])
|
||||
if not available_gyms:
|
||||
self.send_message(channel, f"{nickname}: No gyms found in {location['name']}! Try traveling to a different location.")
|
||||
return
|
||||
|
||||
# Look for gym in player's current location (case-insensitive)
|
||||
gym = await self.database.get_gym_by_name_in_location(gym_name, location["id"])
|
||||
if not gym:
|
||||
# List available gyms in current location for helpful error message
|
||||
available_gyms = await self.database.get_gyms_in_location(location["id"])
|
||||
if available_gyms:
|
||||
gym = None
|
||||
|
||||
if not args:
|
||||
# No gym name provided - auto-challenge if only one gym, otherwise list options
|
||||
if len(available_gyms) == 1:
|
||||
gym = available_gyms[0]
|
||||
self.send_message(channel, f"🏛️ {nickname}: Challenging the {gym['name']} gym in {location['name']}!")
|
||||
else:
|
||||
# Multiple gyms - show list and ask user to specify
|
||||
gym_list = ", ".join([f'"{g["name"]}"' for g in available_gyms])
|
||||
self.send_message(channel, f"{nickname}: Multiple gyms found in {location['name']}! Specify which gym to challenge:")
|
||||
self.send_message(channel, f"Available gyms: {gym_list}")
|
||||
self.send_message(channel, f"💡 Use: !gym challenge \"<gym name>\"")
|
||||
return
|
||||
else:
|
||||
# Gym name provided - find specific gym
|
||||
gym_name = " ".join(self.normalize_input(args)).strip('"')
|
||||
|
||||
# Look for gym in player's current location (case-insensitive)
|
||||
gym = await self.database.get_gym_by_name_in_location(gym_name, location["id"])
|
||||
if not gym:
|
||||
# List available gyms in current location for helpful error message
|
||||
gym_list = ", ".join([f'"{g["name"]}"' for g in available_gyms])
|
||||
self.send_message(channel, f"{nickname}: No gym named '{gym_name}' found in {location['name']}! Available gyms: {gym_list}")
|
||||
else:
|
||||
self.send_message(channel, f"{nickname}: No gyms found in {location['name']}! Try traveling to a different location.")
|
||||
return
|
||||
return
|
||||
|
||||
# Check if player has active pets
|
||||
active_pets = await self.database.get_active_pets(player["id"])
|
||||
|
|
@ -311,7 +325,7 @@ class GymBattles(BaseModule):
|
|||
return
|
||||
|
||||
# This will show a summary - for detailed view they can use !gym list
|
||||
self.send_message(channel, f"🏆 {nickname}: Use !gym list to see all gym progress, or check your profile at: http://petz.rdx4.com/player/{nickname}")
|
||||
self.send_message(channel, f"🏆 {nickname}: Use !gym list to see all gym progress, or check your profile at: http://petz.rdx4.com/player/{nickname}#gym-badges")
|
||||
|
||||
async def cmd_forfeit(self, channel, nickname):
|
||||
"""Forfeit the current gym battle"""
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue