Mostly messaging adjustments, fix for failing to talley votes
This commit is contained in:
parent
e27cfba763
commit
f3965b73d8
@ -10,13 +10,15 @@ from redbot.core.bot import Red
|
||||
from redbot.core.utils import AsyncIter
|
||||
|
||||
from werewolf.builder import parse_code
|
||||
from werewolf.constants import ALIGNMENT_NEUTRAL
|
||||
from werewolf.player import Player
|
||||
from werewolf.role import Role
|
||||
from werewolf.votegroup import VoteGroup
|
||||
|
||||
log = logging.getLogger("red.fox_v3.werewolf.game")
|
||||
|
||||
HALF_DAY_LENGTH = 24 # FixMe: to 120 later for 4 minute days
|
||||
HALF_DAY_LENGTH = 60 # FixMe: Make configurable
|
||||
HALF_NIGHT_LENGTH = 60
|
||||
|
||||
|
||||
async def anyone_has_role(
|
||||
@ -167,7 +169,7 @@ class Game:
|
||||
await player.member.add_roles(*[self.game_role])
|
||||
except discord.Forbidden:
|
||||
log.exception(f"Unable to add role **{self.game_role.name}**")
|
||||
await ctx.send(
|
||||
await ctx.maybe_send_embed(
|
||||
f"Unable to add role **{self.game_role.name}**\n"
|
||||
f"Bot is missing `manage_roles` permissions"
|
||||
)
|
||||
@ -210,7 +212,7 @@ class Game:
|
||||
category=self.channel_category,
|
||||
)
|
||||
except discord.Forbidden:
|
||||
await ctx.send(
|
||||
await ctx.maybe_send_embed(
|
||||
"Unable to create Game Channel and none was provided\n"
|
||||
"Grant Bot appropriate permissions or assign a game_channel"
|
||||
)
|
||||
@ -225,7 +227,7 @@ class Game:
|
||||
)
|
||||
except discord.Forbidden as e:
|
||||
log.exception("Unable to rename Game Channel")
|
||||
await ctx.send("Unable to rename Game Channel, ignoring")
|
||||
await ctx.maybe_send_embed("Unable to rename Game Channel, ignoring")
|
||||
|
||||
try:
|
||||
for target, ow in overwrite.items():
|
||||
@ -235,7 +237,7 @@ class Game:
|
||||
target=target, overwrite=curr, reason="(BOT) New game of werewolf"
|
||||
)
|
||||
except discord.Forbidden:
|
||||
await ctx.send(
|
||||
await ctx.maybe_send_embed(
|
||||
"Unable to edit Game Channel permissions\n"
|
||||
"Grant Bot appropriate permissions to manage permissions"
|
||||
)
|
||||
@ -406,14 +408,17 @@ class Game:
|
||||
await vote_message.add_reaction("👎")
|
||||
|
||||
await asyncio.sleep(15)
|
||||
reaction_list = vote_message.reactions
|
||||
|
||||
if True: # TODO: Allow customizable vote history deletion.
|
||||
await vote_message.delete()
|
||||
# Refetch for reactions
|
||||
vote_message = await self.village_channel.fetch_message(id=vote_message.id)
|
||||
reaction_list = vote_message.reactions
|
||||
|
||||
raw_up_votes = sum(p for p in reaction_list if p.emoji == "👍" and not p.me)
|
||||
raw_down_votes = sum(p for p in reaction_list if p.emoji == "👎" and not p.me)
|
||||
|
||||
if True: # TODO: Allow customizable vote history deletion.
|
||||
await vote_message.delete()
|
||||
|
||||
# TODO: Support vote count modifying roles. (Need notify and count function)
|
||||
voted_to_lynch = raw_down_votes > raw_up_votes
|
||||
|
||||
@ -492,13 +497,13 @@ class Game:
|
||||
return
|
||||
await self._notify("at_night_start")
|
||||
|
||||
await asyncio.sleep(12) # 2 minutes FixMe to 120 later
|
||||
await asyncio.sleep(HALF_NIGHT_LENGTH) # 2 minutes FixMe to 120 later
|
||||
await self.village_channel.send(
|
||||
embed=discord.Embed(title="**Two minutes of night remain...**")
|
||||
embed=discord.Embed(title=f"**{HALF_NIGHT_LENGTH / 60} minutes of night remain...**")
|
||||
)
|
||||
await asyncio.sleep(9) # 1.5 minutes FixMe to 90 later
|
||||
await asyncio.sleep(HALF_NIGHT_LENGTH) # 1.5 minutes FixMe to 90 later
|
||||
await self.village_channel.send(
|
||||
embed=discord.Embed(title="**Thirty seconds until sunrise...**")
|
||||
embed=discord.Embed(title=f"**{HALF_NIGHT_LENGTH / 60} minutes until sunrise...**")
|
||||
)
|
||||
await asyncio.sleep(3) # .5 minutes FixMe to 30 Later
|
||||
|
||||
@ -560,8 +565,7 @@ class Game:
|
||||
)
|
||||
else:
|
||||
embed.add_field(
|
||||
name=f"{i} - {status}{player.member.display_name}",
|
||||
inline=False,
|
||||
name=f"{i} - {status}{player.member.display_name}", inline=False, value=""
|
||||
)
|
||||
|
||||
return await channel.send(embed=embed)
|
||||
@ -585,16 +589,16 @@ class Game:
|
||||
if votegroup is not None:
|
||||
self.p_channels[channel_id]["votegroup"] = votegroup
|
||||
|
||||
async def join(self, member: discord.Member, channel: discord.TextChannel):
|
||||
async def join(self, ctx, member: discord.Member):
|
||||
"""
|
||||
Have a member join a game
|
||||
"""
|
||||
if self.started:
|
||||
await channel.send("**Game has already started!**")
|
||||
await ctx.maybe_send_embed("**Game has already started!**")
|
||||
return
|
||||
|
||||
if await self.get_player_by_member(member) is not None:
|
||||
await channel.send(f"{member.display_name} is already in the game!")
|
||||
await ctx.maybe_send_embed(f"{member.display_name} is already in the game!")
|
||||
return
|
||||
|
||||
self.players.append(Player(member))
|
||||
@ -609,7 +613,7 @@ class Game:
|
||||
# f"Bot is missing `manage_roles` permissions"
|
||||
# )
|
||||
|
||||
await channel.send(
|
||||
await ctx.maybe_send_embed(
|
||||
f"{member.display_name} has been added to the game, "
|
||||
f"total players is **{len(self.players)}**"
|
||||
)
|
||||
@ -645,15 +649,15 @@ class Game:
|
||||
player = await self.get_player_by_member(ctx.author)
|
||||
|
||||
if player is None:
|
||||
await ctx.send("You're not in this game!")
|
||||
await ctx.maybe_send_embed("You're not in this game!")
|
||||
return
|
||||
|
||||
if not player.alive:
|
||||
await ctx.send("**Corpses** can't participate...")
|
||||
await ctx.maybe_send_embed("**Corpses** can't participate...")
|
||||
return
|
||||
|
||||
if player.role.blocked:
|
||||
await ctx.send("Something is preventing you from doing this...")
|
||||
await ctx.maybe_send_embed("Something is preventing you from doing this...")
|
||||
return
|
||||
|
||||
# Let role do target validation, might be alternate targets
|
||||
@ -821,7 +825,7 @@ class Game:
|
||||
async def set_code(self, ctx: commands.Context, game_code):
|
||||
if game_code is not None:
|
||||
self.game_code = game_code
|
||||
await ctx.send("Code has been set")
|
||||
await ctx.maybe_send_embed("Code has been set")
|
||||
|
||||
async def get_roles(self, ctx, game_code=None):
|
||||
if game_code is not None:
|
||||
@ -833,10 +837,12 @@ class Game:
|
||||
try:
|
||||
self.roles = await parse_code(self.game_code, self)
|
||||
except ValueError as e:
|
||||
await ctx.send("Invalid Code: Code contains unknown character\n{}".format(e))
|
||||
await ctx.maybe_send_embed(
|
||||
"Invalid Code: Code contains unknown character\n{}".format(e)
|
||||
)
|
||||
return False
|
||||
except IndexError as e:
|
||||
await ctx.send("Invalid Code: Code references unknown role\n{}".format(e))
|
||||
await ctx.maybe_send_embed("Invalid Code: Code references unknown role\n{}".format(e))
|
||||
|
||||
if not self.roles:
|
||||
return False
|
||||
@ -898,7 +904,8 @@ class Game:
|
||||
self.game_over = True
|
||||
alignment1 = alive_players[0].role.alignment
|
||||
alignment2 = alive_players[1].role.alignment
|
||||
if alignment1 == alignment2: # Same team
|
||||
# Same team and not neutral
|
||||
if alignment1 == alignment2 and alignment1 != ALIGNMENT_NEUTRAL:
|
||||
winners = alive_players
|
||||
else:
|
||||
winners = [max(alive_players, key=lambda p: p.role.alignment)]
|
||||
|
@ -35,9 +35,13 @@ class Player:
|
||||
|
||||
async def send_dm(self, message):
|
||||
try:
|
||||
await self.member.send(message) # Lets do embeds later
|
||||
await self.member.send(message) # Lets ToDo embeds later
|
||||
except discord.Forbidden:
|
||||
log.info(f"Unable to mention {self.member.__repr__()}")
|
||||
await self.role.game.village_channel.send(
|
||||
f"Couldn't DM {self.mention}, uh oh",
|
||||
allowed_mentions=discord.AllowedMentions(users=[self.member]),
|
||||
)
|
||||
except AttributeError:
|
||||
log.exception("Someone messed up and added a bot to the game (I think)")
|
||||
await self.role.game.village_channel.send("Someone messed up and added a bot to the game :eyes:")
|
||||
|
@ -72,9 +72,9 @@ class Werewolf(Cog):
|
||||
code = await gb.build_game(ctx)
|
||||
|
||||
if code != "":
|
||||
await ctx.send(f"Your game code is **{code}**")
|
||||
await ctx.maybe_send_embed(f"Your game code is **{code}**")
|
||||
else:
|
||||
await ctx.send("No code generated")
|
||||
await ctx.maybe_send_embed("No code generated")
|
||||
|
||||
@checks.guildowner()
|
||||
@commands.group()
|
||||
@ -117,10 +117,10 @@ class Werewolf(Cog):
|
||||
"""
|
||||
if role is None:
|
||||
await self.config.guild(ctx.guild).role_id.set(None)
|
||||
await ctx.send("Cleared Game Role")
|
||||
await ctx.maybe_send_embed("Cleared Game Role")
|
||||
else:
|
||||
await self.config.guild(ctx.guild).role_id.set(role.id)
|
||||
await ctx.send("Game Role has been set to **{}**".format(role.name))
|
||||
await ctx.maybe_send_embed("Game Role has been set to **{}**".format(role.name))
|
||||
|
||||
@commands.guild_only()
|
||||
@wwset.command(name="category")
|
||||
@ -130,14 +130,14 @@ class Werewolf(Cog):
|
||||
"""
|
||||
if category_id is None:
|
||||
await self.config.guild(ctx.guild).category_id.set(None)
|
||||
await ctx.send("Cleared Game Channel Category")
|
||||
await ctx.maybe_send_embed("Cleared Game Channel Category")
|
||||
else:
|
||||
category = discord.utils.get(ctx.guild.categories, id=int(category_id))
|
||||
if category is None:
|
||||
await ctx.send("Category not found")
|
||||
await ctx.maybe_send_embed("Category not found")
|
||||
return
|
||||
await self.config.guild(ctx.guild).category_id.set(category.id)
|
||||
await ctx.send("Game Channel Category has been set to **{}**".format(category.name))
|
||||
await ctx.maybe_send_embed("Game Channel Category has been set to **{}**".format(category.name))
|
||||
|
||||
@commands.guild_only()
|
||||
@wwset.command(name="channel")
|
||||
@ -147,10 +147,10 @@ class Werewolf(Cog):
|
||||
"""
|
||||
if channel is None:
|
||||
await self.config.guild(ctx.guild).channel_id.set(None)
|
||||
await ctx.send("Cleared Game Channel")
|
||||
await ctx.maybe_send_embed("Cleared Game Channel")
|
||||
else:
|
||||
await self.config.guild(ctx.guild).channel_id.set(channel.id)
|
||||
await ctx.send("Game Channel has been set to **{}**".format(channel.mention))
|
||||
await ctx.maybe_send_embed("Game Channel has been set to **{}**".format(channel.mention))
|
||||
|
||||
@commands.guild_only()
|
||||
@wwset.command(name="logchannel")
|
||||
@ -160,10 +160,10 @@ class Werewolf(Cog):
|
||||
"""
|
||||
if channel is None:
|
||||
await self.config.guild(ctx.guild).log_channel_id.set(None)
|
||||
await ctx.send("Cleared Game Log Channel")
|
||||
await ctx.maybe_send_embed("Cleared Game Log Channel")
|
||||
else:
|
||||
await self.config.guild(ctx.guild).log_channel_id.set(channel.id)
|
||||
await ctx.send("Game Log Channel has been set to **{}**".format(channel.mention))
|
||||
await ctx.maybe_send_embed("Game Log Channel has been set to **{}**".format(channel.mention))
|
||||
|
||||
@commands.group()
|
||||
async def ww(self, ctx: commands.Context):
|
||||
@ -181,9 +181,9 @@ class Werewolf(Cog):
|
||||
"""
|
||||
game = await self._get_game(ctx, game_code)
|
||||
if not game:
|
||||
await ctx.send("Failed to start a new game")
|
||||
await ctx.maybe_send_embed("Failed to start a new game")
|
||||
else:
|
||||
await ctx.send("Game is ready to join! Use `[p]ww join`")
|
||||
await ctx.maybe_send_embed("Game is ready to join! Use `[p]ww join`")
|
||||
|
||||
@commands.guild_only()
|
||||
@ww.command(name="join")
|
||||
@ -195,10 +195,27 @@ class Werewolf(Cog):
|
||||
game: Game = await self._get_game(ctx)
|
||||
|
||||
if not game:
|
||||
await ctx.send("No game to join!\nCreate a new one with `[p]ww new`")
|
||||
await ctx.maybe_send_embed("Failed to join a game!")
|
||||
return
|
||||
|
||||
await game.join(ctx.author, ctx.channel)
|
||||
await game.join(ctx, ctx.author)
|
||||
await ctx.tick()
|
||||
|
||||
@commands.guild_only()
|
||||
@commands.admin()
|
||||
@ww.command(name="forcejoin")
|
||||
async def ww_forcejoin(self, ctx: commands.Context, target: discord.Member):
|
||||
"""
|
||||
Force someone to join a game of Werewolf
|
||||
"""
|
||||
|
||||
game: Game = await self._get_game(ctx)
|
||||
|
||||
if not game:
|
||||
await ctx.maybe_send_embed("Failed to join a game!")
|
||||
return
|
||||
|
||||
await game.join(ctx, target)
|
||||
await ctx.tick()
|
||||
|
||||
@commands.guild_only()
|
||||
@ -213,7 +230,7 @@ class Werewolf(Cog):
|
||||
game = await self._get_game(ctx)
|
||||
|
||||
if not game:
|
||||
await ctx.send("No game to join!\nCreate a new one with `[p]ww new`")
|
||||
await ctx.maybe_send_embed("No game to join!\nCreate a new one with `[p]ww new`")
|
||||
return
|
||||
|
||||
await game.set_code(ctx, code)
|
||||
@ -239,7 +256,7 @@ class Werewolf(Cog):
|
||||
"""
|
||||
game = await self._get_game(ctx)
|
||||
if not game:
|
||||
await ctx.send("No game running, cannot start")
|
||||
await ctx.maybe_send_embed("No game running, cannot start")
|
||||
|
||||
if not await game.setup(ctx):
|
||||
pass # ToDo something?
|
||||
@ -257,13 +274,13 @@ class Werewolf(Cog):
|
||||
# await ctx.send("Cannot stop game from PM!")
|
||||
# return
|
||||
if ctx.guild.id not in self.games or self.games[ctx.guild.id].game_over:
|
||||
await ctx.send("No game to stop")
|
||||
await ctx.maybe_send_embed("No game to stop")
|
||||
return
|
||||
|
||||
game = await self._get_game(ctx)
|
||||
game.game_over = True
|
||||
await game.current_action.cancel()
|
||||
await ctx.send("Game has been stopped")
|
||||
await ctx.maybe_send_embed("Game has been stopped")
|
||||
|
||||
@commands.guild_only()
|
||||
@ww.command(name="vote")
|
||||
@ -277,7 +294,7 @@ class Werewolf(Cog):
|
||||
target_id = None
|
||||
|
||||
if target_id is None:
|
||||
await ctx.send("`id` must be an integer")
|
||||
await ctx.maybe_send_embed("`id` must be an integer")
|
||||
return
|
||||
|
||||
# if ctx.guild is None:
|
||||
@ -294,7 +311,7 @@ class Werewolf(Cog):
|
||||
game = await self._get_game(ctx)
|
||||
|
||||
if game is None:
|
||||
await ctx.send("No game running, cannot vote")
|
||||
await ctx.maybe_send_embed("No game running, cannot vote")
|
||||
return
|
||||
|
||||
# Game handles response now
|
||||
@ -304,7 +321,7 @@ class Werewolf(Cog):
|
||||
elif channel in (c["channel"] for c in game.p_channels.values()):
|
||||
await game.vote(ctx.author, target_id, channel)
|
||||
else:
|
||||
await ctx.send("Nothing to vote for in this channel")
|
||||
await ctx.maybe_send_embed("Nothing to vote for in this channel")
|
||||
|
||||
@ww.command(name="choose")
|
||||
async def ww_choose(self, ctx: commands.Context, data):
|
||||
@ -315,7 +332,7 @@ class Werewolf(Cog):
|
||||
"""
|
||||
|
||||
if ctx.guild is not None:
|
||||
await ctx.send("This action is only available in DM's")
|
||||
await ctx.maybe_send_embed("This action is only available in DM's")
|
||||
return
|
||||
# DM nonsense, find their game
|
||||
# If multiple games, panic
|
||||
@ -323,7 +340,7 @@ class Werewolf(Cog):
|
||||
if await game.get_player_by_member(ctx.author):
|
||||
break # game = game
|
||||
else:
|
||||
await ctx.send("You're not part of any werewolf game")
|
||||
await ctx.maybe_send_embed("You're not part of any werewolf game")
|
||||
return
|
||||
|
||||
await game.choose(ctx, data)
|
||||
@ -344,7 +361,7 @@ class Werewolf(Cog):
|
||||
if from_name:
|
||||
await menu(ctx, from_name, DEFAULT_CONTROLS)
|
||||
else:
|
||||
await ctx.send("No roles containing that name were found")
|
||||
await ctx.maybe_send_embed("No roles containing that name were found")
|
||||
|
||||
@ww_search.command(name="alignment")
|
||||
async def ww_search_alignment(self, ctx: commands.Context, alignment: int):
|
||||
@ -354,7 +371,7 @@ class Werewolf(Cog):
|
||||
if from_alignment:
|
||||
await menu(ctx, from_alignment, DEFAULT_CONTROLS)
|
||||
else:
|
||||
await ctx.send("No roles with that alignment were found")
|
||||
await ctx.maybe_send_embed("No roles with that alignment were found")
|
||||
|
||||
@ww_search.command(name="category")
|
||||
async def ww_search_category(self, ctx: commands.Context, category: int):
|
||||
@ -364,7 +381,7 @@ class Werewolf(Cog):
|
||||
if pages:
|
||||
await menu(ctx, pages, DEFAULT_CONTROLS)
|
||||
else:
|
||||
await ctx.send("No roles in that category were found")
|
||||
await ctx.maybe_send_embed("No roles in that category were found")
|
||||
|
||||
@ww_search.command(name="index")
|
||||
async def ww_search_index(self, ctx: commands.Context, idx: int):
|
||||
@ -374,23 +391,29 @@ class Werewolf(Cog):
|
||||
if idx_embed is not None:
|
||||
await ctx.send(embed=idx_embed)
|
||||
else:
|
||||
await ctx.send("Role ID not found")
|
||||
await ctx.maybe_send_embed("Role ID not found")
|
||||
|
||||
async def _get_game(self, ctx: commands.Context, game_code=None) -> Union[Game, None]:
|
||||
guild: discord.Guild = getattr(ctx, "guild", None)
|
||||
|
||||
if guild is None:
|
||||
# Private message, can't get guild
|
||||
await ctx.send("Cannot start game from DM!")
|
||||
await ctx.maybe_send_embed("Cannot start game from DM!")
|
||||
return None
|
||||
if guild.id not in self.games or self.games[guild.id].game_over:
|
||||
await ctx.send("Starting a new game...")
|
||||
await ctx.maybe_send_embed("Starting a new game...")
|
||||
valid, role, category, channel, log_channel = await self._get_settings(ctx)
|
||||
|
||||
if not valid:
|
||||
await ctx.send("Cannot start a new game")
|
||||
await ctx.maybe_send_embed("Cannot start a new game")
|
||||
return None
|
||||
|
||||
who_has_the_role = await anyone_has_role(guild.members, role)
|
||||
if who_has_the_role:
|
||||
await ctx.maybe_send_embed(
|
||||
f"Cannot continue, {who_has_the_role.display_name} already has the game role."
|
||||
)
|
||||
return None
|
||||
self.games[guild.id] = Game(
|
||||
self.bot, guild, role, category, channel, log_channel, game_code
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user