[RequirePermissions(Permissions.ManageRoles)] // and restrict this to users who have appropriate permissions public async Task WaitForCode(CommandContext ctx) { // first retrieve the interactivity module from the client InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); // generate a code byte[] codebytes = new byte[8]; using (RandomNumberGenerator rng = RandomNumberGenerator.Create()) { rng.GetBytes(codebytes); } string code = BitConverter.ToString(codebytes).ToLower().Replace("-", ""); // announce the code await ctx.RespondAsync($"The first one to type the following code gets a reward: `{code}`"); // wait for anyone who types it MessageContext msg = await interactivity.WaitForMessageAsync(xm => xm.Content.Contains(code), TimeSpan.FromSeconds(60)); if (msg != null) { // announce the winner await ctx.RespondAsync($"And the winner is: {msg.Message.Author.Mention}"); } else { await ctx.RespondAsync("Nobody? Really?"); } }
public async Task BeepMessage(CommandContext ctx) { InteractivityModule interact = ctx.Client.GetInteractivityModule(); await ctx.RespondAsync("What kinds of Boops would you like?"); await ctx.RespondAsync("1: Boop"); await ctx.RespondAsync("2: Bop"); var response = await interact.WaitForMessageAsync(x => x.Author == ctx.Message.Author, TimeSpan.FromMinutes(1)); if (response == null) { await ctx.RespondAsync("No Boops for u!"); } switch (response.Message.Content) { case "1": await ctx.RespondAsync("Boop"); break; case "2": await ctx.RespondAsync("Bop"); break; default: await ctx.RespondAsync("No"); break; } //await ctx.RespondAsync("Boop"); }
private async Task <GameValue> PlayGame(CommandContext ctx, InteractivityModule interactivity) { var board = new GameValue[9]; var emptySlots = Enumerable.Range(0, 9).ToList(); var myTurn = StaticRandom.Next(2) == 1; GameValue winner = GameValue.Empty; if (!myTurn) { await ctx.RespondAsync($"You are the one starting!"); } while ((winner = GetWinner(board)) == GameValue.Empty) { if (myTurn) { await ctx.TriggerTypingAsync(); var nextSlot = StaticRandom.Next(0, emptySlots.Count); board[emptySlots[nextSlot]] = GameValue.Bot; await ctx.RespondAsync($"{emptySlots[nextSlot] % 3 + 1}:{emptySlots[nextSlot] / 3 + 1}"); emptySlots.RemoveAt(nextSlot); } else { var response = await interactivity.WaitForMessageAsync(message => message.Author.Id == ctx.User.Id && message.Channel.IsPrivate, TimeSpan.FromSeconds(1.0)); if (response == null) { return(GameValue.Timeout); } var messageParts = response.Message.Content.Split(':'); if (messageParts.Length == 2 && int.TryParse(messageParts[0], out var x) && int.TryParse(messageParts[1], out var y) && x >= 1 && x <= 3 && y >= 1 && y <= 3) { var nextSlot = (y - 1) * 3 + (x - 1); if (emptySlots.Contains(nextSlot)) { board[nextSlot] = GameValue.Player; emptySlots.Remove(nextSlot); } else { return(GameValue.IncorrectInput); } } else { return(GameValue.IncorrectInput); } } myTurn = !myTurn; } return(winner); }
public async Task Score(CommandContext ctx) { Set playerSet = Matchmaker.Sets.FirstOrDefault(e => e.AllPlayers.Any(f => f.DiscordId == ctx.User.Id)); DiscordRole modRole = ctx.Guild.Roles.First(e => e.Name == "Moderator"); if (playerSet == null) { return; } if (playerSet.DraftPlayers.Any()) { return; } if (playerSet.BravoTeam.Score > SET_MATCH_NUMBER / 2 || playerSet.AlphaTeam.Score > SET_MATCH_NUMBER / 2) { return; } if (playerSet.Locked) { await ctx.RespondAsync("This set will be locked until a moderator addresses the report. Please wait."); return; } if (playerSet.ResolveMode > 0) { return; } if (ctx.Channel.Id != (await CommandHelper.ChannelFromSet(playerSet.SetNumber)).Id) { return; } if (!playerSet.AlphaTeam.IsCaptain(ctx.User.Id) && !playerSet.BravoTeam.IsCaptain(ctx.User.Id)) { await ctx.RespondAsync("Only the captain of the losing team can report the score."); return; } string team = playerSet.AlphaTeam.IsCaptain(ctx.User.Id) ? "bravo" : "alpha"; playerSet.ReportScore(team); if (playerSet.AlphaTeam.Score > SET_MATCH_NUMBER / 2 || playerSet.BravoTeam.Score > SET_MATCH_NUMBER / 2 || playerSet.MatchNum == SET_MATCH_NUMBER) { string winner = playerSet.AlphaTeam.Score > playerSet.BravoTeam.Score ? "Alpha" : "Bravo"; string loser = playerSet.AlphaTeam.Score < playerSet.BravoTeam.Score ? "Alpha" : "Bravo"; DiscordEmbedBuilder builder = new DiscordEmbedBuilder(); builder.WithTitle("__Results__"); builder.AddField(e => { e.Name = "Score"; e.IsInline = true; e.Value = $"{winner} Wins {playerSet.AlphaTeam.Score} - {playerSet.BravoTeam.Score}"; }); await ctx.RespondAsync($"The winner of this set is Team {winner}!", embed : builder.Build()); DiscordRole loserRole = loser == "Alpha" ? ctx.Guild.Roles.First(e => e.Name == $"Alpha ({playerSet.SetNumber})") : ctx.Guild.Roles.First(e => e.Name == $"Bravo ({playerSet.SetNumber})"); await ctx.RespondAsync( $"{loserRole.Mention}, please acknowledge these results by either sending \"confirm\" or \"deny\"."); InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); DateTime timeoutDateTime = DateTime.Now + TimeSpan.FromMinutes(2); MessageContext replyMessage; try { replyMessage = await interactivity.WaitForMessageAsync(x => { return(((DiscordMember)x.Author).Roles.Select(e => e.Id).Contains(loserRole.Id)); }, TimeSpan.FromMinutes(1)); } catch (Exception e) { Console.WriteLine(e); Logger.Error(e); throw; } while (true) { if (replyMessage.Message == null) { await ctx.RespondAsync("Time's up! Assuming the losing team has accepted their loss."); await this.EndMatchAsync(playerSet, ctx); return; } if (replyMessage.Message.Content.ToLower() == "confirm") { await this.EndMatchAsync(playerSet, ctx); return; } if (replyMessage.Message.Content.ToLower() == "deny") { await ctx.RespondAsync($"{modRole.Mention} issue reported by {replyMessage.Message.Author.Mention}. " + $"To resolve the error, use `%resolve` and follow the resulting instructions." + $" Otherwise, use `%resolve deny` to continue reporting the current score."); return; } TimeSpan timeSpan = timeoutDateTime - DateTime.Now; if (timeSpan <= TimeSpan.Zero) { await ctx.RespondAsync("Time's up! Assuming the losing team has accepted their loss."); await this.EndMatchAsync(playerSet, ctx); return; } replyMessage = await interactivity.WaitForMessageAsync(x => { return(((DiscordMember)x.Author).Roles.Select(e => e.Id).Contains(loserRole.Id)); }, timeSpan); } } else { try { playerSet.MatchNum++; Stage selectedStage = playerSet.GetCurrentStage(); await ctx.RespondAsync(embed : selectedStage .GetEmbedBuilder($"Match {playerSet.MatchNum} of 7: {selectedStage.MapName}") .AddField(e => { e.Name = "Alpha Team's Score"; e.Value = playerSet.AlphaTeam.Score; e.IsInline = true; }) .AddField(e => { e.Name = "Bravo Team's Score"; e.Value = playerSet.BravoTeam.Score; e.IsInline = true; }) .Build()); DiscordMessage feedMessage = (DiscordMessage)await ctx.Guild.GetChannel(666563839646760960).GetMessageAsync(OrderedFeedMessages[playerSet.SetNumber - 1]); await feedMessage.ModifyAsync(embed : playerSet.GetFeedEmbedBuilder(ctx.Channel).Build()); } catch (Exception e) { Console.WriteLine(e); throw; } } }
public async Task Overwrite(CommandContext ctx, string team, int set = 0) { Set selectedSet; DiscordRole modRole = ctx.Guild.Roles.First(e => e.Name == "Moderator"); if (set == 0) { selectedSet = CommandHelper.SetFromChannel(ctx.Channel.Id); if (selectedSet == null) { await ctx.RespondAsync("Please specify set number or use the correct channel as context."); return; } if (selectedSet.ResolveMode <= 0) { // Force report score by moderator. selectedSet.ReportScore(team); if (selectedSet.AlphaTeam.Score > SET_MATCH_NUMBER / 2 || selectedSet.BravoTeam.Score > SET_MATCH_NUMBER / 2 || selectedSet.MatchNum == SET_MATCH_NUMBER) { string winner = selectedSet.AlphaTeam.Score > selectedSet.BravoTeam.Score ? "Alpha" : "Bravo"; string loser = selectedSet.AlphaTeam.Score < selectedSet.BravoTeam.Score ? "Alpha" : "Bravo"; DiscordEmbedBuilder builder = new DiscordEmbedBuilder(); builder.WithTitle("__Results__"); builder.AddField(e => { e.Name = "Score"; e.IsInline = true; e.Value = $"{winner} Wins {selectedSet.AlphaTeam.Score} - {selectedSet.BravoTeam.Score}"; }); await ctx.RespondAsync($"The winner of this set is Team {winner}!", embed : builder.Build()); DiscordRole loserRole = loser == "Alpha" ? ctx.Guild.Roles.First(e => e.Name == $"Alpha ({selectedSet.SetNumber})") : ctx.Guild.Roles.First(e => e.Name == $"Bravo ({selectedSet.SetNumber})"); await ctx.RespondAsync( $"{loserRole.Mention}, please acknowledge these results by either sending \"confirm\" or \"deny\"."); InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); DateTime timeoutDateTime = DateTime.Now + TimeSpan.FromMinutes(2); MessageContext replyMessage; try { replyMessage = await interactivity.WaitForMessageAsync(x => { return(((DiscordMember)x.Author).Roles.Select(e => e.Id).Contains(loserRole.Id)); }, TimeSpan.FromMinutes(1)); } catch (Exception e) { Console.WriteLine(e); Logger.Error(e); throw; } while (true) { if (replyMessage.Message == null) { await ctx.RespondAsync("Time's up! Assuming the losing team has accepted their loss."); await this.EndMatchAsync(selectedSet, ctx); return; } if (replyMessage.Message.Content.ToLower() == "confirm") { await this.EndMatchAsync(selectedSet, ctx); return; } if (replyMessage.Message.Content.ToLower() == "deny") { await ctx.RespondAsync($"{modRole.Mention} issue reported by {replyMessage.Message.Author.Mention}. " + $"To resolve the error, use `%resolve` and follow the resulting instructions." + $" Otherwise, use `%resolve deny` to continue reporting the current score."); return; } replyMessage = await interactivity.WaitForMessageAsync(x => { return(((DiscordMember)x.Author).Roles.Select(e => e.Id).Contains(loserRole.Id)); }, timeoutDateTime - DateTime.Now); } } else { try { selectedSet.MatchNum++; Stage selectedStage = selectedSet.GetCurrentStage(); await ctx.RespondAsync(embed : selectedStage .GetEmbedBuilder($"Match {selectedSet.MatchNum} of 7: {selectedStage.MapName}") .AddField(e => { e.Name = "Alpha Team's Score"; e.Value = selectedSet.AlphaTeam.Score; e.IsInline = true; }) .AddField(e => { e.Name = "Bravo Team's Score"; e.Value = selectedSet.BravoTeam.Score; e.IsInline = true; }) .Build()); DiscordMessage feedMessage = (DiscordMessage)await ctx.Guild.GetChannel(666563839646760960).GetMessageAsync(OrderedFeedMessages[selectedSet.SetNumber - 1]); await feedMessage.ModifyAsync(embed : selectedSet.GetFeedEmbedBuilder(ctx.Channel).Build()); } catch (Exception e) { Console.WriteLine(e); throw; } } return; // End force report logic. } } else { selectedSet = Matchmaker.Sets[set - 1]; } team = team.ToLower(); selectedSet.ReportScore(team); selectedSet.MatchNum++; selectedSet.ResolveMode--; if (selectedSet.ResolveMode == 0) { if (selectedSet.AlphaTeam.Score > SET_MATCH_NUMBER / 2 || selectedSet.BravoTeam.Score > SET_MATCH_NUMBER / 2 || selectedSet.MatchNum == SET_MATCH_NUMBER) { await ctx.RespondAsync("Resolved all issues! All scores will be reported to Airtable."); await this.EndMatchAsync(selectedSet, ctx); } else { await ctx.RespondAsync("Resolved all issues! Teams, continue with your matches."); selectedSet.MatchNum++; Stage selectedStage = selectedSet.Stages[selectedSet.MatchNum - 1]; await ctx.RespondAsync(embed : selectedStage .GetEmbedBuilder($"Match {selectedSet.MatchNum} of 7: {selectedStage.MapName}") .AddField(e => { e.Name = "Alpha Team's Score"; e.Value = selectedSet.AlphaTeam.Score; e.IsInline = true; }) .AddField(e => { e.Name = "Bravo Team's Score"; e.Value = selectedSet.BravoTeam.Score; e.IsInline = true; }) .Build()); DiscordMessage feedMessage = await ctx.Guild.GetChannel(666563839646760960).GetMessageAsync(OrderedFeedMessages[selectedSet.SetNumber - 1]); await feedMessage.ModifyAsync(embed : selectedSet.GetFeedEmbedBuilder(ctx.Channel).Build()); } } else { Stage selectedStage = selectedSet.Stages[selectedSet.MatchNum]; await ctx.RespondAsync("Moderator, use `%overwrite [Team]` to select the winner for this map.", embed : selectedStage.GetEmbedBuilder($"Match {selectedSet.MatchNum + 1} of 7: {selectedStage.MapName}") .AddField(e => { e.Name = "Alpha Team's Score"; e.Value = selectedSet.AlphaTeam.Score; e.IsInline = true; }) .AddField(e => { e.Name = "Bravo Team's Score"; e.Value = selectedSet.BravoTeam.Score; e.IsInline = true; }) .Build()); } }
public async Task MoveCommand(CommandContext ctx, string direction) { //Vérification de base character + guild if (!dep.Entities.Characters.IsPresent(ctx.User.Id) || (!ctx.Channel.IsPrivate) && !dep.Entities.Guilds.IsPresent(ctx.Guild.Id)) { return; } InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); //Si direction indiqué n'est pas reconnu, on redemande tant que résultat pas bon if (GetDirection(direction) == Direction.Unknown) { do { DiscordEmbedBuilder embedErrorDirection = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("errorDirection")); await ctx.RespondAsync(embed : embedErrorDirection); MessageContext msgDirection = await interactivity.WaitForMessageAsync(xm => xm.Author.Id == ctx.User.Id && xm.ChannelId == ctx.Channel.Id, TimeSpan.FromMinutes(1)); if (msgDirection != null) { //La réponse est une nouvelle commande, on oublie celle là if (msgDirection.Message.Content.StartsWith(Config.Instance.Prefix)) { return; } //Sinon on retest la validité else { direction = msgDirection.Message.Content; } } } while (GetDirection(direction) == Direction.Unknown); } Character character = dep.Entities.Characters.GetCharacterByDiscordId(ctx.User.Id); Region currentRegion = dep.Entities.Map.GetRegionByLocation(character.Location); Location newLocation = GetNewLocation(GetDirection(direction), character.Location); //Region non découverte => Nouvelle génération if (dep.Entities.Map.GetRegionByLocation(newLocation) == null) { //Type aléatoire, la région généré ne sera pas forcément valide pour un village Region r = new Region { Type = dep.Entities.Map.GetRandomRegionType() }; //Choix du nom de la région, demander tant qu'il n'est pas valide DiscordEmbedBuilder embedChooseName = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("introductionChooseName", region: r)); await ctx.RespondAsync(embed : embedChooseName); string regionName = ""; bool nameValid = false; do { MessageContext msgGuildName = await interactivity.WaitForMessageAsync( xm => xm.Author.Id == ctx.User.Id && xm.ChannelId == ctx.Channel.Id, TimeSpan.FromMinutes(1)); if (msgGuildName != null) { //Nouvelle commande, on annule if (msgGuildName.Message.Content.StartsWith(Config.Instance.Prefix)) { return; } else { regionName = msgGuildName.Message.Content; } //Enlever *, ` et _ regionName = dep.Dialog.RemoveMarkdown(regionName); } if (!dep.Entities.Map.IsRegionNameTaken(regionName) && regionName.Length > 3 && regionName.Length <= 50) { nameValid = true; } else { DiscordEmbedBuilder embed = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("regionNameTaken")); await ctx.RespondAsync(embed : embed); } } while (!nameValid); //Calculer la prochine case centrale pour générer la région au bon endroit Location nextMapLoc = dep.Entities.Map.GetCentralCaseByDirection(currentRegion.GetCentralCase(), GetDirection(direction)); //Générer la région avec pour centre nextMapLoc r = dep.Entities.Map.GenerateNewRegion(9, ctx.Guild.Id, regionName, r.Type, nextMapLoc); DiscordEmbedBuilder embedRegionDiscovered = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("regionDiscovered", region: r)); await ctx.RespondAsync(embed : embedRegionDiscovered); } Region newRegion = dep.Entities.Map.GetRegionByLocation(newLocation); Case lastCase = dep.Entities.Map.GetCase(character.Location); Case newCase = newRegion.GetCase(newLocation); //Eau, impossible d'y aller (pour le moment) if (newCase is WaterCase) { DiscordEmbedBuilder embed = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("errorDirectionWater")); await ctx.RespondAsync(embed : embed); return; } //Village, à voir selon le type d'accès else if (newCase is VillageCase) { Village village = dep.Entities.Villages.GetVillageById(newCase.VillageId); //Ne peut pas aller dans le village if (village.VillagePermission == VillagePermission.villagers && character.VillageName != village.Name) { DiscordEmbedBuilder embed = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("errorCanGoToVillage")); await ctx.RespondAsync(embed : embed); return; } //Va dans le village DiscordEmbedBuilder embedEnterVillage = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("enterVillage", village: village)); await ctx.RespondAsync(embed : embedEnterVillage); } else { DiscordEmbedBuilder embedCaseInfo = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("caseInfo", region: newRegion, mCase: newCase), dep.Dialog.GetString("caseInfoDetails")); await ctx.RespondAsync(embed : embedCaseInfo); } //Update location character lastCase.RemoveCharacter(character); newCase.AddNewCharacter(character); character.Location = newLocation; }
public async Task CreateVillageCommand(CommandContext ctx) { //Vérification de base character + guild if (!dep.Entities.Characters.IsPresent(ctx.User.Id) || !dep.Entities.Guilds.IsPresent(ctx.Guild.Id)) { return; } Guild guild = dep.Entities.Guilds.GetGuildById(ctx.Guild.Id); Region region = dep.Entities.Map.GetRegionByName(guild.RegionName); Character character = dep.Entities.Characters.GetCharacterByDiscordId(ctx.User.Id); if (region == null || region.GetVillageId() != ulong.MinValue || !character.Location.Equals(region.GetCentralCase().Location)) { //Region n'appartient pas à un serveur, a déjà un village ou case pas adaptée, impossible de construire ici DiscordEmbedBuilder embedNotPossible = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("createVillageNotPossible", character: character, region: region)); await ctx.RespondAsync(embed : embedNotPossible); return; } Inventory inv = dep.Entities.Inventories.GetInventoryById(character.Id); if (inv.GetMoney() < 500) { //Trop pauvre pour construire un village .. DiscordEmbedBuilder embedNoMoney = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("createVillageNoMoney", character: character)); await ctx.RespondAsync(embed : embedNoMoney); return; } ////////Sinon, on peut envisager la construction ... ! InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); Village village = new Village(); //1 Demander le nom DiscordEmbedBuilder embedVillageName = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("createVillageAskName")); await ctx.RespondAsync(embed : embedVillageName); bool VillageName = false; do { MessageContext msgTrueName = await interactivity.WaitForMessageAsync( xm => xm.Author.Id == ctx.User.Id && xm.ChannelId == ctx.Channel.Id, TimeSpan.FromMinutes(1)); if (msgTrueName != null) { if (msgTrueName.Message.Content.Length <= 50 && !dep.Entities.Villages.IsNameTaken(msgTrueName.Message.Content) && msgTrueName.Message.Content.Length > 2) { village.Name = msgTrueName.Message.Content; village.Name = dep.Dialog.RemoveMarkdown(village.Name); VillageName = true; } else { DiscordEmbedBuilder embedErrorTrueName = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("startIntroTrueTaken")); await ctx.RespondAsync(embed : embedErrorTrueName); } } } while (!VillageName); //2 Nom ok, on créer le village de base village.Id = ctx.Guild.Id; village.RegionName = region.Name; village.KingId = character.Id; //Coût du village retiré au joueur inv.RemoveMoney(500); //250 va dans les caisses du villages, le reste servant à la "contructions" des bâtiments de base Inventory inventory = new VillageInventory(); inventory.AddMoney(250); inventory.Id = village.Id; dep.Entities.Inventories.AddInventory(inventory); //Ajout des bâtiment de base Castle castle = new Castle() { Level = 1, Name = "Castle", ProprietaryId = character.Id }; House house = new House() { Level = 1, Name = "Hut", ProprietaryId = character.Id }; village.AddBuilding(castle); village.AddBuilding(house); //Add the king as inhabitant village.AddInhabitant(character); character.VillageName = village.Name; dep.Entities.Characters.EditCharacter(character); //become king character.Profession = Profession.King; //Village rattaché à la région region.SetVillageId(village.Id); //Case de la région mise en non valable region.GetCentralCase().IsAvailable = false; region.SetCentralCase(CaseFactory.BuildCase("village", region.GetCentralCase().Location)); dep.Entities.Villages.AddVillage(village); //Bravo, village créé DiscordEmbedBuilder embedVillageCreated = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("createVillageDone", character: character, village: village)); await ctx.RespondAsync(embed : embedVillageCreated); }
public async Task TradeCommand(CommandContext ctx, params string[] name) { //Vérification de base character + guild + name fourni if (!dep.Entities.Characters.IsPresent(ctx.User.Id) || !dep.Entities.Guilds.IsPresent(ctx.Guild.Id) || name.Length == 0) { return; } InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); DiscordMemberConverter dmc = new DiscordMemberConverter(); bool tradeIsOver = false; //Nos deux character Character currentCharacter = dep.Entities.Characters.GetCharacterByDiscordId(ctx.User.Id); DiscordDmChannel dmCurrentCharacter = await ctx.Member.CreateDmChannelAsync(); Character otherCharacter; //Récupérer ID 2ème character string strName = string.Join(" ", name); if (dmc.TryConvert(strName, ctx, out DiscordMember member)) { otherCharacter = dep.Entities.Characters.GetCharacterByDiscordId(member.Id); } else { otherCharacter = dep.Entities.Characters.GetCharacterByName(strName); } //Toujours rien ? -> Test par truenae if (otherCharacter == null) { otherCharacter = dep.Entities.Characters.GetCharacterByTrueName(strName); } //Vérification character2 if (otherCharacter == null) { var embedNotFound = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("errorCharacterNotExist")); await ctx.Channel.SendMessageAsync(embed : embedNotFound); return; } //Vérification même location if (!currentCharacter.Location.Equals(otherCharacter.Location)) { var embedNotOnSameCase = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("errorCharacterNotOnSameMapForTrade")); await ctx.Channel.SendMessageAsync(embed : embedNotOnSameCase); return; } var embedWaitingAnswer = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("waitingAnswer", otherCharacter)); await ctx.Channel.SendMessageAsync(embed : embedWaitingAnswer); //Les deux inventaires Inventory invC1 = dep.Entities.Inventories.GetInventoryById(currentCharacter.Id); Inventory invC2 = dep.Entities.Inventories.GetInventoryById(otherCharacter.Id); //Liste des items à échanger List <GameObject> itemFromC1 = new List <GameObject>(); List <GameObject> itemFromC2 = new List <GameObject>(); var applicantDiscordMember = await ctx.Client.GetUserAsync(otherCharacter.Id); DiscordDmChannel dmOtherCharacter = await ctx.Client.CreateDmAsync(applicantDiscordMember); var embedProposeTrade = dep.Embed.CreateBasicEmbed(applicantDiscordMember, $"{currentCharacter.Name} want to trade with you ! Type {Config.Instance.Prefix}accept to start the trade."); await dmOtherCharacter.SendMessageAsync(embed : embedProposeTrade); //1 Attendre que member accepte le trade MessageContext msgAccept = await interactivity.WaitForMessageAsync(xm => xm.Author.Id == otherCharacter.Id && xm.Content == $"{Config.Instance.Prefix}accept", TimeSpan.FromMinutes(1)); if (msgAccept != null) { if (msgAccept.Message.Content != $"{Config.Instance.Prefix}accept") { return; } } //Accepté, on montre l'embed d'échange en MP aux 2 DiscordEmbedBuilder tradeEmbed = GetTradeEmbed(ctx, currentCharacter.Name, otherCharacter.Name, itemFromC1, itemFromC2); //Message d'aide DiscordMessage msg1 = await dmCurrentCharacter.SendMessageAsync(embed : tradeEmbed); DiscordMessage msg2 = await dmOtherCharacter.SendMessageAsync(embed : tradeEmbed); bool tradeC1Confirmed = false; bool tradeC2Confirmed = false; bool tradeC1Canceled = false; bool tradeC2Canceled = false; while (!tradeIsOver) { //Attendre message d'un des deux dans le DM MessageContext tradeMsg = await interactivity.WaitForMessageAsync(xm => (xm.Author.Id == currentCharacter.Id && xm.ChannelId == dmCurrentCharacter.Id) || (xm.Author.Id == otherCharacter.Id && xm.ChannelId == dmOtherCharacter.Id) , TimeSpan.FromSeconds(30)); if (tradeMsg != null) { string msg = tradeMsg.Message.Content; //1 Echange accepté if (msg == $"{Config.Instance.Prefix}confirm") { if (tradeMsg.Message.Author.Id == currentCharacter.Id) { tradeC1Confirmed = true; } else if (tradeMsg.Message.Author.Id == otherCharacter.Id) { tradeC2Confirmed = true; } } // 2 Echangé refusé else if (msg == $"{Config.Instance.Prefix}cancel") { if (tradeMsg.Message.Author.Id == currentCharacter.Id) { tradeC1Confirmed = false; tradeC1Canceled = true; } else if (tradeMsg.Message.Author.Id == otherCharacter.Id) { tradeC2Confirmed = false; tradeC2Canceled = true; } } //3 Ajout d'un item else if (msg.StartsWith($"{Config.Instance.Prefix}add")) { tradeC1Confirmed = false; tradeC2Confirmed = false; //a) Nom de l'objet + quantité string[] objectsToAdd = msg.Split(' '); string itemName = ""; //Prendre quantité et viré de l'array si bien présent string strCount = objectsToAdd.Last(); if (int.TryParse(strCount, out int itemCount)) { objectsToAdd = objectsToAdd.Take(objectsToAdd.Count() - 1).ToArray(); } else { itemCount = 1; } //Remove commands objectsToAdd = objectsToAdd.Skip(1).ToArray(); //reconstruire nom objet for (int i = 0; i < objectsToAdd.Length; i++) { itemName += objectsToAdd[i] + " "; } itemName = itemName.Remove(itemName.Length - 1); //b) on vérifie si le joueur a bien les items en inventaire if (tradeMsg.Message.Author.Id == currentCharacter.Id) { GameObject go = invC1.GetGOAndRemoveFromInventory(itemName, itemCount); if (go != null) { //Si item existe déjà, on additionne les quantité if (itemFromC1.Exists(item => item.Name == go.Name)) { itemFromC1.Single(item => item.Name == go.Name).Quantity += go.Quantity; } else { itemFromC1.Add(go); } } } else if (tradeMsg.Message.Author.Id == otherCharacter.Id) { GameObject go = invC2.GetGOAndRemoveFromInventory(itemName, itemCount); if (go != null) { //Si item existe déjà, on additionne les quantité if (itemFromC2.Exists(item => item.Name == go.Name)) { itemFromC2.Single(item => item.Name == go.Name).Quantity += go.Quantity; } else { itemFromC2.Add(go); } } } } else if (msg.StartsWith($"{Config.Instance.Prefix}remove")) { //a) Nom de l'objet + quantité string[] objectsToAdd = msg.Split(' '); string itemName = ""; //reconstruire nom objet for (int i = 1; i < objectsToAdd.Length; i++) { itemName += objectsToAdd[i] + " "; } itemName = itemName.Remove(itemName.Length - 1); if (tradeMsg.Message.Author.Id == currentCharacter.Id) { if (itemFromC1.Exists(item => item.Name.ToLower() == itemName.ToLower())) { var objectToRemove = itemFromC1.Single(item => item.Name.ToLower() == itemName.ToLower()); itemFromC1.Remove(objectToRemove); invC1.AddItem(objectToRemove); } } else if (tradeMsg.Message.Author.Id == otherCharacter.Id) { if (itemFromC2.Exists(item => item.Name.ToLower() == itemName.ToLower())) { var objectToRemove = itemFromC2.Single(item => item.Name.ToLower() == itemName.ToLower()); itemFromC2.Remove(objectToRemove); invC2.AddItem(objectToRemove); } } } //Fin, on actualise les messages et on édite tradeEmbed = GetTradeEmbed(ctx, currentCharacter.Name, otherCharacter.Name, itemFromC1, itemFromC2, tradeC1Confirmed, tradeC2Confirmed, tradeC1Canceled, tradeC2Canceled); await msg1.ModifyAsync(embed : tradeEmbed); await msg2.ModifyAsync(embed : tradeEmbed); if (tradeC1Canceled || tradeC2Canceled) { await dmCurrentCharacter.SendMessageAsync("Trade has been canceled"); await dmOtherCharacter.SendMessageAsync("Trade has been canceled"); invC1.AddItems(itemFromC1); invC2.AddItems(itemFromC2); tradeIsOver = true; } if (tradeC1Confirmed && tradeC2Confirmed) { await dmCurrentCharacter.SendMessageAsync("Trade has been made"); await dmOtherCharacter.SendMessageAsync("Trade has been made"); invC1.AddItems(itemFromC2); invC2.AddItems(itemFromC1); tradeIsOver = true; } } } await msg1.DeleteAsync(); await msg2.DeleteAsync(); }
public async Task VillageApplicantCommand(CommandContext ctx) { //Vérification de base character + guild + roi if (!dep.Entities.Characters.IsPresent(ctx.User.Id) || (!ctx.Channel.IsPrivate) && !dep.Entities.Guilds.IsPresent(ctx.Guild.Id) || dep.Entities.Characters.GetCharacterByDiscordId(ctx.User.Id).Profession != Profession.King) { return; } InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); var character = dep.Entities.Characters.GetCharacterByDiscordId(ctx.User.Id); var village = dep.Entities.Villages.GetVillageByName(character.VillageName); List <string> waitingCharacter = new List <string>(); foreach (ulong id in village.WaitingList) { var applicant = dep.Entities.Characters.GetCharacterByDiscordId(id); waitingCharacter.Add($"{applicant.Name} - Level {applicant.Level}"); } List <CustomEmbedField> attributes = new List <CustomEmbedField> { //1 Infos général du personnage new CustomEmbedField() { Name = "Inhabitant(s) waiting", Attributes = waitingCharacter } }; string title = $"List of applicants {character.Name}"; string description = $"Type {Config.Instance.Prefix}accept [name] to accept, {Config.Instance.Prefix}refuse [name] to refuse"; DiscordEmbedBuilder embed = dep.Embed.CreateDetailledEmbed(title, attributes, description, inline: true); DiscordDmChannel dm = await ctx.Member.CreateDmChannelAsync(); await dm.SendMessageAsync(embed : embed); await ctx.RespondAsync($"{ctx.Member.Mention} private message sent !"); while (village.WaitingList.Count > 0) { MessageContext msg = await interactivity.WaitForMessageAsync(xm => xm.Channel.Id == dm.Id, TimeSpan.FromMinutes(1)); if (msg != null) { var message = msg.Message.Content.Split(" "); var command = message[0]; message = message.Skip(1).ToArray(); var name = string.Join(" ", message); var applicant = dep.Entities.Characters.GetCharacterByName(name); var applicantDiscordMember = await ctx.Client.GetUserAsync(applicant.Id); var dmApplicant = await ctx.Client.CreateDmAsync(applicantDiscordMember); if (applicant == null) { var embedError = dep.Embed.CreateBasicEmbed(ctx.User, $"{name} was not found among the candidates."); await dm.SendMessageAsync(embed : embedError); } else { if (command == Config.Instance.Prefix + "accept") { //Verifier si pas accepté ailleurs if (applicant.VillageName != null) { var embedErrorVillage = dep.Embed.CreateBasicEmbed(ctx.User, $"{name} is already member of another village"); await dm.SendMessageAsync(embed : embedErrorVillage); } else { village.WaitingList.Remove(applicant.Id); village.AddInhabitant(applicant); applicant.Profession = Profession.Villager; var embedError = dep.Embed.CreateBasicEmbed(ctx.User, $"{name} has been accepted"); await dm.SendMessageAsync(embed : embedError); var embedAccepted = dep.Embed.CreateBasicEmbed(applicantDiscordMember, $"Congratulation, you have been accepted in village {village.Name}!"); await dmApplicant.SendMessageAsync(embed : embedAccepted); } } else if (command == Config.Instance.Prefix + "refuse") { village.WaitingList.Remove(applicant.Id); var embedError = dep.Embed.CreateBasicEmbed(ctx.User, $"{name} has been refused"); await dm.SendMessageAsync(embed : embedError); var embedAccepted = dep.Embed.CreateBasicEmbed(applicantDiscordMember, $"I am sorry to inform you that the village of {village.Name} has declined your candidature."); await dmApplicant.SendMessageAsync(embed : embedAccepted); } } } else { //Quitter la fonction return; } } }
public async Task RegisterGuildCommand(CommandContext ctx) { //Ce serveur discord est déjà enregistré et dispose de sa propre map if (dep.Entities.Guilds.IsPresent(ctx.Guild.Id)) { await ctx.RespondAsync(dep.Dialog.GetString("errorGuildAlreadyRegistered")); return; } InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); string regionName = ""; bool nameValid = false; //Avant de générer une nouvelle map, on regarde si une déjà générée par //l'exploration est disponible Region r = dep.Entities.Map.GetAvailableRegion(); //Pas disponible, génération d'une nouvelle map de type Plain et forcément habitable if (r == null) { r = new Region { Type = RegionType.Plain, Id = ctx.Guild.Id }; //Comme souvent, choix du nom et vérification DiscordEmbedBuilder embedChooseName = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("introductionChooseName", region: r)); await ctx.RespondAsync(embed : embedChooseName); do { MessageContext msgGuildName = await interactivity.WaitForMessageAsync( xm => xm.Author.Id == ctx.User.Id && xm.ChannelId == ctx.Channel.Id, TimeSpan.FromMinutes(1)); if (msgGuildName != null) { //Nouvelle commande, on annule if (msgGuildName.Message.Content.StartsWith(Config.Instance.Prefix)) { return; } else { regionName = msgGuildName.Message.Content; } //Enlever *, ` et _ regionName = dep.Dialog.RemoveMarkdown(regionName); } if (!dep.Entities.Map.IsRegionNameTaken(regionName) && regionName.Length > 3 && regionName.Length <= 50) { nameValid = true; } else { DiscordEmbedBuilder embed = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("regionNameTaken")); await ctx.RespondAsync(embed : embed); } } while (!nameValid); r = dep.Entities.Map.GenerateNewRegion(9, ctx.Guild.Id, regionName, r.Type, forceValable: true); } //Enregistrement du serveur discord associé à sa région Guild g = new Guild { Id = ctx.Guild.Id, MemberCount = ctx.Guild.MemberCount, Name = ctx.Guild.Name, RegionName = r.Name, SpawnLocation = r.GetCentralCase().Location }; dep.Entities.Guilds.AddGuild(g); //Message de bienvenue (YAY) DiscordEmbedBuilder embedEnd = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("introductionGenFinish", region: r), dep.Dialog.GetString("introTypeStart"), true); await ctx.RespondAsync(embed : embedEnd); }
public async Task StartCommand(CommandContext ctx) { //Vérification de base if (dep.Entities.Characters.IsPresent(ctx.User.Id)) { await ctx.RespondAsync(dep.Dialog.GetString("errorAlreadyRegistered")); return; } if (!dep.Entities.Guilds.IsPresent(ctx.Guild.Id)) { return; } InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); //Créer Direct Channel (MP) DiscordDmChannel channel = await ctx.Member.CreateDmChannelAsync(); //Création du Character Character c = new Character { Id = ctx.User.Id }; //1 On récupère le truename puis on enregistre directement pour éviter les doublons DiscordEmbedBuilder embedTrueName = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("startIntroAskTruename"), dep.Dialog.GetString("startIntroInfoTruename")); await channel.SendMessageAsync(embed : embedTrueName); bool trueNameIsValid = false; do { MessageContext msgTrueName = await interactivity.WaitForMessageAsync( xm => xm.Author.Id == ctx.User.Id && xm.ChannelId == channel.Id, TimeSpan.FromMinutes(1)); if (msgTrueName != null) { if (msgTrueName.Message.Content.Length <= 50 && !dep.Entities.Characters.IsTrueNameTaken(msgTrueName.Message.Content) && msgTrueName.Message.Content.Length > 2) { c.TrueName = dep.Dialog.RemoveMarkdown(msgTrueName.Message.Content); dep.Entities.Characters.AddCharacter(c); trueNameIsValid = true; } else { DiscordEmbedBuilder embedErrorTrueName = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("startIntroTrueTaken")); await channel.SendMessageAsync(embed : embedErrorTrueName); } } } while (!trueNameIsValid); //2 On demande le nom DiscordEmbedBuilder embedName = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("startIntroAskName"), dep.Dialog.GetString("startIntroInfoName")); await channel.SendMessageAsync(embed : embedName); MessageContext msgName = await interactivity.WaitForMessageAsync( xm => xm.Author.Id == ctx.User.Id && xm.ChannelId == channel.Id, TimeSpan.FromMinutes(1)); if (msgName != null) { c.Name = dep.Dialog.RemoveMarkdown(msgName.Message.Content); } //3 Puis finalement le sexe DiscordEmbedBuilder embedSex = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("startIntroAskGender"), dep.Dialog.GetString("startIntroInfoGender")); await channel.SendMessageAsync(embed : embedSex); MessageContext msgSex = await interactivity.WaitForMessageAsync(xm => xm.Author.Id == ctx.User.Id && (xm.Content.ToLower() == "male" || xm.Content.ToLower() == "female" && xm.ChannelId == channel.Id), TimeSpan.FromMinutes(1)); if (msgSex != null) { if (msgSex.Message.Content.ToLower() == "male") { c.Sex = Sex.Male; } else { c.Sex = Sex.Female; } } else { c.Sex = Sex.Male; } //Si le nom a bien été rentré, on créer le personnage if (c.Name != null) { DiscordEmbedBuilder embedFinal = dep.Embed.CreateBasicEmbed(ctx.User, dep.Dialog.GetString("startIntroConclude", c)); await channel.SendMessageAsync(embed : embedFinal); c.Level = 1; c.Energy = 100; c.MaxEnergy = 100; c.Location = dep.Entities.Guilds.GetGuildById(ctx.Guild.Id).SpawnLocation; c.Stats = new CharacterStats { Endurance = 1, Strength = 1, Intelligence = 1, Agility = 1, Dexterity = 1, Health = 100, MaxHealth = 100, UpgradePoint = 0 }; //INVENTAIRE CharacterInventory inv = new CharacterInventory { Id = c.Id }; inv.AddMoney(500); inv.AddItem(new Wood(10)); inv.AddItem(new Weapon() { Name = "Awesome sword", Quantity = 1, AttackDamage = 10, CraftsmanId = 100, Hand = 2 }); c.Skills.Add(new LoggerSkill()); dep.Entities.Inventories.AddInventory(inv); c.OriginRegionName = dep.Entities.Map.GetRegionByLocation(dep.Entities.Guilds.GetGuildById(ctx.Guild.Id).SpawnLocation).Name; c.Profession = Profession.Peasant; dep.Entities.Map.GetCase(c.Location).AddNewCharacter(c); dep.Entities.Characters.EditCharacter(c); } //Sinon on supprime celui qui avait commencé à être créer else { dep.Entities.Characters.DeleteCharacter(c.Id); } }
public async Task ApplyForRegistration(CommandContext ctx) { if (!ctx.Channel.IsPrivate) { return; } try { DiscordUser user = ctx.User; if ((await MySqlClient.RetrieveAllSdlPlayers()).Any(e => e.DiscordId == user.Id)) { await ctx.RespondAsync("You are already are registered or are awaiting registration for SDL!"); return; } List <ulong> awaitingIds = new List <ulong>(); string regDirectory = Directory.CreateDirectory(Path.Combine(Globals.AppPath, "Registrations")).FullName; foreach (string file in Directory.EnumerateFiles(regDirectory)) { awaitingIds.Add(Convert.ToUInt64((await File.ReadAllLinesAsync(file))[0])); } if (awaitingIds.Contains(user.Id)) { await ctx.RespondAsync("You are already are registered or are awaiting registration for SDL!"); return; } await ctx.RespondAsync(Resources.RegistrationBegin); InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); MessageContext timeZoneResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (timeZoneResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } await ctx.RespondAsync($"Your timezone has been set to {timeZoneResponse.Message.Content}. " + $"By the way, at any time you may reply \"retry\" to reenter the last response. " + $"Please note that you only get one chance to retry a response!"); await ctx.RespondAsync(Resources.RegistrationNickname); MessageContext nicknameResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (nicknameResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } if (nicknameResponse.Message.Content.ToLower() == "retry") { await ctx.RespondAsync("Please restate your timezone."); timeZoneResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (timeZoneResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } await ctx.RespondAsync($"Your timezone has been set to {timeZoneResponse.Message.Content}."); await ctx.RespondAsync(Resources.RegistrationNickname); nicknameResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (nicknameResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } } string timezone = timeZoneResponse.Message.Content; await ctx.RespondAsync(Resources.RegistrationTeams); MessageContext teamsResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (teamsResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } if (teamsResponse.Message.Content.ToLower() == "retry") { await ctx.RespondAsync("Please restate your nickname."); nicknameResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (nicknameResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } await ctx.RespondAsync($"Your nickname has been set to {nicknameResponse.Message.Content}."); await ctx.RespondAsync(Resources.RegistrationTeams); teamsResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (teamsResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } } string nickname = nicknameResponse.Message.Content; await ctx.RespondAsync(Resources.RegistrationScreenshot); MessageContext screenshotResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); bool hasScreenshot = true; if (screenshotResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } if (screenshotResponse.Message.Content.ToLower() == "retry") { await ctx.RespondAsync("Please restate your teams."); teamsResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (teamsResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } await ctx.RespondAsync($"Your team(s) have been set to {teamsResponse.Message.Content}."); await ctx.RespondAsync(Resources.RegistrationTeams); screenshotResponse = await interactivity.WaitForMessageAsync(x => x.Author.Id == user.Id, TimeSpan.FromMinutes(10)); if (screenshotResponse == null) { await ctx.RespondAsync(Resources.RegistrationTimeout); return; } } else if (screenshotResponse.Message.Content.ToLower() == "no") { hasScreenshot = false; } string teams = teamsResponse.Message.Content; DiscordEmbedBuilder builder = new DiscordEmbedBuilder { Description = $"**{ctx.User.Mention} ({ctx.User.Username}#{ctx.User.Discriminator}) has applied for registration.**" }; builder.AddField(e => { e.Name = "Time Zone"; e.Value = timezone; e.IsInline = true; }); builder.AddField(e => { e.Name = "Nickname"; e.Value = nickname; e.IsInline = true; }); builder.AddField(e => { e.Name = "Competitive Team Experience"; e.Value = teams; e.IsInline = true; }); await ctx.RespondAsync(Resources.RegistrationProcessing); DiscordChannel regChannel = await Program.Client.GetChannelAsync(595219144488648704); DiscordMessage userMessage = await regChannel.SendMessageAsync("Needs Approval.", embed : builder.Build()); await userMessage.CreateReactionAsync(DiscordEmoji.FromUnicode("\u2705")); // Check mark await userMessage.CreateReactionAsync(DiscordEmoji.FromUnicode("\u274E")); // X await File.WriteAllTextAsync(Path.Combine(regDirectory, $"{userMessage.Id}"), $"{ctx.User.Id}\n{nickname}"); await ctx.RespondAsync(Resources.RegistrationComplete); } catch (Exception e) { Console.WriteLine(e); throw; } }
public async Task Leave(CommandContext ctx) { try { if (!(ctx.User is DiscordMember user)) { return; } Lobby joinedLobby = Matchmaker.Lobbies.FirstOrDefault(e => e.Players.Any(f => f.DiscordId == user.Id)); if (joinedLobby != null) { joinedLobby.RemovePlayer(joinedLobby.Players.FirstOrDefault(e => e.DiscordId == user.Id)); await ctx.RespondAsync($"You have left lobby #{joinedLobby.LobbyNumber}."); if (joinedLobby.Players.Count == 0) { joinedLobby.Close(); await ctx.RespondAsync($"Lobby #{joinedLobby.LobbyNumber} has been disbanded."); } } else { Set joinedSet = Matchmaker.Sets.FirstOrDefault(e => e.AllPlayers.Any(f => f.DiscordId == user.Id)); if (joinedSet == null) { return; } if (ctx.Channel.Id != (await CommandHelper.ChannelFromSet(joinedSet.SetNumber)).Id) { return; } decimal penalty = MatchModule.CalculatePoints(joinedSet) / 2 + 10; string penaltyDir = Directory.CreateDirectory(Path.Combine(Globals.AppPath, "Penalties")).FullName; string penaltyFile = Path.Combine(penaltyDir, $"{user.Id}.penalty"); string penaltyMessage = $"If you leave the set, you will be instated with a penalty of {penalty} points. "; Record record; if (File.Exists(penaltyFile)) { record = JsonConvert.DeserializeObject <Record>(File.ReadAllText(penaltyFile)); int infractionCount = record.InfractionsThisMonth() + 1; switch (infractionCount) { case 1: penaltyMessage += ""; break; case 2: penaltyMessage += "In addition, you will be banned from participating in SDL for 24 hours."; break; case 3: penaltyMessage += "In addition, you will be banned from participating in SDL for 1 week."; break; default: penaltyMessage += "In addition, you will be banned from participating in SDL for 1 week AND will be barred from participating in cups."; break; } } else { penaltyMessage += " Otherwise, this time will be just a warning."; record = new Record { AllInfractions = new List <Infraction>() }; } await ctx.RespondAsync(penaltyMessage + "\nAre you sure you wish to leave the set? (Y/N)"); InteractivityModule interactivity = ctx.Client.GetInteractivityModule(); MessageContext response = await interactivity.WaitForMessageAsync(x => user.Id == x.Author.Id, TimeSpan.FromMinutes(1)); if (response == null) { await ctx.RespondAsync($"{user.Mention} took too long to respond. Assuming you changed your mind, please continue with the set."); } else if (response.Message.Content.ToLower() == "y") { decimal points = await MatchModule.ReportScores(joinedSet, true); await MySqlClient.PenalizePlayer(await MySqlClient.RetrieveSdlPlayer(user.Id), (int)penalty, "Left a set."); record.AllInfractions.Add(new Infraction { Penalty = (int)penalty, Notes = "Left a set.", TimeOfOffense = DateTime.Now }); if (joinedSet.AlphaTeam.Players.Any(e => e.DiscordId == user.Id)) { joinedSet.AlphaTeam.RemovePlayer( joinedSet.AlphaTeam.Players.First(e => e.DiscordId == user.Id)); } else if (joinedSet.BravoTeam.Players.Any(e => e.DiscordId == user.Id)) { joinedSet.BravoTeam.RemovePlayer( joinedSet.BravoTeam.Players.First(e => e.DiscordId == user.Id)); } else if (joinedSet.DraftPlayers.Any(e => e.DiscordId == user.Id)) { joinedSet.DraftPlayers.Remove( joinedSet.DraftPlayers.First(e => e.DiscordId == user.Id)); } List <DiscordMember> remainingUsers = ctx.Guild.Members.Where(x => joinedSet.AllPlayers.Any(y => y.DiscordId == x.Id)).ToList(); File.WriteAllText(penaltyFile, JsonConvert.SerializeObject(record, Formatting.Indented)); await ctx.RespondAsync( $"{user.Mention} Aforementioned penalty applied. Don't make a habit of this! " + $"As for the rest of the set, you will return to <#572536965833162753> to requeue. " + $"Beginning removal of access to this channel in 30 seconds. " + $"Rate limiting may cause the full process to take up to two minutes.", embed : joinedSet.GetScoreEmbedBuilder(points, points / 2).Build()); /*Lobby movedLobby = Matchmaker.Lobbies.First(e => !e.Players.Any()); * * if (movedLobby == null) * { * // TODO Not sure what to do if all lobbies are filled. * return; * } * * foreach (SdlPlayer joinedSetPlayer in joinedSet.AllPlayers) * { * movedLobby.AddPlayer(joinedSetPlayer, true); * }*/ joinedSet.Close(); await Task.Delay(TimeSpan.FromSeconds(30)); List <DiscordRole> roleRemovalList = CommandHelper.DraftRoleIds.Select(e => ctx.Guild.GetRole(e)).ToList(); await user.RemoveRolesAsync(roleRemovalList.Where(x => user.Roles.Select(xr => xr.Id).Contains(x.Id))); foreach (DiscordMember member in remainingUsers) { await member.RemoveRolesAsync(roleRemovalList.Where(x => member.Roles.Any(f => f.Id == x.Id))); } /*await (await ctx.Client.GetChannelAsync(572536965833162753)) * .SendMessageAsync($"{8 - movedLobby.Players.Count} players needed to begin.", * embed: movedLobby.GetEmbedBuilder().Build());*/ } else { await ctx.RespondAsync("Assuming you declined leaving since you did not reply with \"Y\". Please continue with the set."); } } } catch (Exception e) { Console.WriteLine(e); throw; } }