Animal Racing added ($race, $joinrace). Need to add betting to it.
This commit is contained in:
parent
fce0da50f1
commit
a7618b1ee4
@ -138,7 +138,7 @@ namespace NadekoBot.Extensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
/// <param name="list"></param>
|
/// <param name="list"></param>
|
||||||
public static void Shuffle<T>(this IList<T> list)
|
public static IList<T> Shuffle<T>(this IList<T> list)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Thanks to @Joe4Evr for finding a bug in the old version of the shuffle
|
// Thanks to @Joe4Evr for finding a bug in the old version of the shuffle
|
||||||
@ -160,6 +160,7 @@ namespace NadekoBot.Extensions
|
|||||||
list[k] = list[n];
|
list[k] = list[n];
|
||||||
list[n] = value;
|
list[n] = value;
|
||||||
}
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -41,8 +41,9 @@ namespace NadekoBot
|
|||||||
var commandService = NadekoBot.Client.GetService<CommandService>();
|
var commandService = NadekoBot.Client.GetService<CommandService>();
|
||||||
|
|
||||||
statsStopwatch.Start();
|
statsStopwatch.Start();
|
||||||
|
#if !NADEKO_RELEASE
|
||||||
commandService.CommandExecuted += StatsCollector_RanCommand;
|
commandService.CommandExecuted += StatsCollector_RanCommand;
|
||||||
|
#endif
|
||||||
Task.Run(StartCollecting);
|
Task.Run(StartCollecting);
|
||||||
|
|
||||||
commandLogTimer.Start();
|
commandLogTimer.Start();
|
||||||
|
253
NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
Normal file
253
NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
using NadekoBot.Classes;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Discord.Commands;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using Discord;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Gambling.Commands
|
||||||
|
{
|
||||||
|
class AnimalRacing : DiscordCommand
|
||||||
|
{
|
||||||
|
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces = new ConcurrentDictionary<ulong, AnimalRace>();
|
||||||
|
|
||||||
|
public AnimalRacing(DiscordModule module) : base(module)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal override void Init(CommandGroupBuilder cgb)
|
||||||
|
{
|
||||||
|
cgb.CreateCommand(Prefix + "race")
|
||||||
|
.Description("Starts a new animal race.")
|
||||||
|
.Do(e => {
|
||||||
|
var ar = new AnimalRace(e.Server.Id, e.Channel);
|
||||||
|
if (ar.Fail)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
cgb.CreateCommand(Prefix + "joinrace")
|
||||||
|
.Alias(Prefix + "jr")
|
||||||
|
.Description("Joins a new race")
|
||||||
|
.Do(async e => {
|
||||||
|
AnimalRace ar;
|
||||||
|
|
||||||
|
if (!AnimalRaces.TryGetValue(e.Server.Id, out ar)) {
|
||||||
|
await e.Channel.SendMessage("No race exists on this server");
|
||||||
|
}
|
||||||
|
await ar.JoinRace(e.User);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AnimalRace
|
||||||
|
{
|
||||||
|
|
||||||
|
private ConcurrentQueue<string> animals = new ConcurrentQueue<string>(NadekoBot.Config.RaceAnimals.Shuffle());
|
||||||
|
|
||||||
|
public bool Fail { get; internal set; }
|
||||||
|
|
||||||
|
public List<Participant> participants = new List<Participant>();
|
||||||
|
private ulong serverId;
|
||||||
|
private int messagesSinceGameStarted = 0;
|
||||||
|
|
||||||
|
public Channel raceChannel { get; set; }
|
||||||
|
public bool Started { get; private set; } = false;
|
||||||
|
|
||||||
|
public AnimalRace(ulong serverId, Channel ch)
|
||||||
|
{
|
||||||
|
this.serverId = serverId;
|
||||||
|
this.raceChannel = ch;
|
||||||
|
if (!AnimalRaces.TryAdd(serverId, this))
|
||||||
|
{
|
||||||
|
Fail = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var cancelSource = new CancellationTokenSource();
|
||||||
|
var token = cancelSource.Token;
|
||||||
|
var fullgame = CheckForFullGameAsync(token);
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
await raceChannel.SendMessage($"🏁`Race is starting in 20 seconds or when the room is full. Type $jr to join the race.`");
|
||||||
|
var t = await Task.WhenAny(Task.Delay(20000, token), fullgame);
|
||||||
|
Started = true;
|
||||||
|
cancelSource.Cancel();
|
||||||
|
if (t == fullgame)
|
||||||
|
{
|
||||||
|
await raceChannel.SendMessage("🏁`Race full, starting right now!`");
|
||||||
|
}
|
||||||
|
else if (participants.Count > 1) {
|
||||||
|
await raceChannel.SendMessage("🏁`Game starting with " + participants.Count + " praticipants.`");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await raceChannel.SendMessage("🏁`Race failed to start since there was not enough participants.`");
|
||||||
|
End();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await Task.Run(StartRace);
|
||||||
|
End();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void End()
|
||||||
|
{
|
||||||
|
AnimalRace throwaway;
|
||||||
|
AnimalRaces.TryRemove(serverId, out throwaway);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task StartRace() {
|
||||||
|
var rng = new Random();
|
||||||
|
Participant winner = null;
|
||||||
|
Message msg = null;
|
||||||
|
int place = 1;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
NadekoBot.Client.MessageReceived += Client_MessageReceived;
|
||||||
|
|
||||||
|
while (!participants.All(p => p.Total >= 60))
|
||||||
|
{
|
||||||
|
//update the state
|
||||||
|
participants.ForEach(p =>
|
||||||
|
{
|
||||||
|
|
||||||
|
p.Total += 1 + rng.Next(0, 10);
|
||||||
|
if (p.Total > 60)
|
||||||
|
{
|
||||||
|
p.Total = 60;
|
||||||
|
if (winner == null)
|
||||||
|
{
|
||||||
|
winner = p;
|
||||||
|
}
|
||||||
|
if (p.Place == 0)
|
||||||
|
p.Place = place++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//draw the state
|
||||||
|
|
||||||
|
var text = $@"|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|
|
||||||
|
{String.Join("\n", participants.Select(p => $"{(int)(p.Total / 60f * 100),-2}%|{p.ToString()}"))}
|
||||||
|
|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|";
|
||||||
|
if (msg == null || messagesSinceGameStarted >= 10) // also resend the message if channel was spammed
|
||||||
|
{
|
||||||
|
if(msg != null)
|
||||||
|
try { await msg.Delete(); } catch { }
|
||||||
|
msg = await raceChannel.SendMessage(text);
|
||||||
|
messagesSinceGameStarted = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
await msg.Edit(text);
|
||||||
|
|
||||||
|
await Task.Delay(2500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
NadekoBot.Client.MessageReceived -= Client_MessageReceived;
|
||||||
|
}
|
||||||
|
await raceChannel.SendMessage($"🏁 {winner.User.Mention} as {winner.Animal} `Won the race!`");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Client_MessageReceived(object sender, MessageEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Message.IsAuthor)
|
||||||
|
return;
|
||||||
|
Console.WriteLine("Message received " + messagesSinceGameStarted);
|
||||||
|
messagesSinceGameStarted++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CheckForFullGameAsync(CancellationToken cancelToken) {
|
||||||
|
while (animals.Count > 0)
|
||||||
|
{
|
||||||
|
await Task.Delay(100,cancelToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> JoinRace(User u)
|
||||||
|
{
|
||||||
|
var animal = "";
|
||||||
|
if (!animals.TryDequeue(out animal))
|
||||||
|
{
|
||||||
|
await raceChannel.SendMessage($"{u.Mention} `There is no running race on this server.`");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var p = new Participant(u, animal);
|
||||||
|
if (participants.Contains(p))
|
||||||
|
{
|
||||||
|
await raceChannel.SendMessage($"{u.Mention} `You already joined this race.`");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Started)
|
||||||
|
{
|
||||||
|
await raceChannel.SendMessage($"{u.Mention} `Race is already started`");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
participants.Add(p);
|
||||||
|
await raceChannel.SendMessage($"{u.Mention} **joined the race as a {p.Animal}**");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Participant
|
||||||
|
{
|
||||||
|
public User User { get; set; }
|
||||||
|
public string Animal { get; set; }
|
||||||
|
|
||||||
|
public float Coeff { get; set; }
|
||||||
|
public int Total { get; set; }
|
||||||
|
|
||||||
|
public int Place { get; set; } = 0;
|
||||||
|
|
||||||
|
public Participant(User u, string a)
|
||||||
|
{
|
||||||
|
this.User = u;
|
||||||
|
this.Animal = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return User.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
var p = obj as Participant;
|
||||||
|
return p == null?
|
||||||
|
false:
|
||||||
|
p.User == User;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var str = new string('‣', Total) + Animal;
|
||||||
|
if (Place == 0)
|
||||||
|
return str;
|
||||||
|
if (Place == 1)
|
||||||
|
{
|
||||||
|
return str + "🏆";
|
||||||
|
}
|
||||||
|
else if (Place == 2)
|
||||||
|
{
|
||||||
|
return str + "`2nd`";
|
||||||
|
}
|
||||||
|
else if (Place == 3)
|
||||||
|
{
|
||||||
|
return str + "`3rd`";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return str + $"`{Place}th`";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ using Discord.Modules;
|
|||||||
using NadekoBot.Classes;
|
using NadekoBot.Classes;
|
||||||
using NadekoBot.DataModels;
|
using NadekoBot.DataModels;
|
||||||
using NadekoBot.Extensions;
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Modules.Gambling.Commands;
|
||||||
using NadekoBot.Modules.Permissions.Classes;
|
using NadekoBot.Modules.Permissions.Classes;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -18,6 +19,7 @@ namespace NadekoBot.Modules.Gambling
|
|||||||
commands.Add(new DrawCommand(this));
|
commands.Add(new DrawCommand(this));
|
||||||
commands.Add(new FlipCoinCommand(this));
|
commands.Add(new FlipCoinCommand(this));
|
||||||
commands.Add(new DiceRollCommand(this));
|
commands.Add(new DiceRollCommand(this));
|
||||||
|
commands.Add(new AnimalRacing(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Gambling;
|
public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Gambling;
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
<DefineConstants>TRACE</DefineConstants>
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PRIVATE|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PRIVATE|AnyCPU'">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@ -189,6 +190,7 @@
|
|||||||
<Compile Include="Classes\FlowersHandler.cs" />
|
<Compile Include="Classes\FlowersHandler.cs" />
|
||||||
<Compile Include="Modules\Conversations\Commands\RipCommand.cs" />
|
<Compile Include="Modules\Conversations\Commands\RipCommand.cs" />
|
||||||
<Compile Include="Modules\CustomReactions\CustomReactions.cs" />
|
<Compile Include="Modules\CustomReactions\CustomReactions.cs" />
|
||||||
|
<Compile Include="Modules\Gambling\Commands\AnimalRacing.cs" />
|
||||||
<Compile Include="Modules\Music\Classes\PlaylistFullException.cs" />
|
<Compile Include="Modules\Music\Classes\PlaylistFullException.cs" />
|
||||||
<Compile Include="Modules\Programming\Commands\HaskellRepl.cs" />
|
<Compile Include="Modules\Programming\Commands\HaskellRepl.cs" />
|
||||||
<Compile Include="Modules\Programming\ProgrammingModule.cs" />
|
<Compile Include="Modules\Programming\ProgrammingModule.cs" />
|
||||||
|
@ -90,6 +90,17 @@ namespace NadekoBot.Classes.JSONModels
|
|||||||
public bool IsRotatingStatus { get; set; } = false;
|
public bool IsRotatingStatus { get; set; } = false;
|
||||||
public int BufferSize { get; set; } = 4.MiB();
|
public int BufferSize { get; set; } = 4.MiB();
|
||||||
|
|
||||||
|
public string[] RaceAnimals { get; internal set; } = {
|
||||||
|
"🐼",
|
||||||
|
"🐻",
|
||||||
|
"🐧",
|
||||||
|
"🐨",
|
||||||
|
"🐬",
|
||||||
|
"🐞",
|
||||||
|
"🦀",
|
||||||
|
"🦄" };
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
public List<Quote> Quotes { get; set; } = new List<Quote>();
|
public List<Quote> Quotes { get; set; } = new List<Quote>();
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
|
@ -4,7 +4,16 @@
|
|||||||
"ForwardToAllOwners": false,
|
"ForwardToAllOwners": false,
|
||||||
"IsRotatingStatus": false,
|
"IsRotatingStatus": false,
|
||||||
"BufferSize": 4194304,
|
"BufferSize": 4194304,
|
||||||
"Quotes": [],
|
"RaceAnimals": [
|
||||||
|
"🐼",
|
||||||
|
"🐻",
|
||||||
|
"🐧",
|
||||||
|
"🐨",
|
||||||
|
"🐬",
|
||||||
|
"🐞",
|
||||||
|
"🦀",
|
||||||
|
"🦄"
|
||||||
|
],
|
||||||
"RemindMessageFormat": "❗⏰**I've been told to remind you to '%message%' now by %user%.**⏰❗",
|
"RemindMessageFormat": "❗⏰**I've been told to remind you to '%message%' now by %user%.**⏰❗",
|
||||||
"CustomReactions": {
|
"CustomReactions": {
|
||||||
"\\o\\": [
|
"\\o\\": [
|
||||||
|
Loading…
Reference in New Issue
Block a user