commands.py

 avatar
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