Compare commits

...

3 Commits

Author SHA1 Message Date
bobloy 0250a297e1 Better message
4 years ago
bobloy 711c83ddbb Enable configurable day/night lengths
4 years ago
bobloy 4523ffc98d Adjustments to setup
4 years ago

@ -62,6 +62,8 @@ class Game:
village: discord.TextChannel = None, village: discord.TextChannel = None,
log_channel: discord.TextChannel = None, log_channel: discord.TextChannel = None,
game_code=None, game_code=None,
day_length=HALF_DAY_LENGTH * 2,
night_length=HALF_NIGHT_LENGTH * 2,
): ):
self.bot = bot self.bot = bot
self.guild = guild self.guild = guild
@ -73,6 +75,9 @@ class Game:
self.day_vote = {} # author: target self.day_vote = {} # author: target
self.vote_totals = {} # id: total_votes self.vote_totals = {} # id: total_votes
self.half_day_length = day_length // 2
self.half_night_length = night_length // 2
self.started = False self.started = False
self.game_over = False self.game_over = False
self.any_votes_remaining = False self.any_votes_remaining = False
@ -97,6 +102,7 @@ class Game:
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
self.cycle_task = None
self.action_queue = deque() self.action_queue = deque()
self.current_action = None self.current_action = None
self.listeners = {} self.listeners = {}
@ -116,6 +122,13 @@ class Game:
# for c_data in self.p_channels.values(): # for c_data in self.p_channels.values():
# asyncio.ensure_future(c_data["channel"].delete("Werewolf game-over")) # asyncio.ensure_future(c_data["channel"].delete("Werewolf game-over"))
def _prestart_status(self, ctx):
return (
f"Currently **{len(self.players)} / {len(self.roles)}**\n"
f"Use `{ctx.prefix}ww code` to pick a game setup\n"
f"Use `{ctx.prefix}buildgame` to generate a new game"
)
async def setup(self, ctx: commands.Context): async def setup(self, ctx: commands.Context):
""" """
Runs the initial setup Runs the initial setup
@ -127,15 +140,20 @@ class Game:
4. Start game 4. Start game
""" """
if self.game_code: if self.game_code:
# Turn random roles into real roles
await self.get_roles(ctx) await self.get_roles(ctx)
else:
await ctx.maybe_send_embed(
f"No game code has been assigned, cannot start\n{self._prestart_status(ctx)}"
)
return False
if len(self.players) != len(self.roles): if len(self.players) != len(self.roles):
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
f"Player count does not match role count, cannot start\n" f"Player count does not match role count, cannot start\n"
f"Currently **{len(self.players)} / {len(self.roles)}**\n" f"{self._prestart_status(ctx)}"
f"Use `{ctx.prefix}ww code` to pick a game setup\n"
f"Use `{ctx.prefix}buildgame` to generate a new game"
) )
# Clear the roles to be randomly generated again
self.roles = [] self.roles = []
return False return False
@ -156,6 +174,7 @@ class Game:
self.roles = [] self.roles = []
return False return False
# Check if the role is already in use. If so, cannot continue until removed
anyone_with_role = await anyone_has_role(self.guild.members, self.game_role) anyone_with_role = await anyone_has_role(self.guild.members, self.game_role)
if anyone_with_role is not None: if anyone_with_role is not None:
await ctx.maybe_send_embed( await ctx.maybe_send_embed(
@ -164,6 +183,7 @@ class Game:
) )
return False return False
# Add the game role to those who are playing
try: try:
for player in self.players: for player in self.players:
await player.member.add_roles(*[self.game_role]) await player.member.add_roles(*[self.game_role])
@ -175,6 +195,7 @@ class Game:
) )
return False return False
# Randomly assign the roles in the game to the players
await self.assign_roles() await self.assign_roles()
# Create category and channel with individual overwrites # Create category and channel with individual overwrites
@ -219,14 +240,16 @@ class Game:
return False return False
else: else:
self.save_perms[self.village_channel] = self.village_channel.overwrites self.save_perms[self.village_channel] = self.village_channel.overwrites
try:
await self.village_channel.edit( # Disable renaming channels, too easy to get rate limited.
name="🔵werewolf", # try:
reason="(BOT) New game of werewolf", # await self.village_channel.edit(
) # name="🔵werewolf",
except discord.Forbidden as e: # reason="(BOT) New game of werewolf",
log.exception("Unable to rename Game Channel") # )
await ctx.maybe_send_embed("Unable to rename Game Channel, ignoring") # except discord.Forbidden as e:
# log.exception("Unable to rename Game Channel")
# await ctx.maybe_send_embed("Unable to rename Game Channel, ignoring")
try: try:
for target, ow in overwrite.items(): for target, ow in overwrite.items():
@ -283,9 +306,9 @@ class Game:
self.vote_groups[channel_id] = vote_group self.vote_groups[channel_id] = vote_group
log.debug("Pre-cycle") log.debug("Pre-cycle")
await asyncio.sleep(0) await asyncio.sleep(0) # Pass back to controller to avoid heartbeat issues
asyncio.create_task(self._cycle()) # Start the loop self.cycle_task = asyncio.create_task(self._cycle()) # Start the loop
return True return True
# ###########START Notify structure############ # ###########START Notify structure############
@ -360,13 +383,15 @@ class Game:
self.any_votes_remaining = True self.any_votes_remaining = True
# Now we sleep and let the day happen. Print the remaining daylight half way through # Now we sleep and let the day happen. Print the remaining daylight half way through
await asyncio.sleep(HALF_DAY_LENGTH) # 4 minute days FixMe to 120 later await asyncio.sleep(self.half_day_length)
if check(): if check():
return return
await self.village_channel.send( await self.village_channel.send(
embed=discord.Embed(title=f"*{HALF_DAY_LENGTH / 60} minutes of daylight remain...*") embed=discord.Embed(
title=f"*{self.half_day_length/ 60} minutes of daylight remain...*"
)
) )
await asyncio.sleep(HALF_DAY_LENGTH) # 4 minute days FixMe to 120 later await asyncio.sleep(self.half_day_length)
# Need a loop here to wait for trial to end # Need a loop here to wait for trial to end
while self.ongoing_vote: while self.ongoing_vote:
@ -501,13 +526,13 @@ class Game:
await self._notify("at_night_start") await self._notify("at_night_start")
await asyncio.sleep(HALF_NIGHT_LENGTH) # 2 minutes FixMe to 120 later await asyncio.sleep(self.half_night_length)
await self.village_channel.send( await self.village_channel.send(
embed=discord.Embed(title=f"**{HALF_NIGHT_LENGTH / 60} minutes of night remain...**") embed=discord.Embed(
title=f"**{self.half_night_length / 60} minutes of night remain...**"
) )
await asyncio.sleep(HALF_NIGHT_LENGTH) # 1.5 minutes FixMe to 90 later )
await asyncio.sleep(self.half_night_length)
await asyncio.sleep(3) # .5 minutes FixMe to 30 Later
self.action_queue.append(self._at_night_end()) self.action_queue.append(self._at_night_end())
@ -553,7 +578,7 @@ class Game:
# ###########END Notify structure############ # ###########END Notify structure############
async def generate_targets(self, channel, with_roles=False): async def generate_targets(self, channel, with_roles=False):
embed = discord.Embed(title="Remaining Players", description="[ID] - [Name]") embed = discord.Embed(title="Remaining Players", description="ID || Name")
for i, player in enumerate(self.players): for i, player in enumerate(self.players):
if player.alive: if player.alive:
status = "" status = ""
@ -561,13 +586,15 @@ class Game:
status = "*[Dead]*-" status = "*[Dead]*-"
if with_roles or not player.alive: if with_roles or not player.alive:
embed.add_field( embed.add_field(
name=f"{i} - {status}{player.member.display_name}", name=f"{i} || {status}{player.member.display_name}",
value=f"{player.role}", value=f"{player.role}",
inline=False, inline=False,
) )
else: else:
embed.add_field( embed.add_field(
name=f"{i} - {status}{player.member.display_name}", inline=False, value="____" name=f"{i} || {status}{player.member.display_name}",
inline=False,
value="\N{Zero Width Space}",
) )
return await channel.send(embed=embed) return await channel.send(embed=embed)
@ -859,7 +886,7 @@ class Game:
self.players.sort(key=lambda pl: pl.member.display_name.lower()) self.players.sort(key=lambda pl: pl.member.display_name.lower())
if len(self.roles) != len(self.players): if len(self.roles) != len(self.players):
await self.village_channel.send("Unhandled error - roles!=players") await self.village_channel.send("Unhandled error - roles != # players")
return False return False
for idx, role in enumerate(self.roles): for idx, role in enumerate(self.roles):

@ -36,6 +36,7 @@ class Werewolf(Cog):
"category_id": None, "category_id": None,
"channel_id": None, "channel_id": None,
"log_channel_id": None, "log_channel_id": None,
"default_game": {"daytime": 60 * 5, "nighttime": 60 * 5},
} }
self.config.register_global(**default_global) self.config.register_global(**default_global)
@ -398,12 +399,13 @@ class Werewolf(Cog):
# Private message, can't get guild # Private message, can't get guild
await ctx.maybe_send_embed("Cannot start game from DM!") await ctx.maybe_send_embed("Cannot start game from DM!")
return None return None
if guild.id not in self.games or self.games[guild.id].game_over: if guild.id not in self.games or self.games[guild.id].game_over:
await ctx.maybe_send_embed("Starting a new game...") await ctx.maybe_send_embed("Starting a new game...")
valid, role, category, channel, log_channel = await self._get_settings(ctx) valid, role, category, channel, log_channel = await self._get_settings(ctx)
if not valid: if not valid:
await ctx.maybe_send_embed("Cannot start a new game") await ctx.maybe_send_embed("Cannot start a new game, check server settings.")
return None return None
who_has_the_role = await anyone_has_role(guild.members, role) who_has_the_role = await anyone_has_role(guild.members, role)
@ -413,7 +415,15 @@ class Werewolf(Cog):
) )
return None return None
self.games[guild.id] = Game( self.games[guild.id] = Game(
self.bot, guild, role, category, channel, log_channel, game_code bot=self.bot,
guild=guild,
role=role,
category=category,
village=channel,
log_channel=log_channel,
game_code=game_code,
day_length=await self.config.guild(guild).default_game.day_length(),
night_length=await self.config.guild(guild).default_game.night_length(),
) )
return self.games[guild.id] return self.games[guild.id]

Loading…
Cancel
Save