Implement multi-channel support.

* Can now have shootouts in multiple channels.
This commit is contained in:
Sydney 2020-12-04 14:08:46 -05:00
parent 96afb67bf2
commit 68d434cc91
No known key found for this signature in database
GPG key ID: 6E62B942078EC9A2
2 changed files with 79 additions and 18 deletions

View file

@ -154,6 +154,7 @@ A game cog that rewards players for fast typing. The first player to type a mess
- Configurable random time between when the lobby ends and the game starts. - Configurable random time between when the lobby ends and the game starts.
- Settable pot amount, even zero! - Settable pot amount, even zero!
- Configurable wait time after the first player has joined the game. - Configurable wait time after the first player has joined the game.
- Shootouts in multiple channels!
#### Smart React #### Smart React

View file

@ -10,7 +10,7 @@ class Shootout(commands.Cog):
default_config = { default_config = {
"cost": 50, "cost": 50,
"Messages": ["Shoot!", "Draw!", "Fire!", "Kill!"], "Messages": ["Shoot!", "Draw!", "Fire!", "Kill!"],
"Session": {"Pot": 0, "Players": [], "Active": False}, "Sessions": [],
"Times": {"lobby": 60, "delay": 10, "fuzzy": 3}, "Times": {"lobby": 60, "delay": 10, "fuzzy": 3},
"Victory": [ "Victory": [
"{} has won the shootout! {} {} has been deposited to their account!", "{} has won the shootout! {} {} has been deposited to their account!",
@ -19,6 +19,12 @@ class Shootout(commands.Cog):
"{} fires their gun, and all of their enemies fall to the ground! They claim the bounty of {} {}.", "{} fires their gun, and all of their enemies fall to the ground! They claim the bounty of {} {}.",
], ],
} }
session_config = {
"Channel": None,
"Pot": 0,
"Players": [],
"Active": False,
}
def __init__(self, bot): def __init__(self, bot):
super().__init__() super().__init__()
@ -31,14 +37,15 @@ class Shootout(commands.Cog):
return return
async def game_checks(self, ctx, settings) -> bool: async def game_checks(self, ctx, settings) -> bool:
if bool(settings["Session"]["Active"]): session = await self.get_session_from_context(ctx)
if bool(session["Active"]):
await ctx.send("There's already a shootout! Wait for them to finish!") await ctx.send("There's already a shootout! Wait for them to finish!")
return False return False
if ctx.author.id in settings["Session"]["Players"]: if ctx.author.id in session["Players"]:
await ctx.send("You're already waiting for the shootout!") await ctx.send("You're already waiting for the shootout!")
return False return False
try: try:
await bank.withdraw_credits(ctx.author, settings["cost"]) # <- Might raise a ValueError! await bank.withdraw_credits(ctx.author, settings["cost"])
return True return True
except ValueError: except ValueError:
currency = await bank.get_currency_name(ctx.guild) currency = await bank.get_currency_name(ctx.guild)
@ -46,12 +53,15 @@ class Shootout(commands.Cog):
return False return False
async def add_player(self, ctx, cost): async def add_player(self, ctx, cost):
current_pot = await self.config.guild(ctx.guild).Session.Pot() session = await self.get_session_from_context(ctx)
await self.config.guild(ctx.guild).Session.Pot.set(value=(current_pot + cost))
async with self.config.guild(ctx.guild).Session.Players() as players: current_pot = session["Pot"]
players.append(ctx.author.id) session["Pot"] = current_pot + cost
num_players = len(players)
session["Players"].append(ctx.author.id)
num_players = len(session["Players"])
await self.save_session_to_config(ctx, session)
if num_players == 1: if num_players == 1:
wait = await self.config.guild(ctx.guild).Times.lobby() wait = await self.config.guild(ctx.guild).Times.lobby()
@ -66,7 +76,7 @@ class Shootout(commands.Cog):
await ctx.send("{} joined the shootout!".format(ctx.author.mention)) await ctx.send("{} joined the shootout!".format(ctx.author.mention))
async def start_game(self, ctx): async def start_game(self, ctx):
session = await self.config.guild(ctx.guild).Session.all() session = await self.get_session_from_context(ctx)
players = [ctx.guild.get_member(player) for player in session["Players"]] players = [ctx.guild.get_member(player) for player in session["Players"]]
filtered_players = [player for player in players if isinstance(player, discord.Member)] filtered_players = [player for player in players if isinstance(player, discord.Member)]
if len(filtered_players) < 2: if len(filtered_players) < 2:
@ -75,10 +85,11 @@ class Shootout(commands.Cog):
except BalanceTooHigh as e: except BalanceTooHigh as e:
await bank.set_balance(ctx.author, e.max_balance) await bank.set_balance(ctx.author, e.max_balance)
await ctx.send("A shootout with yourself means just shooting at some bottles. For that, no charge.") await ctx.send("A shootout with yourself means just shooting at some bottles. For that, no charge.")
await self.config.guild(ctx.guild).Session.clear() await self.clear_session(ctx)
return return
listen_message = await self.get_random_draw_message(ctx) listen_message = await self.get_random_draw_message(ctx)
await self.config.guild(ctx.guild).Session.Active.set(True) session["Active"] = True
await self.save_session_to_config(ctx, session)
await ctx.send( await ctx.send(
'A shootout is about to start! When I say "Draw!", type `{}` to shoot your weapon! First person who shoots wins!'.format( 'A shootout is about to start! When I say "Draw!", type `{}` to shoot your weapon! First person who shoots wins!'.format(
listen_message listen_message
@ -98,13 +109,14 @@ class Shootout(commands.Cog):
async def end_game(self, ctx, winner: discord.Member): async def end_game(self, ctx, winner: discord.Member):
currency = await bank.get_currency_name(ctx.guild) currency = await bank.get_currency_name(ctx.guild)
total = await self.config.guild(ctx.guild).Session.Pot() session = await self.get_session_from_context(ctx)
total = session["Pot"]
try: try:
await bank.deposit_credits(winner, total) await bank.deposit_credits(winner, total)
except BalanceTooHigh as e: except BalanceTooHigh as e:
await bank.set_balance(winner, e.max_balance) await bank.set_balance(winner, e.max_balance)
await ctx.send((await self.get_random_win_message(ctx)).format(winner.mention, total, currency)) await ctx.send((await self.get_random_win_message(ctx)).format(winner.mention, total, currency))
await self.config.guild(ctx.guild).Session.clear() await self.clear_session(ctx)
async def get_random_draw_message(self, ctx) -> str: async def get_random_draw_message(self, ctx) -> str:
return random.choice((await self.config.guild(ctx.guild).Messages())) return random.choice((await self.config.guild(ctx.guild).Messages()))
@ -117,6 +129,34 @@ class Shootout(commands.Cog):
fuzzy = await self.config.guild(ctx.guild).Times.fuzzy() fuzzy = await self.config.guild(ctx.guild).Times.fuzzy()
return random.randint(delay - fuzzy, delay + fuzzy) return random.randint(delay - fuzzy, delay + fuzzy)
async def get_session_from_context(self, ctx):
channel_id = ctx.channel.id
sessions = await self.config.guild(ctx.guild).Sessions()
# Check through all of our currently loaded sessions
for session in sessions:
if session["Channel"] == channel_id:
return session
# Session for this channel does not exist
new_session = self.session_config.copy()
new_session["Channel"] = channel_id
sessions.append(new_session)
await self.config.guild(ctx.guild).Sessions.set(sessions)
return new_session
async def save_session_to_config(self, ctx, the_session) -> None:
sessions = await self.config.guild(ctx.guild).Sessions()
for index, session in enumerate(sessions):
if session["Channel"] == the_session["Channel"]:
sessions[index] = the_session
await self.config.guild(ctx.guild).Sessions.set(sessions)
async def clear_session(self, ctx) -> None:
sessions = await self.config.guild(ctx.guild).Sessions()
for index, session in enumerate(sessions):
if session["Channel"] == ctx.channel.id:
sessions.remove(session)
await self.config.guild(ctx.guild).Sessions.set(sessions)
@commands.command() @commands.command()
@commands.guild_only() @commands.guild_only()
async def shootout(self, ctx): async def shootout(self, ctx):
@ -269,13 +309,33 @@ class Shootout(commands.Cog):
**These commands require the Administrator permission node.**""" **These commands require the Administrator permission node.**"""
pass pass
@soset_admin.command(name="reset") @soset_admin.group(name="reset")
async def soset_admin_reset(self, ctx): async def soset_admin_reset(self, ctx):
"""Clears all session data. Useful for if you break something. """Clear session data. Useful if you break something."""
**THIS COMMAND CLEARS ALL SESSION DATA. DO NOT USE WHILE A GAME IS IN SESSION, OR IT WILL BE DESTROYED.** pass
@soset_admin_reset.command(name="channel")
async def soset_admin_reset_channel(self, ctx):
"""Clears session data for this channel. Useful for if you break something.
**THIS COMMAND CLEARS SESSION FOR THIS CHANNELS. DO NOT USE WHILE A GAME IS IN SESSION, OR IT WILL BE DESTROYED.**
""" """
await self.config.guild(ctx.guild).Session.clear() await self.clear_session(ctx)
await ctx.send("I cleared data for this channel.")
await ctx.tick() await ctx.tick()
return
@soset_admin_reset.command(name="all")
async def soset_admin_reset_all(self, ctx):
"""Clears all session data. Useful for if you break something.
**THIS COMMAND CLEARS ALL SESSION FOR ALL CHANNELS DATA. DO NOT USE WHILE GAMES ARE IN SESSION, OR THEY WILL BE DESTROYED.**
"""
await self.config.guild(ctx.guild).Sessions.clear()
await ctx.send("I cleared data for all sessions.")
await ctx.tick()
@soset_admin.command(name="test")
async def soset_admin_test(self, ctx):
return await ctx.send(await self.get_session_from_context(ctx))
@soset_admin.command(name="dump") @soset_admin.command(name="dump")
async def soset_admin_dump(self, ctx): async def soset_admin_dump(self, ctx):