Ruby-Cogs/unbelievaboat/heist.py

240 lines
No EOL
9.2 KiB
Python

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)