import random import asyncio import discord from redbot.core import commands, bank, Config from redbot.core.utils.chat_formatting import humanize_number from datetime import datetime, timedelta class Heist(commands.Cog): """Heist system for UnbelievaBoat economy""" def __init__(self, bot): self.bot = bot self.config = Config.get_conf(self, identifier=95932766180345, force_registration=True) self.active_heists = {} default_global = { "targets": { "Small Bank": { "min_crew": 2, "max_crew": 4, "min_payout": 5000, "max_payout": 20000, "success_rate": 0.6, "cooldown": 3600 # 1 hour }, "Casino": { "min_crew": 3, "max_crew": 6, "min_payout": 10000, "max_payout": 50000, "success_rate": 0.5, "cooldown": 7200 # 2 hours }, "Federal Reserve": { "min_crew": 5, "max_crew": 8, "min_payout": 25000, "max_payout": 100000, "success_rate": 0.3, "cooldown": 14400 # 4 hours } } } default_guild = { "last_heist": None, "heist_cooldown": 1800 # 30 minutes between heists } default_user = { "heist_stats": { "participated": 0, "succeeded": 0, "failed": 0, "total_earned": 0 }, "last_heist": None } self.config.register_global(**default_global) self.config.register_guild(**default_guild) self.config.register_user(**default_user) @commands.group() async def heist(self, ctx): """Heist commands""" pass @heist.command(name="targets") async def list_targets(self, ctx): """List available heist targets""" targets = await self.config.targets() embed = discord.Embed( title="Available Heist Targets", color=discord.Color.red(), description="Choose your target wisely!" ) for name, data in targets.items(): embed.add_field( name=name, value=f"Crew Size: {data['min_crew']}-{data['max_crew']}\n" f"Potential Payout: ${data['min_payout']:,}-${data['max_payout']:,}\n" f"Success Rate: {data['success_rate']*100}%\n" f"Cooldown: {data['cooldown']//3600} hours", inline=False ) await ctx.send(embed=embed) @heist.command(name="start") async def start_heist(self, ctx, *, target_name: str): """Start a heist on a specific target""" if ctx.guild.id in self.active_heists: return await ctx.send("A heist is already in progress in this server!") targets = await self.config.targets() if target_name not in targets: return await ctx.send("Invalid target! Use `!heist targets` to see available targets.") target = targets[target_name] last_heist = await self.config.guild(ctx.guild).last_heist() if last_heist: last_heist = datetime.fromisoformat(last_heist) cooldown = timedelta(seconds=await self.config.guild(ctx.guild).heist_cooldown()) if datetime.now() - last_heist < cooldown: remaining = cooldown - (datetime.now() - last_heist) return await ctx.send(f"The heat is still high! Wait {remaining.seconds//60} minutes before the next heist.") self.active_heists[ctx.guild.id] = { "target": target_name, "leader": ctx.author, "crew": [ctx.author], "status": "recruiting", "min_crew": target["min_crew"], "max_crew": target["max_crew"] } embed = discord.Embed( title="Heist Planning Phase", description=f"{ctx.author.name} is planning a heist on {target_name}!\n" f"Need {target['min_crew']-1} to {target['max_crew']-1} more crew members.\n" f"Use `!heist join` to participate!\n" f"Planning phase ends in 60 seconds.", color=discord.Color.gold() ) await ctx.send(embed=embed) await asyncio.sleep(60) if ctx.guild.id in self.active_heists: heist = self.active_heists[ctx.guild.id] if len(heist["crew"]) < target["min_crew"]: del self.active_heists[ctx.guild.id] return await ctx.send("Not enough crew members joined. The heist has been cancelled.") await self.execute_heist(ctx, target_name) @heist.command(name="join") async def join_heist(self, ctx): """Join an active heist""" if ctx.guild.id not in self.active_heists: return await ctx.send("There is no active heist to join!") heist = self.active_heists[ctx.guild.id] if heist["status"] != "recruiting": return await ctx.send("This heist is no longer recruiting!") if ctx.author in heist["crew"]: return await ctx.send("You're already in the crew!") if len(heist["crew"]) >= heist["max_crew"]: return await ctx.send("The crew is already full!") heist["crew"].append(ctx.author) await ctx.send(f"{ctx.author.name} has joined the heist! ({len(heist['crew'])}/{heist['max_crew']} crew members)") async def execute_heist(self, ctx, target_name): """Execute the heist and determine the outcome""" heist = self.active_heists[ctx.guild.id] target = (await self.config.targets())[target_name] # Calculate success chance based on crew size and target difficulty crew_bonus = (len(heist["crew"]) - target["min_crew"]) * 0.05 final_success_rate = min(0.95, target["success_rate"] + crew_bonus) # Roll for success success = random.random() < final_success_rate if success: # Calculate payout base_payout = random.randint(target["min_payout"], target["max_payout"]) individual_payout = base_payout // len(heist["crew"]) embed = discord.Embed( title="Heist Successful!", description=f"The crew successfully robbed {target_name}!\n" f"Each crew member earned ${individual_payout:,}!", color=discord.Color.green() ) # Distribute payouts and update stats for member in heist["crew"]: await bank.deposit_credits(member, individual_payout) async with self.config.user(member).heist_stats() as stats: stats["participated"] += 1 stats["succeeded"] += 1 stats["total_earned"] += individual_payout else: fine = random.randint(1000, 5000) embed = discord.Embed( title="Heist Failed!", description=f"The heist on {target_name} was a disaster!\n" f"Each crew member was fined ${fine:,}!", color=discord.Color.red() ) # Apply fines and update stats for member in heist["crew"]: try: await bank.withdraw_credits(member, fine) except ValueError: await bank.set_balance(member, 0) async with self.config.user(member).heist_stats() as stats: stats["participated"] += 1 stats["failed"] += 1 # Update guild heist cooldown await self.config.guild(ctx.guild).last_heist.set(datetime.now().isoformat()) # Cleanup del self.active_heists[ctx.guild.id] # Send result await ctx.send(embed=embed) @heist.command(name="stats") async def heist_stats(self, ctx, member: discord.Member = None): """View heist statistics for a user""" member = member or ctx.author stats = await self.config.user(member).heist_stats() embed = discord.Embed( title=f"Heist Stats for {member.name}", color=discord.Color.blue() ) success_rate = (stats["succeeded"] / stats["participated"] * 100) if stats["participated"] > 0 else 0 embed.add_field(name="Heists Participated", value=stats["participated"]) embed.add_field(name="Successful Heists", value=stats["succeeded"]) embed.add_field(name="Failed Heists", value=stats["failed"]) embed.add_field(name="Success Rate", value=f"{success_rate:.1f}%") embed.add_field(name="Total Earnings", value=f"${stats['total_earned']:,}") await ctx.send(embed=embed)