mirror of
https://github.com/barelyprofessional/KfChatDotNet.git
synced 2026-04-30 03:22:04 -04:00
message deletion and krash (#102)
* Update message deletion in BlackjackCommand Refactor message deletion logic for non-whisper messages. * Add message deletion for non-whisper coinflip * Implement message deletion for non-whispers Added a check to delete non-whisper messages if they have a MessageUuid. * Delete non-whisper messages in KenoCommand * Implement KrashBetCommand for betting functionality * Lambchop message deletion Lambchop message deletion * limbo message deletion limbo message deletion * Delete message if not a whisper mines Delete message if not a whisper mines * planes message dleete planes message dleete * plinko message delete plinko message delete * Add message deletion for non-whisper messages roulette Delete the message if it's not a whisper and has a UUID. * add message deletion for non-whisper slots add message deletion for non-whisper slots * Implement message deletion for WheelCommand Add message deletion for non-whisper messages. * Add KasinoKrash service initialization * Add KasinoKrash service for game management Implement KasinoKrash service for managing the Krash game, including state management, betting, and payout logic. * Update message formatting in KasinoMines.cs add buttons * Update MinesCommand.cs allow more mines spam since message will be deleted anyways, spam will be supported via button
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using KfChatDotNetBot.Extensions;
|
||||
using KfChatDotNetBot.Models;
|
||||
@@ -62,6 +62,11 @@ public class BlackjackCommand : ICommand
|
||||
return;
|
||||
}
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
|
||||
var cleanupDelay = TimeSpan.FromMilliseconds(settings[BuiltIn.Keys.KasinoBlackjackCleanupDelay].ToType<int>());
|
||||
|
||||
if (arguments.TryGetValue("amount", out var amountGroup))
|
||||
|
||||
@@ -52,6 +52,11 @@ public class CoinflipCommand : ICommand
|
||||
return;
|
||||
}
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
|
||||
var cleanupDelay = TimeSpan.FromMilliseconds(settings[BuiltIn.Keys.KasinoCoinflipCleanupDelay].ToType<int>());
|
||||
|
||||
if (!arguments.TryGetValue("amount", out var amount))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using KfChatDotNetBot.Extensions;
|
||||
using KfChatDotNetBot.Models;
|
||||
using KfChatDotNetBot.Models.DbModels;
|
||||
@@ -37,6 +37,11 @@ public class DiceCommand : ICommand
|
||||
BuiltIn.Keys.KasinoDiceEnabled
|
||||
]);
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
|
||||
// Check if dice is enabled
|
||||
var diceEnabled = (settings[BuiltIn.Keys.KasinoDiceEnabled]).ToBoolean();
|
||||
if (!diceEnabled)
|
||||
|
||||
@@ -47,7 +47,10 @@ public class KenoCommand : ICommand
|
||||
BuiltIn.Keys.KasinoGameDisabledMessageCleanupDelay, BuiltIn.Keys.KasinoKenoCleanupDelay,
|
||||
BuiltIn.Keys.KasinoKenoFrameDelay, BuiltIn.Keys.KasinoKenoEnabled
|
||||
]);
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
// Check if keno is enabled
|
||||
var kenoEnabled = (settings[BuiltIn.Keys.KasinoKenoEnabled]).ToBoolean();
|
||||
if (!kenoEnabled)
|
||||
|
||||
81
KfChatDotNetBot/Commands/Kasino/KrashCommand.cs
Normal file
81
KfChatDotNetBot/Commands/Kasino/KrashCommand.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using KfChatDotNetBot.Extensions;
|
||||
using KfChatDotNetBot.Models;
|
||||
using KfChatDotNetBot.Models.DbModels;
|
||||
using KfChatDotNetBot.Services;
|
||||
using KfChatDotNetBot.Settings;
|
||||
using KfChatDotNetWsClient.Models.Events;
|
||||
|
||||
namespace KfChatDotNetBot.Commands.Kasino;
|
||||
|
||||
[KasinoCommand]
|
||||
[WagerCommand]
|
||||
public class KrashBetCommand : ICommand
|
||||
{
|
||||
public List<Regex> Patterns => [
|
||||
new Regex(@"^krash (?<amount>\d+(?:\.\d+)?) (?<multi>\d+(?:\.\d+)?)$", RegexOptions.IgnoreCase),
|
||||
new Regex(@"^krash (?<amount>\d+(?:\.\d+)?)$", RegexOptions.IgnoreCase),
|
||||
new Regex(@"^krash", RegexOptions.IgnoreCase)
|
||||
];
|
||||
|
||||
public string? HelpText => "!rain <amount> to start a rain, !rain to join all active rains";
|
||||
public UserRight RequiredRight => UserRight.Loser;
|
||||
public TimeSpan Timeout => TimeSpan.FromSeconds(90);
|
||||
public RateLimitOptionsModel? RateLimitOptions => null;
|
||||
public bool WhisperCanInvoke => false;
|
||||
|
||||
public async Task RunCommand(ChatBot botInstance, BotCommandMessageModel message, UserDbModel user,
|
||||
GroupCollection arguments,
|
||||
CancellationToken ctx)
|
||||
{
|
||||
var cleanupDelay = TimeSpan.FromSeconds(10);
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
var gambler = await Money.GetGamblerEntityAsync(user.Id, ct: ctx);
|
||||
|
||||
if (gambler == null)
|
||||
throw new InvalidOperationException($"Caught a null when retrieving gambler for {user.KfUsername}");
|
||||
|
||||
if (botInstance.BotServices.KasinoKrash == null)
|
||||
{
|
||||
await botInstance.SendChatMessageAsync("Krash is not currently running.", true, autoDeleteAfter: cleanupDelay);
|
||||
return;
|
||||
}
|
||||
decimal multi;
|
||||
decimal wager;
|
||||
if (!arguments.TryGetValue("amount", out var amountGroup))
|
||||
{
|
||||
//attempt to cash out a currently running game
|
||||
await botInstance.BotServices.KasinoKrash.AttemptKrash(gambler);
|
||||
}
|
||||
if (!arguments.TryGetValue("multi", out var multiGroup))
|
||||
{
|
||||
multi = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
multi = Convert.ToDecimal(multiGroup.Value);
|
||||
}
|
||||
wager = Convert.ToDecimal(amountGroup.Value);
|
||||
if (wager > gambler.Balance)
|
||||
{
|
||||
await botInstance.SendChatMessageAsync(
|
||||
$"{user.FormatUsername()}, your balance of {gambler.Balance} is not enough to bet {wager} on krash.",
|
||||
true, autoDeleteAfter: TimeSpan.FromSeconds(5));
|
||||
return;
|
||||
}
|
||||
if (botInstance.BotServices.KasinoKrash.theGame == null)
|
||||
{
|
||||
//start a new game
|
||||
await botInstance.BotServices.KasinoKrash.StartGame(gambler, wager, multi);
|
||||
}
|
||||
else
|
||||
{
|
||||
//add to the existing game
|
||||
await botInstance.BotServices.KasinoKrash.AddParticipant(gambler, wager, multi);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using KfChatDotNetBot.Extensions;
|
||||
using KfChatDotNetBot.Models;
|
||||
using KfChatDotNetBot.Models.DbModels;
|
||||
@@ -66,7 +66,10 @@ public class LambchopCommand : ICommand
|
||||
BuiltIn.Keys.KasinoGameDisabledMessageCleanupDelay, BuiltIn.Keys.KasinoLambchopCleanupDelay,
|
||||
BuiltIn.Keys.KasinoLambchopEnabled
|
||||
]);
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
// Check if lambchop is enabled
|
||||
var lambchopEnabled = (settings[BuiltIn.Keys.KasinoLambchopEnabled]).ToBoolean();
|
||||
if (!lambchopEnabled)
|
||||
|
||||
@@ -42,7 +42,10 @@ public class LimboCommand : ICommand
|
||||
BuiltIn.Keys.KasinoLimboCleanupDelay, BuiltIn.Keys.KasinoLimboEnabled,
|
||||
BuiltIn.Keys.KiwiFarmsGreenColor, BuiltIn.Keys.KiwiFarmsRedColor
|
||||
]);
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
// Check if limbo is enabled
|
||||
var limboEnabled = (settings[BuiltIn.Keys.KasinoLimboEnabled]).ToBoolean();
|
||||
if (!limboEnabled)
|
||||
|
||||
@@ -39,7 +39,7 @@ public class MinesCommand : ICommand
|
||||
|
||||
public RateLimitOptionsModel? RateLimitOptions => new RateLimitOptionsModel
|
||||
{
|
||||
MaxInvocations = 3,
|
||||
MaxInvocations = 10,
|
||||
Window = TimeSpan.FromSeconds(10)
|
||||
};
|
||||
public bool WhisperCanInvoke => false;
|
||||
@@ -56,6 +56,10 @@ public class MinesCommand : ICommand
|
||||
BuiltIn.Keys.KasinoMinesEnabled, BuiltIn.Keys.KasinoGameDisabledMessageCleanupDelay
|
||||
]);
|
||||
var cleanupDelay = TimeSpan.FromMilliseconds(settings[BuiltIn.Keys.KasinoMinesCleanupDelay].ToType<int>());
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
if (!settings[BuiltIn.Keys.KasinoMinesEnabled].ToBoolean())
|
||||
{
|
||||
var gameDisabledCleanupDelay= TimeSpan.FromMilliseconds(settings[BuiltIn.Keys.KasinoGameDisabledMessageCleanupDelay].ToType<int>());
|
||||
|
||||
@@ -51,7 +51,10 @@ public class Planes : ICommand
|
||||
BuiltIn.Keys.KasinoPlanesCleanupDelay, BuiltIn.Keys.KasinoPlanesRandomRiggeryEnabled,
|
||||
BuiltIn.Keys.KasinoPlanesTargetedRiggeryEnabled, BuiltIn.Keys.KasinoPlanesTargetedRiggeryVictims
|
||||
]);
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
// Check if planes is enabled
|
||||
var planesEnabled = (settings[BuiltIn.Keys.KasinoPlanesEnabled]).ToBoolean();
|
||||
if (!planesEnabled)
|
||||
|
||||
@@ -72,7 +72,10 @@ public class PlinkoCommand : ICommand
|
||||
VACUUM += 1 - (double)HOUSE_EDGE;
|
||||
validPositions = new List<(int row, int col)>() { (0, DIFFICULTY-1) };
|
||||
validColumnsForRow = new Dictionary<int, List<int>>(){{0, new List<int>(){DIFFICULTY-1}}};
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
//calculate all the valid positions for the difficulty
|
||||
for (int i = 1; i < DIFFICULTY; i++)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using KfChatDotNetBot.Extensions;
|
||||
@@ -126,6 +126,10 @@ public class RouletteCommand : ICommand
|
||||
}
|
||||
|
||||
await PlaceBet(botInstance, user, amountGroup.Value, betGroup.Value.Trim(), countdownDuration, ctx);
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PlaceBet(ChatBot botInstance, UserDbModel user, string amountStr, string betStr,
|
||||
|
||||
@@ -49,7 +49,10 @@ public class SlotsCommand : ICommand
|
||||
var settings = await SettingsProvider.GetMultipleValuesAsync([
|
||||
BuiltIn.Keys.KasinoGameDisabledMessageCleanupDelay, BuiltIn.Keys.KasinoSlotsEnabled
|
||||
]);
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
// Check if slots is enabled
|
||||
var slotsEnabled = (settings[BuiltIn.Keys.KasinoSlotsEnabled]).ToBoolean();
|
||||
if (!slotsEnabled)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Globalization;
|
||||
using KfChatDotNetBot.Extensions;
|
||||
using KfChatDotNetBot.Models;
|
||||
@@ -69,7 +69,10 @@ public class WheelCommand : ICommand
|
||||
BuiltIn.Keys.KasinoGameDisabledMessageCleanupDelay, BuiltIn.Keys.KasinoWheelCleanupDelay,
|
||||
BuiltIn.Keys.KasinoWheelEnabled
|
||||
]);
|
||||
|
||||
if (message is { IsWhisper: false, MessageUuid: not null })
|
||||
{
|
||||
await botInstance.KfClient.DeleteMessageAsync(message.MessageUuid);
|
||||
}
|
||||
// Check if wheel is enabled
|
||||
var wheelEnabled = (settings[BuiltIn.Keys.KasinoWheelEnabled]).ToBoolean();
|
||||
if (!wheelEnabled)
|
||||
|
||||
@@ -42,6 +42,7 @@ public class BotServices
|
||||
private YouTubePubSub? _youTubePubSub;
|
||||
public KasinoRain? KasinoRain;
|
||||
public KasinoShop? KasinoShop;
|
||||
public KasinoKrash? KasinoKrash;
|
||||
|
||||
private Task? _websocketWatchdog;
|
||||
private Task? _howlggGetUserTimer;
|
||||
@@ -95,7 +96,8 @@ public class BotServices
|
||||
BuildShuffleDotUs(),
|
||||
BuildYouTubePubSub(),
|
||||
BuildKasinoRain(),
|
||||
BuildKasinoShop()
|
||||
BuildKasinoShop(),
|
||||
BuildKasinoKrash()
|
||||
];
|
||||
try
|
||||
{
|
||||
@@ -112,6 +114,12 @@ public class BotServices
|
||||
_howlggGetUserTimer = HowlggGetUserTimer();
|
||||
}
|
||||
|
||||
private async Task BuildKasinoKrash()
|
||||
{
|
||||
_logger.Debug("Building the Kasino Krash thingy");
|
||||
KasinoKrash = new KasinoKrash(_chatBot, _cancellationToken);
|
||||
}
|
||||
|
||||
private async Task BuildKasinoRain()
|
||||
{
|
||||
_logger.Debug("Building the Kasino Rain thingy");
|
||||
|
||||
254
KfChatDotNetBot/Services/KasinoKrash.cs
Normal file
254
KfChatDotNetBot/Services/KasinoKrash.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
using System.Text.Json;
|
||||
using KfChatDotNetBot.Extensions;
|
||||
using KfChatDotNetBot.Models;
|
||||
using KfChatDotNetBot.Models.DbModels;
|
||||
using KfChatDotNetBot.Settings;
|
||||
using NLog;
|
||||
using StackExchange.Redis;
|
||||
using System.Text.Json.Serialization;
|
||||
using KfChatDotNetBot.Commands.Kasino;
|
||||
using RandN;
|
||||
using RandN.Compat;
|
||||
|
||||
namespace KfChatDotNetBot.Services;
|
||||
|
||||
public class KasinoKrash : IDisposable
|
||||
{
|
||||
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
|
||||
private Task? _krashTimerTask;
|
||||
private IDatabase? _redisDb;
|
||||
private ChatBot _kfChatBot;
|
||||
private CancellationToken _ct;
|
||||
public decimal HOUSE_EDGE = 0.98m;
|
||||
public KasinoKrashModel? theGame;
|
||||
|
||||
|
||||
public KasinoKrash(ChatBot kfChatBot, CancellationToken ct = default) //the service itself
|
||||
{
|
||||
_kfChatBot = kfChatBot;
|
||||
_ct = ct;
|
||||
var connectionString = SettingsProvider.GetValueAsync(BuiltIn.Keys.BotRedisConnectionString).Result;
|
||||
if (string.IsNullOrEmpty(connectionString.Value))
|
||||
{
|
||||
_logger.Error($"Can't initialize the Kasino Krash service as Redis isn't configured in {BuiltIn.Keys.BotRedisConnectionString}");
|
||||
return;
|
||||
}
|
||||
|
||||
var redis = ConnectionMultiplexer.Connect(connectionString.Value);
|
||||
_redisDb = redis.GetDatabase();
|
||||
//attempt to pull a game from the db in case the bot crashed while a game was ongoing. if so it will restart the run
|
||||
theGame = GetKrashState().Result;
|
||||
if (theGame != null) _ = RunGame();
|
||||
}
|
||||
public bool IsInitialized()
|
||||
{
|
||||
return _redisDb != null;
|
||||
}
|
||||
public async Task<KasinoKrashModel?> GetKrashState()
|
||||
{
|
||||
if (_redisDb == null) throw new InvalidOperationException("Kasino Krash service isn't initialized");
|
||||
var json = await _redisDb.StringGetAsync("Krash.State");
|
||||
if (string.IsNullOrEmpty(json)) return null;
|
||||
var data = JsonSerializer.Deserialize<KasinoKrashModel>(json.ToString());
|
||||
return data;
|
||||
}
|
||||
public async Task RemoveKrashState()
|
||||
{
|
||||
if (_redisDb == null) throw new InvalidOperationException("Kasino krash service isn't initialized");
|
||||
await _redisDb.KeyDeleteAsync("Krash.State");
|
||||
theGame = null;
|
||||
}
|
||||
public async Task SaveKrashState(KasinoKrashModel krash)
|
||||
{
|
||||
if (_redisDb == null) throw new InvalidOperationException("Kasino Krash service isn't initialized");
|
||||
var json = JsonSerializer.Serialize(krash);
|
||||
await _redisDb.StringSetAsync("Krash.State", json, null, When.Always);
|
||||
}
|
||||
|
||||
public async Task AttemptKrash(GamblerDbModel gambler)
|
||||
{
|
||||
if (theGame == null)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to retrieve state or no krash is in progress");
|
||||
}
|
||||
if (!theGame.bets.Any(x => x.gambler.User.KfId == gambler.User.KfId)) return;
|
||||
if (!theGame.krashAccepted) return;
|
||||
|
||||
//find which bet is yours
|
||||
int index = 0;
|
||||
foreach (var bet in theGame.bets)
|
||||
{
|
||||
if (bet.gambler.User.KfId == gambler.User.KfId) break;
|
||||
index++;
|
||||
}
|
||||
|
||||
var krashBet = theGame.bets[index];
|
||||
theGame.bets.RemoveAt(index);
|
||||
decimal payout = theGame.currentMulti * krashBet.wager - krashBet.wager;
|
||||
var newBalance = await Money.NewWagerAsync(krashBet.gambler.Id, krashBet.wager, payout, WagerGame.Krash);
|
||||
await _kfChatBot.SendChatMessageAsync(
|
||||
$"{krashBet.gambler.User.FormatUsername()}, you [color=limegreen][b]won[/b][/color] {await payout.FormatKasinoCurrencyAsync()}!",
|
||||
true, autoDeleteAfter: TimeSpan.FromSeconds(10));
|
||||
if (_kfChatBot.BotServices.KasinoShop != null)
|
||||
{
|
||||
await _kfChatBot.BotServices.KasinoShop.ProcessWagerTracking(krashBet.gambler, WagerGame.Krash, krashBet.wager,
|
||||
payout, newBalance);
|
||||
}
|
||||
await SaveKrashState(theGame);
|
||||
}
|
||||
|
||||
public async Task AddParticipant(GamblerDbModel gambler, decimal wager, decimal multi = -1)
|
||||
{
|
||||
if (theGame == null)
|
||||
{
|
||||
theGame = await GetKrashState();
|
||||
if (theGame == null) throw new InvalidOperationException("Failed to retrieve state or no krash is in progress");
|
||||
_ = RunGame();
|
||||
}
|
||||
if (theGame.bets.Any(x => x.gambler.User.KfId == gambler.User.KfId)) return;
|
||||
if (!theGame.betsAccepted) return;
|
||||
KrashBet bet = new KrashBet{gambler = gambler, wager = wager, multi = multi};
|
||||
theGame.bets.Add(bet);
|
||||
await SaveKrashState(theGame);
|
||||
}
|
||||
|
||||
public async Task StartGame(GamblerDbModel creator, decimal wager, decimal multi = -1)
|
||||
{
|
||||
theGame = new KasinoKrashModel(creator);
|
||||
theGame.bets.Add(new KrashBet{gambler = creator, wager = wager, multi = multi});
|
||||
await SaveKrashState(theGame);
|
||||
_ = RunGame();
|
||||
}
|
||||
public async Task RunGame() //running the actual game
|
||||
{
|
||||
if (theGame == null)
|
||||
{
|
||||
await RemoveKrashState();
|
||||
await _kfChatBot.SendChatMessageAsync("Krash error 1", true);
|
||||
return;
|
||||
}
|
||||
var msg = await _kfChatBot.SendChatMessageAsync(
|
||||
$"{theGame.creator.User.FormatUsername()} started a Krash! You have 30 seconds to place your bets.", true);
|
||||
TimeSpan preGameTimer = TimeSpan.FromSeconds(30);
|
||||
TimeSpan interval = TimeSpan.FromSeconds(1);
|
||||
var timer = new PeriodicTimer(interval);
|
||||
string bets;
|
||||
while (await timer.WaitForNextTickAsync(_ct)) //timer before starting the game
|
||||
{
|
||||
bets = "";
|
||||
foreach (var bet in theGame.bets) bets += $"{bet.gambler.User.FormatUsername()} is betting {bet.wager}[br]";
|
||||
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid,
|
||||
$"{theGame.creator.User.FormatUsername()} started a Krash! You have {preGameTimer} to place your bets.[br]{bets}");
|
||||
preGameTimer -= interval;
|
||||
if (preGameTimer <= TimeSpan.Zero)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//any bets placed after this point will be cancelled, must wait until the last game finishes to start a new one.
|
||||
theGame.betsAccepted = false;
|
||||
await SaveKrashState(theGame);
|
||||
|
||||
//start the display of the game
|
||||
|
||||
//change these to change the speed of the game
|
||||
decimal growthRate = 1.02m;
|
||||
decimal growthAcceleration = 1.00185m;
|
||||
await _kfChatBot.KfClient.DeleteMessageAsync(msg.ChatMessageUuid!);
|
||||
msg = await _kfChatBot.SendChatMessageAsync($"[center][b][size=200][color=limegreen]{theGame.currentMulti}x");
|
||||
decimal defaultGrowth = 0.01m;
|
||||
interval = TimeSpan.FromSeconds(0.1);
|
||||
timer = new PeriodicTimer(interval);
|
||||
while (await timer.WaitForNextTickAsync(_ct))
|
||||
{
|
||||
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid!, $"[center][b][size=200][color=limegreen]{theGame.currentMulti}x");
|
||||
theGame.currentMulti += defaultGrowth;
|
||||
defaultGrowth *= growthRate;
|
||||
growthRate *= growthAcceleration;
|
||||
if (theGame.currentMulti >= theGame.finalMulti) break;
|
||||
}
|
||||
//at this point the game crashes and everybody who did not cash out or pre bet on a multi will have balance subtracted, winners will be paid out.
|
||||
await _kfChatBot.KfClient.EditMessageAsync(msg.ChatMessageUuid!, $"[center][b][size=200][color=red]{theGame.finalMulti}x");
|
||||
foreach (var bet in theGame.bets)
|
||||
{
|
||||
if (bet.multi <= theGame.finalMulti)
|
||||
{
|
||||
//you win
|
||||
decimal payout = theGame.currentMulti * bet.wager - bet.wager;
|
||||
var newBalance = await Money.NewWagerAsync(bet.gambler.Id, bet.wager, payout, WagerGame.Krash);
|
||||
await _kfChatBot.SendChatMessageAsync(
|
||||
$"{bet.gambler.User.FormatUsername()}, you [color=limegreen][b]won[/b][/color] {await payout.FormatKasinoCurrencyAsync()}!",
|
||||
true, autoDeleteAfter: TimeSpan.FromSeconds(10));
|
||||
if (_kfChatBot.BotServices.KasinoShop != null)
|
||||
{
|
||||
await _kfChatBot.BotServices.KasinoShop.ProcessWagerTracking(bet.gambler, WagerGame.Krash, bet.wager,
|
||||
payout, newBalance);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//automatically lose, no pre entered multi or it was greater than the final multi and failed to cash out
|
||||
var newBalance = await Money.NewWagerAsync(bet.gambler.Id, bet.wager, -bet.wager, WagerGame.Krash);
|
||||
await _kfChatBot.SendChatMessageAsync(
|
||||
$"{bet.gambler.User.FormatUsername()}, you [color=red][b]lost[/b][/color] {await bet.wager.FormatKasinoCurrencyAsync()}!",
|
||||
true, autoDeleteAfter: TimeSpan.FromSeconds(10));
|
||||
if (_kfChatBot.BotServices.KasinoShop != null)
|
||||
{
|
||||
await _kfChatBot.BotServices.KasinoShop.ProcessWagerTracking(bet.gambler, WagerGame.Krash, bet.wager,
|
||||
-bet.wager, newBalance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//now close the game
|
||||
await _kfChatBot.KfClient.DeleteMessageAsync(msg.ChatMessageUuid!);
|
||||
await RemoveKrashState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class KasinoKrashModel
|
||||
{
|
||||
public GamblerDbModel creator;
|
||||
public decimal finalMulti = 0;
|
||||
public decimal currentMulti = 1.01m;
|
||||
public List<KrashBet> bets = new();
|
||||
public decimal HOUSE_EDGE = 0.98m;
|
||||
public bool betsAccepted = true;
|
||||
public bool krashAccepted = false;
|
||||
public KasinoKrashModel(GamblerDbModel creator)
|
||||
{
|
||||
this.creator = creator;
|
||||
finalMulti = GetLinearWeightedRandom(1.01, 25000);
|
||||
}
|
||||
|
||||
private decimal GetLinearWeightedRandom(double minValue, double maxValue)
|
||||
{
|
||||
var random = RandomShim.Create(StandardRng.Create());
|
||||
double r = random.NextDouble(); // Returns 0.0 to 1.0
|
||||
|
||||
// The core 1/x logic
|
||||
double result = 1.0 / (1.0 - r);
|
||||
|
||||
// Clamp the result to your specific range
|
||||
if (result < minValue) result = minValue;
|
||||
if (result > maxValue) result = maxValue;
|
||||
|
||||
return (decimal)result;
|
||||
}
|
||||
}
|
||||
|
||||
public class KrashBet
|
||||
{
|
||||
public required GamblerDbModel gambler{ get; set;}
|
||||
public required decimal wager { get; set; }
|
||||
public required decimal multi { get; set; }
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
_krashTimerTask?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ public class KasinoMines
|
||||
value += "[br]";
|
||||
}
|
||||
|
||||
value += $"{Creator.User.FormatUsername()}";
|
||||
value += $"{Creator.User.FormatUsername()} [ditto]!mines 1[/ditto] [ditto]!mines cashout[/ditto]";
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -330,6 +330,7 @@ public class KasinoMines
|
||||
else str += "⬜";
|
||||
|
||||
}
|
||||
str += "[br]";
|
||||
}
|
||||
await _kfChatBot.KfClient.EditMessageAsync(game.LastMessageId!, str);
|
||||
var net = payout - game.Wager;
|
||||
|
||||
Reference in New Issue
Block a user