commands.py
unknown
python
8 months ago
19 kB
5
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