1
Fork 0
mirror of https://github.com/wlinator/luminara.git synced 2024-10-02 22:23:13 +00:00
Lumi/modules/gambling.py

309 lines
12 KiB
Python

import asyncio
import os
import random
import discord
from discord.ext import commands
from dotenv import load_dotenv
from data.BlackJackStats import BlackJackStats
from data.Currency import Currency
from data.Inventory import Inventory
from data.Item import Item
from data.SlotsStats import SlotsStats
from main import economy_config
from sb_tools import economy_embeds, economy_functions, universal, interaction, embeds
load_dotenv('.env')
active_blackjack_games = {}
special_balance_name = os.getenv("SPECIAL_BALANCE_NAME")
cash_balance_name = os.getenv("CASH_BALANCE_NAME")
class GamblingCog(commands.Cog):
def __init__(self, sbbot):
self.bot = sbbot
@commands.slash_command(
name="blackjack",
description="Start a game of blackjack.",
guild_only=True
)
@commands.check(universal.channel_check)
async def blackjack(self, ctx, *, bet: discord.Option(int)):
# check if the player already has an active blackjack going
if ctx.author.id in active_blackjack_games:
await ctx.respond(embed=economy_embeds.already_playing("BlackJack"))
return
# Currency handler
ctx_currency = Currency(ctx.author.id)
# check if the user has enough cash
player_cash_balance = ctx_currency.cash
if bet > player_cash_balance or bet <= 0:
await ctx.respond(embed=economy_embeds.not_enough_cash())
return
active_blackjack_games[ctx.author.id] = True
try:
player_hand = []
dealer_hand = []
deck = economy_functions.blackjack_get_new_deck()
# deal initial cards (player draws two & dealer one)
player_hand.append(economy_functions.blackjack_deal_card(deck))
player_hand.append(economy_functions.blackjack_deal_card(deck))
dealer_hand.append(economy_functions.blackjack_deal_card(deck))
# calculate initial hands
player_hand_value = economy_functions.blackjack_calculate_hand_value(player_hand)
dealer_hand_value = economy_functions.blackjack_calculate_hand_value(dealer_hand)
status = "game_start" if player_hand_value != 21 else "player_blackjack"
view = interaction.BlackJackButtons(ctx) if status == "game_start" else None
await ctx.respond(embed=economy_embeds.blackjack_show(ctx, bet, player_hand,
dealer_hand, player_hand_value,
dealer_hand_value, status=status), view=view,
content=ctx.author.mention)
while status == "game_start":
await view.wait()
if view.clickedHit:
# player draws a card & value is calculated
player_hand.append(economy_functions.blackjack_deal_card(deck))
player_hand_value = economy_functions.blackjack_calculate_hand_value(player_hand)
if player_hand_value > 21:
status = "player_busted"
elif player_hand_value == 21:
status = "player_won_21"
elif view.clickedStand:
# player stands, dealer draws cards until he wins OR busts
while dealer_hand_value <= player_hand_value:
dealer_hand.append(economy_functions.blackjack_deal_card(deck))
dealer_hand_value = economy_functions.blackjack_calculate_hand_value(dealer_hand)
if dealer_hand_value > 21:
status = "dealer_busted"
else:
status = "dealer_won"
else:
status = "timed_out"
break
# edit the embed, disable view if game is over.
if status == "game_start":
view = interaction.BlackJackButtons(ctx)
else:
view = None
await ctx.edit(embed=economy_embeds.blackjack_show(ctx, bet, player_hand,
dealer_hand, player_hand_value,
dealer_hand_value, status=status), view=view,
content=ctx.author.mention)
# change balance
if status == "player_busted" or status == "dealer_won":
ctx_currency.take_cash(bet)
ctx_currency.push()
# push stats (low priority)
stats = BlackJackStats(
user_id=ctx.author.id,
is_won=False,
bet=bet,
payout=0,
hand_player=player_hand,
hand_dealer=dealer_hand
)
stats.push()
elif status == "timed_out":
await ctx.send(embed=economy_embeds.out_of_time(), content=ctx.author.mention)
ctx_currency.take_cash(bet)
ctx_currency.push()
else:
# bet multiplier
payout = bet * float(economy_config["blackjack"]["reward_multiplier"])
ctx_currency.add_cash(payout)
ctx_currency.push()
if status == "player_blackjack":
# if 21 -> add item
inventory = Inventory(ctx.author.id)
item = Item.get_item_by_name("bitch_coin")
inventory.add_item(item)
embed = discord.Embed(
color=discord.Color.embed_background(),
title="You hit a BlackJack!",
description=f"Yous a bitch for winning with a natural hand so I gave you 1 "
f"**{item.display_name}**."
)
embed.set_footer(text="Take a look in /inventory")
await ctx.respond(embed=embed)
# push stats (low priority)
stats = BlackJackStats(
user_id=ctx.author.id,
is_won=True,
bet=bet,
payout=payout,
hand_player=player_hand,
hand_dealer=dealer_hand
)
stats.push()
except Exception as e:
await ctx.respond(embed=embeds.command_error_1())
print("Something went wrong in the gambling command:\n", e)
finally:
# remove player from active games list
del active_blackjack_games[ctx.author.id]
@commands.slash_command(
name="slots",
descriptions="Spin the slots for a chance to win the jackpot!",
guild_only=True
)
@commands.check(universal.channel_check)
async def slots(self, ctx, *, bet: discord.Option(int)):
# Currency handler
ctx_currency = Currency(ctx.author.id)
# check if the user has enough cash
player_cash_balance = ctx_currency.cash
if bet > player_cash_balance or bet <= 0:
await ctx.respond(embed=economy_embeds.not_enough_cash())
return
# calculate the results before the command is shown
results = [random.randint(0, 6) for i in range(3)]
calculated_results = economy_functions.calculate_slots_results(bet, results)
type = calculated_results[0]
payout = calculated_results[1]
multiplier = calculated_results[2]
is_won = True
if type == "lost":
is_won = False
# start with default "spinning" embed
await ctx.respond(embed=economy_embeds.slots_spinning(ctx, 3, bet, results, self.bot))
await asyncio.sleep(1)
await ctx.edit(embed=economy_embeds.slots_spinning(ctx, 2, bet, results, self.bot),
allowed_mentions=discord.AllowedMentions.none())
await asyncio.sleep(1)
await ctx.edit(embed=economy_embeds.slots_spinning(ctx, 1, bet, results, self.bot),
allowed_mentions=discord.AllowedMentions.none())
await asyncio.sleep(1)
await ctx.edit(embed=economy_embeds.slots_finished(ctx, type, multiplier, bet, results, self.bot),
allowed_mentions=discord.AllowedMentions.none())
# user payout
if payout >= 0:
ctx_currency.add_cash(payout)
else:
ctx_currency.take_cash(payout)
# push stats (low priority)
if payout <= 0:
payout = 0
stats = SlotsStats(
user_id=ctx.author.id,
is_won=is_won,
bet=bet,
payout=payout,
spin_type=type,
icons=results
)
ctx_currency.push()
stats.push()
@commands.slash_command(
name="duel",
description="Challenge another player to a fight.",
guild_only=True
)
@commands.check(universal.channel_check)
async def duel(self, ctx, *, opponent: discord.Option(discord.Member), bet: discord.Option(int)):
challenger = ctx.author
if challenger.id == opponent.id:
return await ctx.respond(content="You cannot duel yourself.")
elif opponent.bot:
return await ctx.respond(content="You cannot duel a bot.")
# Currency handler
challenger_currency = Currency(ctx.author.id)
opponent_currency = Currency(opponent.id)
# check if challenger has enough cash
challenger_cash_balance = challenger_currency.cash
if bet > challenger_cash_balance or bet <= 0:
return await ctx.respond(embed=economy_embeds.not_enough_cash())
# if opponent doesn't have sufficient money, the bet will become the opponent's cash
opponent_cash_balance = opponent_currency.cash
all_in = ""
if opponent_cash_balance <= 0:
return await ctx.respond(f"Woops, you can't do that because **{opponent.name}** has no money.")
elif bet > opponent_cash_balance:
bet = opponent_cash_balance
all_in = " | opponent's all-in"
# challenge message
view = interaction.DuelChallenge(opponent)
await ctx.respond(
content=f"**{challenger.name}** challenges {opponent.mention} to a duel ({cash_balance_name}{bet}{all_in})\n"
f"Use the buttons to accept/deny (challenge expires after 60s)", view=view)
await view.wait()
if view.clickedConfirm:
winner = random.choice([challenger, opponent])
loser = opponent if winner == challenger else challenger
combat_message = random.choice(economy_config["duel"]["combat_messages"]).format(f"**{winner.name}**",
f"**{loser.name}**")
await ctx.respond(content=f"{combat_message}\n\n"
f"{winner.mention} wins **{cash_balance_name}{bet}**\n"
f"{loser.mention} loses this bet.")
# payouts
if winner == challenger:
challenger_currency.add_cash(bet)
opponent_currency.take_cash(bet)
elif winner == opponent:
opponent_currency.add_cash(bet)
challenger_currency.take_cash(bet)
elif view.clickedDeny:
await ctx.edit(content=f"**{opponent.name}** canceled the duel.")
else:
await ctx.edit(content=f"Time ran out.")
challenger_currency.push()
opponent_currency.push()
def setup(sbbot):
sbbot.add_cog(GamblingCog(sbbot))