Implement requested changes.

* Made a delay between when the shootout starts and when messages can be submitted.
    - This delay can be configurable.
* Added a fuzzy time to help randomize the time between when the lobby ends and shootout begins.
    - This fuzzy time can be configurable.
* "Draw!" messages are now configurable. This is the message the bot listens for.
* Added randomized and configurable victory messages.
    - The first {} is always the user's mention.
    - The second {} is always the currency amount won.
    - The final {} is always the name of the currency.
* Added warnings when setting excessively high wait times. Admins can confirm they want high wait times with a "yes" message.
* Debug config dump and reset commands are now visible.
This commit is contained in:
Sydney 2020-12-03 20:21:16 -05:00
parent 195b0eca05
commit 96afb67bf2
No known key found for this signature in database
GPG key ID: 6E62B942078EC9A2
2 changed files with 148 additions and 36 deletions

View file

@ -150,6 +150,8 @@ Also, since it does use the Audio cog, if users in different VC's queue sfx soun
A game cog that rewards players for fast typing. The first player to type a message wins a pot of currency.
**Features:**
- Configurable message to type to win.
- Configurable randomized victory messages.
- Configurable random time between when the lobby ends and the game starts.
- Settable pot amount, even zero!
- Configurable wait time after the first player has joined the game.

View file

