commands.py
unknown
python
14 days ago
19 kB
1
Indexable
import discord from discord.ext import commands import asyncio from discord.ext.commands.cooldowns import CooldownMapping, BucketType from discord.ext.commands import Cooldown from datetime import datetime, timedelta import random from .utils.crew_builder import generate_random_pirate class PirateAdventureCommands(commands.Cog): def __init__(self, bot, main_cog): self.bot = bot self.main = main_cog self.recruit_cooldown = CooldownMapping.from_cooldown(1, 1, BucketType.user) self.last_legend_battle = None # Global cooldown self.user_legend_cooldowns = {} # {user_id: datetime} async def spawn_legendary_pirate(self, ctx): from .utils.crew_builder import generate_pirate_by_rarity pirate = generate_pirate_by_rarity("Legendary") # Store current spawn so people canβt claim twice self.current_legendary = { "pirate": pirate, "claimed": False, } # PREVIEW EMBED (initial) preview_embed = discord.Embed( title="π¨ A Legendary Pirate Has Appeared!", description=( f"**Name:** {pirate['name']}\n" f"**Rarity:** {pirate['rarity']}\n" f"**Power:** {pirate['power']}\n\n" "β±οΈ In 60 seconds, this pirate will be up for grabs!" ), color=discord.Color.red() ) preview_embed.set_image(url=pirate["image"]) await ctx.send(embed=preview_embed) await asyncio.sleep(60) # CLAIM EMBED claim_embed = discord.Embed( title="β‘ Legendary Pirate Is Now Claimable!", description=( f"**Name:** {pirate['name']}\n" f"**Rarity:** {pirate['rarity']}\n" f"**Power:** {pirate['power']}\n\n" "Be the first to react with β to recruit this legend!" ), color=discord.Color.gold() ) claim_embed.set_image(url=pirate["image"]) message = await ctx.send(embed=claim_embed) await message.add_reaction("β ") def check(reaction, user): return ( str(reaction.emoji) == "β " and reaction.message.id == message.id and not user.bot ) try: reaction, user = await self.bot.wait_for("reaction_add", timeout=30.0, check=check) except asyncio.TimeoutError: self.current_legendary = None return await ctx.send("β±οΈ No one claimed the legendary pirate in time. They vanished into the mist.") profile = self.main.player_profiles.get(user.id) if not profile: return await ctx.send(f"{user.mention} doesn't have a profile!") # Check if already has legendary if any(p["rarity"] == "Legendary" for p in profile["crew"]): return await ctx.send(f"β {user.mention} already has a Legendary in their crew!") if len(profile["crew"]) >= 6: return await ctx.send(f"β οΈ {user.mention}'s crew is full! Use `;release` before claiming.") profile["crew"].append(pirate) self.current_legendary = None await ctx.send(f"π {user.mention} has recruited **{pirate['name']}**, the Legendary Pirate!") @commands.command(name="start") async def start(self, ctx): user_id = ctx.author.id prefix = ctx.clean_prefix if user_id in self.main.player_profiles: await ctx.send("You have already started your journey") return self.main.player_profiles[user_id] = { "level": 1, "bounty": 100, # starting bounty "crew": [], "experience": 0, "legendary_alerts": False } embed = discord.Embed( title=f"π΄ββ οΈ Welcome aboard, {ctx.author.display_name}!", description="Your pirate journey has begun!", color=discord.Color.gold() ) embed.add_field(name="π° Starting Bounty", value="100 Berries", inline=False) embed.set_footer(text=f"Use `{prefix}profile` to view your stats!") # let the user know await ctx.send(embed=embed) @commands.command(name="profile") async def profile(self, ctx): user_id = ctx.author.id prefix = ctx.clean_prefix if user_id in self.main.player_profiles: profile = self.main.player_profiles[user_id] bounty = profile["bounty"] level = profile["level"] embed = discord.Embed( title=f"π΄ββ οΈ {ctx.author.display_name}'s Pirate Profile", color=discord.Color.blue() ) embed.add_field(name="πΈ Level", value=profile["level"], inline=True) embed.add_field(name="π° Bounty", value=f"{profile['bounty']} Berries", inline=True) embed.add_field(name="π§ Experience", value=profile["experience"], inline=True) embed.add_field(name="π₯ Crew Members", value=len(profile["crew"]), inline=True) alert_status = "On β " if profile.get("legendary_alerts", False) else "Off β" embed.add_field(name="π’ Legendary Alerts", value=alert_status, inline=True) await ctx.send(embed=embed) else: embed = discord.Embed( title="No profile found!", description=f"You don't have a profile yet. Use {prefix}start to begin your pirate journey.", color=discord.Color.red() ) await ctx.send(embed=embed) @commands.command(name="recruit") async def recruit(self, ctx): user_id = ctx.author.id prefix = ctx.clean_prefix # Don't apply cooldown unless they have a profile if user_id not in self.main.player_profiles: return await ctx.send(f"β οΈ You need to start your journey first with `{prefix}start`.") player = self.main.player_profiles[user_id] MAX_CREW_SIZE = 6 if len(player["crew"]) >= MAX_CREW_SIZE: embed = discord.Embed( title="π₯ Crew Full!", description=( f"You already have {MAX_CREW_SIZE} pirates in your crew.\n" f"Use `{prefix}crew` to view them or `{prefix}release` to make space." ), color=discord.Color.red() ) return await ctx.send(embed=embed) # Manually check cooldown bucket = self.recruit_cooldown.get_bucket(ctx.message) retry_after = bucket.update_rate_limit() if retry_after: return await ctx.send(f"β³ You're on cooldown! Try again in `{retry_after:.1f}` seconds.") from .utils.crew_builder import generate_random_pirate pirate = generate_random_pirate() # Create the embed showing the pirate embed = discord.Embed( title="π΄ββ οΈ A pirate appears!", description=( f"**Name:** {pirate['name']}\n" f"**Rarity:** {pirate['rarity']}\n" f"**Power:** {pirate['power']}\n\n" "React β to recruit or β to let them go." ), color=discord.Color.gold() if pirate['rarity'] == "Legendary" else discord.Color.blue() ) embed.set_image(url=pirate["image"]) message = await ctx.send(embed=embed) # React with options await message.add_reaction("β ") await message.add_reaction("β") # Check function to make sure it's the correct user and emoji def check(reaction, user): return ( user == ctx.author and str(reaction.emoji) in ["β ", "β"] and reaction.message.id == message.id ) try: # Wait for a valid reaction reaction, user = await self.bot.wait_for("reaction_add", timeout=20.0, check=check) except asyncio.TimeoutError: await ctx.send("β±οΈ You took too long. The pirate sailed away!") return if str(reaction.emoji) == "β ": self.main.player_profiles[user_id]["crew"].append(pirate) await ctx.send(f"β **{pirate['name']}** has joined your crew!") await message.clear_reactions() else: await ctx.send(f"β You let **{pirate['name']}** go.") await message.clear_reactions() @commands.command(name="crew") async def crew(self, ctx): user_id = ctx.author.id prefix = ctx.clean_prefix if user_id not in self.main.player_profiles: return await ctx.send(f"β οΈ You need to start your journey first with `{prefix}start`.") profile = self.main.player_profiles[user_id] crew = profile["crew"] if not crew: return await ctx.send(f"π₯ Your crew is currently empty! Use `{prefix}recruit` to find new pirates.") total_power = sum(p["power"] for p in crew) embed = discord.Embed( title=f"π₯ {ctx.author.display_name}'s Crew", description=f"Total Power: **{total_power}**", color=discord.Color.dark_teal() ) for idx, pirate in enumerate(crew, start=1): embed.add_field( name=f"#{idx} {pirate['name']}", value=f"π£ Rarity: {pirate['rarity']}\nπͺ Power: {pirate['power']}", inline=False ) await ctx.send(embed=embed) @commands.command(name="release") async def release(self, ctx, slot_number: int): user_id = ctx.author.id prefix = ctx.clean_prefix # Check if user has started if user_id not in self.main.player_profiles: return await ctx.send(f"β οΈ You need to start your journey first with `{prefix}start`.") profile = self.main.player_profiles[user_id] crew = profile["crew"] if not crew: return await ctx.send("π₯ You donβt have any crew members to release.") # Convert to 0-based index index = slot_number - 1 # Check if the number is valid if index < 0 or index >= len(crew): return await ctx.send(f"β Invalid slot number. Use `{prefix}crew` to see valid slots.") # Get and remove the pirate removed_pirate = crew.pop(index) await ctx.send( f"β You released **{removed_pirate['name']}** from your crew.\n" f"They sail the seas once more!" ) @commands.command(name="setlegrole") @commands.has_permissions(administrator=True) async def set_legrole(self, ctx, role: discord.Role): guild_id = ctx.guild.id self.main.legendary_roles[guild_id] = role.id await ctx.send(f"π’ Legendary alert role set to {role.mention}") @commands.command(name="legalert") async def legalert(self, ctx, toggle: str = None): user_id = ctx.author.id prefix = ctx.clean_prefix if user_id not in self.main.player_profiles: return await ctx.send(f"β οΈ You need to start your journey first with `{prefix}start`.") if toggle not in ["on", "off"]: return await ctx.send("βοΈ Usage: `;legalert on` or `;legalert off`") self.main.player_profiles[user_id]["legendary_alerts"] = toggle == "on" status = "enabled" if toggle == "on" else "disabled" await ctx.send(f"π’ Legendary alerts have been **{status}** for you.") @commands.command(name="battlelegend") async def battlelegend(self, ctx, holder: discord.Member): """Challenge a legendary pirate holder to battle.""" attacker_id = ctx.author.id holder_id = holder.id now = datetime.utcnow() if ctx.author == holder: return await ctx.send("β You cannot battle yourself.") # Ensure both users have started their journey if attacker_id not in self.main.player_profiles: return await ctx.send(f"β οΈ {ctx.author.mention}, you need to start your journey first with `{ctx.clean_prefix}start`.") if holder_id not in self.main.player_profiles: return await ctx.send(f"β οΈ {holder.mention} hasn't started their journey yet.") attacker_profile = self.main.player_profiles[attacker_id] holder_profile = self.main.player_profiles[holder_id] # Check if the holder has a legendary pirate holder_legendaries = [p for p in holder_profile["crew"] if p["rarity"] == "Legendary"] if not holder_legendaries: return await ctx.send(f"β {holder.mention} doesn't have a legendary pirate to battle for.") # Cooldown checks if self.last_legend_battle and (now - self.last_legend_battle) < timedelta(hours=1): remaining = timedelta(hours=1) - (now - self.last_legend_battle) minutes, seconds = divmod(int(remaining.total_seconds()), 60) return await ctx.send(f"β³ Another challenge was recently made. Try again in **{minutes}m {seconds}s**.") last_challenge = self.user_legend_cooldowns.get(attacker_id) if last_challenge and (now - last_challenge) < timedelta(hours=12): remaining = timedelta(hours=12) - (now - last_challenge) hours, minutes = divmod(int(remaining.total_seconds()), 3600) minutes //= 60 return await ctx.send(f"π You've already challenged a legend recently. Try again in **{hours}h {minutes}m**.") # Battle logic attacker_power = sum(p["power"] for p in attacker_profile["crew"]) holder_power = sum(p["power"] for p in holder_profile["crew"]) battle_result = random.choices( ["attacker", "holder"], weights=[attacker_power, holder_power], k=1 )[0] if battle_result == "attacker": # Attacker wins: Steal the legendary pirate legendary_pirate = holder_legendaries[0] holder_profile["crew"].remove(legendary_pirate) # Ensure attacker has space in crew if len(attacker_profile["crew"]) >= 6: # Attacker must release a crew member to make space await ctx.send( f"π {ctx.author.mention} has defeated {holder.mention} and is about to claim **{legendary_pirate['name']}**!\n" f"However, your crew is full. You must release one member to make space.\n" f"Use `{ctx.clean_prefix}release <slot_number>` to remove a crew member." ) # Store the legendary temporarily attacker_profile["pending_legendary"] = legendary_pirate else: attacker_profile["crew"].append(legendary_pirate) await ctx.send( f"π {ctx.author.mention} has defeated {holder.mention} and claimed **{legendary_pirate['name']}**!" ) else: # Holder wins: Attacker loses half their crew crew_size = len(attacker_profile["crew"]) if crew_size > 0: to_remove = crew_size // 2 removed_crew = random.sample(attacker_profile["crew"], to_remove) for pirate in removed_crew: attacker_profile["crew"].remove(pirate) await ctx.send( f"π {ctx.author.mention} challenged {holder.mention} but was defeated.\n" f"You lost **{to_remove}** crew members in the battle." ) else: await ctx.send( f"π {ctx.author.mention} challenged {holder.mention} but was defeated.\n" f"You have no crew members left to lose." ) # Update cooldowns self.last_legend_battle = datetime.utcnow() self.user_legend_cooldowns[attacker_id] = datetime.utcnow() # Inside your PirateAdventureCommands class # Individual commands: @commands.command(name="spawncommon") @commands.has_permissions(administrator=True) async def spawn_common(self, ctx): await self.spawn_pirate(ctx, "Common") @commands.command(name="spawnrare") @commands.has_permissions(administrator=True) async def spawn_rare(self, ctx): await self.spawn_pirate(ctx, "Rare") @commands.command(name="spawnepic") @commands.has_permissions(administrator=True) async def spawn_epic(self, ctx): await self.spawn_pirate(ctx, "Epic") @commands.command(name="spawnlegendary") @commands.has_permissions(administrator=True) async def spawn_legendary(self, ctx): await self.spawn_legendary_pirate(ctx) # β Helper function β shared logic async def spawn_pirate(self, ctx, rarity): from .utils.crew_builder import generate_pirate_by_rarity pirate = generate_pirate_by_rarity(rarity) embed = discord.Embed( title=f"π§ͺ A {rarity} Pirate Appears!", description=( f"**Name:** {pirate['name']}\n" f"**Rarity:** {pirate['rarity']}\n" f"**Power:** {pirate['power']}\n\n" "React β to recruit or β to let them go." ), color=discord.Color.gold() if rarity == "Legendary" else discord.Color.blue() ) embed.set_image(url=pirate["image"]) message = await ctx.send(embed=embed) await message.add_reaction("β ") await message.add_reaction("β") def check(reaction, user): return user == ctx.author and str(reaction.emoji) in ["β ", "β"] and reaction.message.id == message.id try: reaction, user = await self.bot.wait_for("reaction_add", timeout=20.0, check=check) except asyncio.TimeoutError: return await ctx.send("β±οΈ Too slow! The pirate disappeared...") if str(reaction.emoji) == "β ": profile = self.main.player_profiles.get(user.id) if not profile: return await ctx.send("β οΈ You don't have a profile.") if len(profile["crew"]) >= 6: return await ctx.send("π₯ Your crew is full!") profile["crew"].append(pirate) await ctx.send(f"β **{pirate['name']}** has joined your crew!") else: await ctx.send(f"β You let **{pirate['name']}** go.") await message.clear_reactions()
Editor is loading...
Leave a Comment