From 79442352fa9154468eeaf3f29e10d3aa3c9921a2 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Mon, 31 Jan 2022 23:24:03 +0700 Subject: [PATCH] Improvements to hacker trainer, fixed bug selling arsenal items --- Bot/HackerBattle.fs | 1 - Bot/Store.fs | 2 +- Bot/Trainer.fs | 84 ++++++++++++++++++++++++++++++--------------- Shared/Shared.fs | 28 ++++++++++++--- 4 files changed, 80 insertions(+), 35 deletions(-) diff --git a/Bot/HackerBattle.fs b/Bot/HackerBattle.fs index ab7e659..d4ae65d 100644 --- a/Bot/HackerBattle.fs +++ b/Bot/HackerBattle.fs @@ -19,7 +19,6 @@ let getTimeTillCooldownFinishes (timespan : TimeSpan) timestamp = else $"{timeRemaining.Seconds} seconds" - let checkIfPlayerIsAttackingThemselves defender attacker = match attacker.DiscordId = defender.DiscordId with | true -> Error "You think you're clever? You can't hack yourself, pal." diff --git a/Bot/Store.fs b/Bot/Store.fs index 28fe2a8..2d7faae 100644 --- a/Bot/Store.fs +++ b/Bot/Store.fs @@ -85,7 +85,7 @@ let updateArsenal player salePrice updatedArsenal = { player with Bank = player. let sellItem (event : ComponentInteractionCreateEventArgs) player itemId = async { let item = armoury |> Array.find (fun i -> i.Id = itemId) - let updatedPlayer = { player with Bank = player.Bank + item.Cost ; Arsenal = player.Arsenal |> Array.filter (fun w -> w.Id = itemId)} + let updatedPlayer = { player with Bank = player.Bank + item.Cost ; Arsenal = player.Arsenal |> Array.filter (fun w -> w.Id <> itemId)} do! DbService.updatePlayer updatedPlayer let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true diff --git a/Bot/Trainer.fs b/Bot/Trainer.fs index 3c30768..bd23b60 100644 --- a/Bot/Trainer.fs +++ b/Bot/Trainer.fs @@ -26,6 +26,13 @@ let sendInitialEmbed (client : DiscordClient) = |> Async.Ignore } |> Async.RunSynchronously +let step1Msg = { + ButtonId = "Trainer-2" + ButtonText = "Show me" + Message = "First time, eh? Beautopia is a dangerous place. I'm going to teach you how to protect yourself from other degenerates. " + + "And in the process, I'll also show you how to hack some sheeple, so you can earn some cash." +} + let handleTrainerStep1 (event : ComponentInteractionCreateEventArgs) = async { let! maybePlayer = DbService.tryFindPlayer event.User.Id @@ -33,20 +40,10 @@ let handleTrainerStep1 (event : ComponentInteractionCreateEventArgs) = do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate) |> Async.AwaitTask match maybePlayer with - | Some player when player.Arsenal |> Array.exists (fun w -> w.Type = Hack) - && player.Arsenal |> Array.exists (fun w -> w.Type = Shield) -> - let msg = "First time, eh? Beautopia is a dangerous place. I'm going to teach you how to protect yourself from other degenerates. " - + "And in the process, I'll also show you how to hack some sheeple, so you can earn some cash." - do! Message.sendFollowUpMessageWithButton event "Trainer-2" msg - | Some player -> - let missingItem = - if player.Arsenal |> Array.exists (fun w -> w.Type = Hack) - then "Shields" - else "Hacks" - let msg = $"Looks like you're missing {missingItem}. Go to the store and purchase some before proceeding." - do! Message.sendFollowUpMessage event msg + | Some _ -> + do! Message.sendFollowUpMessageWithButton event step1Msg | None -> - let msg = "An error occurred, please contact a moderator" + let msg = "Looks like an error occurred, you're not a registered degenerate. Please contact a moderator." do! Message.sendFollowUpMessage event msg } @@ -56,9 +53,16 @@ let handleTrainerStep2 (event : ComponentInteractionCreateEventArgs) = match result with | Some player -> let weaponName = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name - do! Message.sendInteractionEvent event + do! Message.updateMessageWithGreyedOutButtons event step1Msg + + let shieldMessage = + if Player.shields player |> Array.isEmpty + then $"You do not have any Shields in your arsenal, here's a {defaultShield.Name} you can use for now" + else $"You currently have {weaponName} in your arsenal" + + do! Message.sendFollowUpMessage event ($"First things first, let's get your system protected. Let's enable a shield to protect you from potential hackers. " - + $"You currently have {weaponName} in your arsenal. To enable it and protect your system, you can use the `/defend` slash command to choose a shield." + + $"{shieldMessage}. To enable it and protect your system, you can use the `/defend` slash command to choose a shield." + $"\n\nRun the `/defend` command now and then select '{weaponName}'.") | None -> do! Message.sendFollowUpMessage event $"Something went wrong, please contact a moderator" @@ -88,6 +92,13 @@ let defend (ctx : InteractionContext) = } |> Async.StartAsTask :> Task +let handleDefenseMsg = { + ButtonId = "Trainer-4" + ButtonText = "Got it" + Message = "I wasn't able to hack you. Great job! Because you had your system protected when I tried to hack you, you took some money from me. " + + "Shields only protect you for a certain amount of time, so remember to keep your system protected at all times." +} + let handleDefense (event : ComponentInteractionCreateEventArgs) = let sendMessage' = Message.sendFollowUpMessage event async { @@ -105,9 +116,7 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) = do! Async.Sleep 4000 do! sendMessage' $"Hacking attempt failed! {player.Name} defended hack from Degenz-Trainer and took {prize} from them! " do! Async.Sleep 3000 - let msg = ("I wasn't able to hack you. Great job! Because you had your system protected when I tried to hack you, you took some money from me. " - + "Shields only protect you for a certain amount of time, so remember to keep your system protected at all times.") - do! Message.sendFollowUpMessageWithButton event "Trainer-4" msg + do! Message.sendFollowUpMessageWithButton event handleDefenseMsg | None -> do! sendMessage' $"Something went wrong, please contact a moderator" } @@ -118,8 +127,15 @@ let handleTrainerStep4 (event : ComponentInteractionCreateEventArgs) = match result with | Some player -> let weaponName = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name - do! Message.sendInteractionEvent event - ($"Next why don't you try hacking me. You currently have {weaponName} equipped. To hack me and get some money, " + do! Message.updateMessageWithGreyedOutButtons event handleDefenseMsg + + let hackMessage = + if Player.shields player |> Array.isEmpty + then $"You do not have any Hacks in your arsenal, here's a {defaultHack.Name} you can use for now" + else $"You currently have {weaponName} in your arsenal" + + do! Message.sendFollowUpMessage event + ($"Next why don't you try hacking me. {hackMessage}. To hack me and get some money, " + $" you can use the '/hack' slash command and select a user to hack, then choose the hack attack you wish to use." + $"\n\nRun the `/hack` command now and pick me as your target, then click on the '{weaponName}' button.") | None -> @@ -132,7 +148,11 @@ let attack (ctx : InteractionContext) (target : DiscordUser) = let! playerResult = DbService.tryFindPlayer ctx.Member.Id match isRightTarget , playerResult with | true , Some player -> - let embed = Embeds.pickHack "Trainer-5" player player + let playerWithAttacks = + match player.Arsenal with + | [||] -> { player with Arsenal = [| defaultHack |] } + | _ -> player + let embed = Embeds.pickHack "Trainer-5" playerWithAttacks player do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed) |> Async.AwaitTask @@ -140,7 +160,7 @@ let attack (ctx : InteractionContext) (target : DiscordUser) = let builder = DiscordInteractionResponseBuilder() builder.Content <- "You picked the wrong target, you dufus. Try again, this time pick me!" - builder.AsEphemeral true |> ignore + builder.IsEphemeral <- true do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask @@ -155,6 +175,14 @@ let attack (ctx : InteractionContext) (target : DiscordUser) = } |> Async.StartAsTask :> Task +let handleAttackMsg = { + ButtonId = "Trainer-6" + ButtonText = "Hell yeah" + Message = "I think we're done. You are going to need more hacks and shields if you want to survive in this crazy world. " + + "Remember to go check out the store and purchase whatever you need to add to your arsenal." + + "\n\nAlright you degenerate, off you go!" +} + let handleAttack (event : ComponentInteractionCreateEventArgs) = let sendMessage' = Message.sendFollowUpMessage event async { @@ -172,10 +200,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) = do! sendMessage' ("Look at that, you are now officially an elite haxor! By successfully hacking other people you can earn GoodBoyTokenz. " + "Hacks take time to recover so check back in later once you've used all your hacks.") do! Async.Sleep 7000 - let msg = ("I think we're done. You are going to need more hacks and shields if you want to survive in this crazy world. " - + "Remember to go check out the store and purchase whatever you need to add to your arsenal." - + "\n\nAlright you degenerate, off you go!") - do! Message.sendFollowUpMessageWithButton event "Trainer-6" msg + do! Message.sendFollowUpMessageWithButton event handleAttackMsg | None -> do! sendMessage' $"Something went wrong, please contact a moderator" } @@ -186,10 +211,13 @@ let handleTrainerStep6 (event : ComponentInteractionCreateEventArgs) = // let role = event.Guild.GetRole(GuildEnvironment.roleTrainee) // do! membr.RevokeRoleAsync(role) |> Async.AwaitTask - let builder = DiscordInteractionResponseBuilder() + let builder = DiscordFollowupMessageBuilder() + builder.IsEphemeral <- true builder.Content <- "Get out of here!" - do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) + do! Message.updateMessageWithGreyedOutButtons event handleAttackMsg + do! event.Interaction.CreateFollowupMessageAsync(builder) |> Async.AwaitTask + |> Async.Ignore } let handleButtonEvent (event : ComponentInteractionCreateEventArgs) = diff --git a/Shared/Shared.fs b/Shared/Shared.fs index ed90a9d..0390613 100644 --- a/Shared/Shared.fs +++ b/Shared/Shared.fs @@ -114,7 +114,7 @@ Bank: {p.Bank}" let constructButtons (actionType: string) (playerInfo: string) (weapons: BattleItem array) = weapons - |> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Primary, $"{actionType}-{w.Id}-{playerInfo}", $"{w.Name}")) + |> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Success, $"{actionType}-{w.Id}-{playerInfo}", $"{w.Name}")) let modifyPlayerBank player amount = { player with Bank = max (player.Bank + amount) 0 } @@ -122,6 +122,12 @@ let armoury = let file = System.IO.File.ReadAllText("Items.json") JsonConvert.DeserializeObject(file) +type InteractiveMessage = { + ButtonId : string + ButtonText : string + Message : string +} + module Message = let sendFollowUpMessage (event : ComponentInteractionCreateEventArgs) msg = async { @@ -145,18 +151,30 @@ module Message = |> Async.Ignore } - let sendFollowUpMessageWithButton (event : ComponentInteractionCreateEventArgs) buttonId msg = + let sendFollowUpMessageWithButton (event : ComponentInteractionCreateEventArgs) interactiveMessage = async { let builder = DiscordFollowupMessageBuilder() - let button = DiscordButtonComponent(ButtonStyle.Primary, buttonId, "Got it") :> DiscordComponent + let button = DiscordButtonComponent(ButtonStyle.Success, interactiveMessage.ButtonId, interactiveMessage.ButtonText) :> DiscordComponent builder.AddComponents [| button |] |> ignore builder.IsEphemeral <- true - builder.Content <- msg + builder.Content <- interactiveMessage.Message do! event.Interaction.CreateFollowupMessageAsync(builder) |> Async.AwaitTask |> Async.Ignore } + let updateMessageWithGreyedOutButtons (event : ComponentInteractionCreateEventArgs) interactiveMessage = + async { + let builder = DiscordInteractionResponseBuilder() + let button = DiscordButtonComponent(ButtonStyle.Success, interactiveMessage.ButtonId, interactiveMessage.ButtonText, true) :> DiscordComponent + builder.AddComponents [| button |] |> ignore + builder.IsEphemeral <- true + builder.Content <- interactiveMessage.Message + do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) + |> Async.AwaitTask + |> Async.Ignore + } + let sendInteractionEvent (event : ComponentInteractionCreateEventArgs) msg = async { let builder = DiscordInteractionResponseBuilder() @@ -168,7 +186,7 @@ module Message = let sendInteractionEventWithButton (event : ComponentInteractionCreateEventArgs) buttonId msg = async { let builder = DiscordInteractionResponseBuilder() - let button = DiscordButtonComponent(ButtonStyle.Primary, buttonId, "Got it") :> DiscordComponent + let button = DiscordButtonComponent(ButtonStyle.Success, buttonId, "Got it") :> DiscordComponent builder.AddComponents [| button |] |> ignore builder.IsEphemeral <- true builder.Content <- msg