From 61e47ad59171f9a6db1a4f5ab032002ea2ffb372 Mon Sep 17 00:00:00 2001 From: alogindtractor <251821224+A-Log-In-D-Tractor@users.noreply.github.com> Date: Fri, 9 Jan 2026 16:53:52 -0800 Subject: [PATCH] fix plinko spam, allow multiple slot spins within the same image (#40) * spam reduction spam reduction * Update SlotsCommand to handle multiple spins Update SlotsCommand to handle multiple spins --- .../Commands/Kasino/PlinkoCommand.cs | 18 +++++----- .../Commands/Kasino/SlotsCommand.cs | 33 ++++++++++++++----- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/KfChatDotNetBot/Commands/Kasino/PlinkoCommand.cs b/KfChatDotNetBot/Commands/Kasino/PlinkoCommand.cs index 2c773d0..926053b 100644 --- a/KfChatDotNetBot/Commands/Kasino/PlinkoCommand.cs +++ b/KfChatDotNetBot/Commands/Kasino/PlinkoCommand.cs @@ -172,6 +172,8 @@ public class PlinkoCommand : ICommand } breakCounter = 0; var logger = LogManager.GetCurrentClassLogger(); + string lastPayoutMessage = ""; + string PlinkoMessage = ""; while (ballsNotInPlay.Count > 0 || ballsInPlay.Count > 0) { breakCounter++; @@ -182,7 +184,8 @@ public class PlinkoCommand : ICommand ballsInPlay.Add(ballsNotInPlay[0]); ballsNotInPlay.RemoveAt(0); } - await botInstance.KfClient.EditMessageAsync(plinkoMessageID.ChatMessageId!.Value,PlinkoBoardDisplay(ballsInPlay)); + PlinkoMessage = PlinkoBoardDisplay(ballsInPlay) + "[br]" + lastPayoutMessage; + await botInstance.KfClient.EditMessageAsync(plinkoMessageID.ChatMessageId!.Value,PlinkoMessage); if (ballsInPlay[0].POSITION.row == DIFFICULTY - 1) //once your ball has reached the bottom calculate the payout { currentPayout = wager * PlinkoPayoutBoard[ballsInPlay[0].POSITION.col]; @@ -190,13 +193,11 @@ public class PlinkoCommand : ICommand if (currentPayout == wager * 25) logger.Info($"Plinko: Max win on plinko, ball position: ({ballsInPlay[0].POSITION.row}, {ballsInPlay[0].POSITION.col})"); if (currentPayout > wager) { - await botInstance.SendChatMessageAsync( - $"{user.FormatUsername()}, you [color={settings[BuiltIn.Keys.KiwiFarmsGreenColor].Value!}]won[/color] ${currentPayout} KKK from a plinko ball worth {wager}!", true, autoDeleteAfter: TimeSpan.FromSeconds(5)); + lastPayoutMessage = ($"{user.FormatUsername()}, you [color={settings[BuiltIn.Keys.KiwiFarmsGreenColor].Value!}]won[/color] ${currentPayout} KKK from a plinko ball worth {wager}!"); } else { - await botInstance.SendChatMessageAsync( - $"{user.FormatUsername()}, you [color={settings[BuiltIn.Keys.KiwiFarmsRedColor].Value!}]lost[/color] ${wager-currentPayout} KKK from a plinko ball worth {wager}.", true, autoDeleteAfter: TimeSpan.FromSeconds(5)); + lastPayoutMessage = ($"{user.FormatUsername()}, you [color={settings[BuiltIn.Keys.KiwiFarmsRedColor].Value!}]lost[/color] ${wager-currentPayout} KKK from a plinko ball worth {wager}."); } ballsInPlay.RemoveAt(0); } @@ -205,9 +206,10 @@ public class PlinkoCommand : ICommand ball.Iterate(); } - await Task.Delay(250, ctx); - await botInstance.KfClient.EditMessageAsync(plinkoMessageID.ChatMessageId!.Value,PlinkoBoardDisplay(ballsInPlay)); - await Task.Delay(250, ctx); + await Task.Delay(300, ctx); + PlinkoMessage = PlinkoBoardDisplay(ballsInPlay) + "[br]" + lastPayoutMessage; + await botInstance.KfClient.EditMessageAsync(plinkoMessageID.ChatMessageId!.Value, PlinkoMessage); + await Task.Delay(300, ctx); } var newBalance = await Money.NewWagerAsync(gambler.Id, wager*numberOfBalls, payout-(wager*numberOfBalls), WagerGame.Plinko, ct: ctx); diff --git a/KfChatDotNetBot/Commands/Kasino/SlotsCommand.cs b/KfChatDotNetBot/Commands/Kasino/SlotsCommand.cs index 55d93a2..ad2c4d4 100644 --- a/KfChatDotNetBot/Commands/Kasino/SlotsCommand.cs +++ b/KfChatDotNetBot/Commands/Kasino/SlotsCommand.cs @@ -23,9 +23,13 @@ namespace KfChatDotNetBot.Commands.Kasino; public class SlotsCommand : ICommand { public List Patterns => [ + new Regex(@"^slots (?\d+) (?\d+)$", RegexOptions.IgnoreCase), + new Regex(@"^slots (?\d+\.\d+) (?\d+)$", RegexOptions.IgnoreCase), new Regex(@"^slots (?\d+)$", RegexOptions.IgnoreCase), new Regex(@"^slots (?\d+\.\d+)$", RegexOptions.IgnoreCase), new Regex("^slots$", RegexOptions.IgnoreCase), + new Regex(@"^sluts (?\d+) (?\d+)$", RegexOptions.IgnoreCase), + new Regex(@"^sluts (?\d+\.\d+) (?\d+)$", RegexOptions.IgnoreCase), new Regex(@"^sluts (?\d+)$", RegexOptions.IgnoreCase), new Regex(@"^sluts (?\d+\.\d+)$", RegexOptions.IgnoreCase), new Regex("^sluts", RegexOptions.IgnoreCase) @@ -66,11 +70,22 @@ public class SlotsCommand : ICommand return; } + int spins = 0; + if (!arguments.TryGetValue("spins", out var spinsArg)) spins = 1; + else spins = Convert.ToInt32(spinsArg.Value); + + if (spins < 1 || spins > 10) + { + await botInstance.SendChatMessageAsync($"{user.FormatUsername()} you can only do between 1 and 10 spins.", true, autoDeleteAfter: TimeSpan.FromSeconds(30)); + return; + } + + var wager = Convert.ToDecimal(amount.Value); 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 (gambler.Balance < wager) + if (gambler.Balance < wager * spins) { await botInstance.SendChatMessageAsync( $"{user.FormatUsername()}, your balance of {await gambler.Balance.FormatKasinoCurrencyAsync()} isn't enough for this wager.", @@ -82,7 +97,7 @@ public class SlotsCommand : ICommand using (var board = new KiwiSlotBoard(wager)) { board.LoadAssets(); - board.ExecuteGameLoop(); + board.ExecuteGameLoop(spins); using (var finalImageStream = board.ExportAndCleanup()) { if (finalImageStream == null) @@ -101,17 +116,17 @@ public class SlotsCommand : ICommand BuiltIn.Keys.KiwiFarmsGreenColor, BuiltIn.Keys.KiwiFarmsRedColor ]); decimal newBalance; - if (winnings == 0) //dud spin + if (winnings == 0) //dud spin(s) { - newBalance = await Money.NewWagerAsync(gambler.Id, wager, -wager, WagerGame.Slots, ct: ctx); + newBalance = await Money.NewWagerAsync(gambler.Id, wager*spins, -wager*spins, WagerGame.Slots, ct: ctx); await botInstance.SendChatMessageAsync( $"{user.FormatUsername()} you [color={colors[BuiltIn.Keys.KiwiFarmsRedColor].Value}]lost[/color]. Current balance: {await newBalance.FormatKasinoCurrencyAsync()}", true, autoDeleteAfter: TimeSpan.FromSeconds(30)); return; } - winnings -= wager; - newBalance = await Money.NewWagerAsync(gambler.Id, wager, winnings, WagerGame.Slots, ct: ctx); + winnings -= wager*spins; + newBalance = await Money.NewWagerAsync(gambler.Id, wager*spins, winnings, WagerGame.Slots, ct: ctx); await botInstance.SendChatMessageAsync( $"{user.FormatUsername()}, you [color={colors[BuiltIn.Keys.KiwiFarmsGreenColor].Value}]won[/color] {await winnings.FormatKasinoCurrencyAsync()}! Current balance: {await newBalance.FormatKasinoCurrencyAsync()}", true, autoDeleteAfter: TimeSpan.FromSeconds(30)); } @@ -307,7 +322,7 @@ public class SlotsCommand : ICommand AnimatedImage.Frames.RemoveFrame(0); } - public void ExecuteGameLoop(int featureSpins = 0) + public void ExecuteGameLoop(int spins, int featureSpins = 0) { GeneratePreBoard(featureSpins); var fCount = 0; @@ -322,7 +337,7 @@ public class SlotsCommand : ICommand ProcessReelsAndWins(); var total = _activeFeatureTier switch { 3 => 3, 4 => 5, 5 => 10, _ => 0 }; - if (featureSpins == 0) for (var s = 1; s <= total; s++) ExecuteGameLoop(s); + if (featureSpins == 0) for (var s = 1; s <= total; s++) ExecuteGameLoop(1,s); } private void ProcessReelsAndWins() @@ -410,4 +425,4 @@ public class SlotsCommand : ICommand AnimatedImage?.Dispose(); } } -} \ No newline at end of file +}