@ -3,28 +3,27 @@
# https://github.com/Redjumpman/Jumper-Plugins/blob/a5a55e3968cb366bf257cb0e886a1c30588e85ef/russianroulette/russianroulette.py
#
from redbot.core import bank, commands, checks, Config
import discord
import asyncio
import asyncio, contextlib, discord, random, shlex
class Shootout(commands.Cog):
default_config = {
"cost": 50,
"message": "Shoot!",
"wait_time": 60,
"Messages": ["Shoot!", "Draw!", "Fire!", "Kill!"],
"Session": {"Pot": 0, "Players": [], "Active": False},
"Times": {"lobby": 60, "delay": 10, "fuzzy": 3},
"Victory": [
"{} has won the shootout! {} {} has been deposited to their account!",
"Looks like {} is the fastest shot in the server! They were given the pot of {} {}",
"{} must practice. That draw time was insane! The pot of {} {} belongs to them.",
"{} fires their gun, and all of their enemies fall to the ground! They claim the bounty of {} {}.",
],
}
def __init__(self, bot):
super().__init__()
self.bot = bot
self.config = Config.get_conf(self, identifier=163490961253466112, force_registration=True)
default_config = {
"cost": 50,
"message": "Shoot!",
"wait_time": 60,
"Session": {"Pot": 0, "Players": [], "Active": False},
}
self.config.register_guild(**self.default_config)
async def red_delete_data_for_user(self, **kwargs):
@ -55,7 +54,7 @@ class Shootout(commands.Cog):
num_players = len(players)
if num_players == 1:
wait = await self.config.guild(ctx.guild).wait_time()
wait = await self.config.guild(ctx.guild).Times.lobby()
await ctx.send(
"{0.author.mention} is gathering players for a shootout!\n"
"Type `{0.prefix}shootout` to join in!\n"
@ -67,25 +66,29 @@ class Shootout(commands.Cog):
await ctx.send("{} joined the shootout!".format(ctx.author.mention))
async def start_game(self, ctx):
settings = await self.config.guild(ctx.guild).Session.all()
players = [ctx.guild.get_member(player) for player in settings["Players"]]
session = await self.config.guild(ctx.guild).Session.all()
players = [ctx.guild.get_member(player) for player in session["Players"]]
filtered_players = [player for player in players if isinstance(player, discord.Member)]
if len(filtered_players) < 2:
try:
await bank.deposit_credits(ctx.author, settings["Pot"])
await bank.deposit_credits(ctx.author, session["Pot"])
except BalanceTooHigh as e:
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 self.config.guild(ctx.guild).Session.clear()
return
listen_message = await self.config.guild(ctx.guild).message()
listen_message = await self.get_random_draw_message(ctx)
await self.config.guild(ctx.guild).Session.Active.set(True)
await ctx.send(
"The shootout has started! Draw your weapons and 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
)
)
await asyncio.sleep((await self.get_random_wait_time(ctx)))
await ctx.send("Draw!")
def check(m):
return m.content.lower() == listen_message.lower() and m.channel == ctx.channel and m.author in players
@ -100,13 +103,20 @@ class Shootout(commands.Cog):
await bank.deposit_credits(winner, total)
except BalanceTooHigh as e:
await bank.set_balance(winner, e.max_balance)
await ctx.send(
"{} has won the shootout! {} {} has been deposited to their account!".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()
async def get_random_draw_message(self, ctx) -> str:
return random.choice((await self.config.guild(ctx.guild).Messages()))
async def get_random_win_message(self, ctx) -> str:
return random.choice((await self.config.guild(ctx.guild).Victory()))
async def get_random_wait_time(self, ctx) -> int:
delay = await self.config.guild(ctx.guild).Times.delay()
fuzzy = await self.config.guild(ctx.guild).Times.fuzzy()
return random.randint(delay - fuzzy, delay + fuzzy)
@commands.command()
@commands.guild_only()
async def shootout(self, ctx):
@ -142,32 +152,132 @@ class Shootout(commands.Cog):
await ctx.tick()
return
@soset.command(name="message")
async def soset_message(self, ctx, message: str):
"""Sets the message that the bot listens for during shootout games. Only affects new games!"""
await self.config.guild(ctx.guild).message.set(message)
@soset.command(name="draw")
async def soset_draw(self, ctx, *, draws: str):
"""Sets the message that the bot listens for during shootout games.
One will randomly be selected per game.
"""
await self.config.guild(ctx.guild).Messages.set(shlex.split(draws))
await ctx.tick()
return
@soset.command(name="wait")
@soset.command(name="victory")
async def soset_victory(self, ctx, *, victories: str):
"""Sets the random victory messages the bot displays when someone wins.
Use full string in quotation marks to break up the messages.
Failure to use quotation marks will set victory messages with a single word.
**This WILL cause errors during `[p]shootout` command execution!**
"""
await self.config.guild(ctx.guild).Victory.set(shlex.split(victories))
await ctx.tick()
return
@soset.command(name="lobby")
async def soset_wait(self, ctx, wait: int):
"""Sets the wait time until the shootout starts after player 1 runs the command."""
"""Sets the wait time until the shootout starts after player 1 runs the command.
Also known as the lobby time.
"""
if wait < 0:
return await ctx.send("Get your negativity out of here!")
await self.config.guild(ctx.guild).wait_time.set(wait)
if wait > 120:
if await self.confirm_long_wait_time(ctx):
await self.config.guild(ctx.guild).Times.lobby.set(wait)
await ctx.tick()
else:
return await ctx.send("Cancelling setting.")
else:
await self.config.guild(ctx.guild).Times.lobby.set(wait)
await ctx.tick()
@soset.command(name="delay")
async def soset_delay(self, ctx, wait: int):
"""Sets the delay time between when the bot displays the message to shoot, and when it accepts messages.
This is also known as the delay time."""
if wait < 0:
return await ctx.send("Get your negativity out of here!")
fuzzy = await self.config.guild(ctx.guild).Times.fuzzy()
if (wait - fuzzy) < 0:
return await ctx.send(
f"New delay value would set delay - fuzzy value less than 0. With currency fuzzy value, delay needs to be at least {fuzzy}"
)
if wait > 120:
if await self.confirm_long_wait_time(ctx):
await self.config.guild(ctx.guild).Times.delay.set(wait)
await ctx.tick()
else:
return await ctx.send("Cancelling setting.")
await self.config.guild(ctx.guild).Times.delay.set(wait)
await ctx.tick()
@soset.command(name="fuzzy")
async def soset_fuzzy(self, ctx, wait: int):
"""Sets the fuzzy time to set the randomness between when the bot sends the shoot message and when it accepts messages.
This is also known as the fuzzy time.
Specifically, the fuzzy time is used to determine the min and max value of the wait time. The actual wait time is a random number between `delay - fuzzy` and `delay + fuzzy`.
```python
return random.randomint(delay - fuzzy, delay + fuzzy)
```
"""
if wait < 0:
return await ctx.send("Get your negativity out of here!")
delay = await self.config.guild(ctx.guild).Times.delay()
if (delay - wait) < 0:
return await ctx.send(
f"New fuzzy value would set delay - fuzzy value less than 0. With current delay value, fuzzy needs to be at least {delay}"
)
if (delay + wait) > 120:
if await self.confirm_long_wait_time(ctx):
await self.config.guild(ctx.guild).Times.fuzzy.set(wait)
else:
return await ctx.send("Cancelling setting.")
await self.config.guild(ctx.guild).Times.fuzzy.set(wait)
await ctx.tick()
async def confirm_long_wait_time(self, ctx) -> bool:
query = await ctx.send(
"Long wait times can cause users to leave the game and the bot to potentially experience issues. If you want to set this anyway, type `yes`."
)
try:
def check(m):
return m.channel == ctx.channel and m.author == ctx.author
message = await self.bot.wait_for("message", check=check, timeout=15)
if message.content.lower() == "yes":
with contextlib.suppress(discord.Forbidden):
await message.delete()
await query.delete()
return True
else:
await query.delete()
return False
except asyncio.TimeoutError:
await query.delete()
return False
@soset.group(name="admin")
@commands.guild_only()
@checks.admin_or_permissions(administrator=True)
@commands.command(hidden=True)
async def shootout_reset(self, ctx):
"""This command clears all session data. Useful for if you break something."""
async def soset_admin(self, ctx):
"""Perform administrator only commands. Useful debugging commands provided.
**These commands require the Administrator permission node.**"""
pass
@soset_admin.command(name="reset")
async def soset_admin_reset(self, ctx):
"""Clears all session data. Useful for if you break something.
**THIS COMMAND CLEARS ALL SESSION DATA. DO NOT USE WHILE A GAME IS IN SESSION, OR IT WILL BE DESTROYED.**
"""
await self.config.guild(ctx.guild).Session.clear()
await ctx.tick()
@commands.guild_only()
@checks.admin_or_permissions(administrator=True)
@commands.command(hidden=True)
async def shootout_dump_config(self, ctx):
"""This command dumps the current config data."""
@soset_admin.command(name="dump")
async def soset_admin_dump(self, ctx):
"""Dumps the entire config for this guild."""
await ctx.send("{}".format(await self.config.guild(ctx.guild).all()))