Make most commands deferred/follow up so they don't fail. bug fixes

This commit is contained in:
Joseph Ferano 2022-02-03 02:59:11 +07:00
parent 12ba17de30
commit cd15a08e37
7 changed files with 162 additions and 165 deletions

View File

@ -1,23 +1,24 @@
module Degenz.Embeds
open System
open DSharpPlus.EventArgs
open Degenz.Types
open DSharpPlus.Entities
open AsciiTableFormatter
let hackGif = "https://s10.gifyu.com/images/Hacker-Degenz-V2.gif"
let shieldGif = "https://s10.gifyu.com/images/Defense-Degenz-V2.gif"
let hackGif = "https://s10.gifyu.com/images/Hacker-Degenz-V20ce8eb832734aa62-min.gif"
let shieldGif = "https://s10.gifyu.com/images/Defense-Degenz-V2-min.gif"
let getHackGif = function
| HackId.Virus -> "https://s10.gifyu.com/images/Attack-DegenZ.gif"
| HackId.RemoteAccess -> "https://s10.gifyu.com/images/Mind-Control-Degenz-V2.gif"
| HackId.Worm -> "https://s10.gifyu.com/images/WormBugAttack_Degenz.gif"
| HackId.Virus -> "https://s10.gifyu.com/images/Attack-DegenZ-1.gif"
| HackId.RemoteAccess -> "https://s10.gifyu.com/images/Mind-Control-Degenz-V2-min.gif"
| HackId.Worm -> "https://s10.gifyu.com/images/WormBugAttack_Degenz-min.gif"
| _ -> hackGif
let getShieldGif = function
| ShieldId.Firewall -> "https://s10.gifyu.com/images/Defense-GIF-1-Degenz.gif"
| ShieldId.Encryption -> "https://s10.gifyu.com/images/Encryption-Degenz-V2.gif"
| ShieldId.Cypher -> "https://s10.gifyu.com/images/Matrix_Degenz.gif"
| ShieldId.Firewall -> "https://s10.gifyu.com/images/Defense-GIF-1-Degenz-min.gif"
| ShieldId.Encryption -> "https://s10.gifyu.com/images/Encryption-Degenz-V2-1-min.gif"
| ShieldId.Cypher -> "https://s10.gifyu.com/images/Cypher-Smaller.gif"
| _ -> shieldGif
@ -40,10 +41,10 @@ let pickDefense actionId player =
let embed =
DiscordEmbedBuilder()
.WithColor(DiscordColor.Blurple)
.WithDescription("Pick a defense to mount for 10 hours")
.WithDescription("Pick a shield to protect yourself from hacks")
.WithImageUrl(shieldGif)
DiscordInteractionResponseBuilder()
DiscordFollowupMessageBuilder()
.AddComponents(buttons)
.AddEmbed(embed)
.AsEphemeral true
@ -59,21 +60,12 @@ let pickHack actionId attacker defender =
.WithDescription("Pick the hack that you want to use")
.WithImageUrl(hackGif)
DiscordInteractionResponseBuilder()
DiscordFollowupMessageBuilder()
.AddComponents(buttons)
.AddEmbed(embed.Build())
.AsEphemeral true
let responseSuccessfulHack defenderName hack prize =
let embed = DiscordEmbedBuilder()
embed.ImageUrl <- getHackGif hack
DiscordInteractionResponseBuilder()
.WithContent($"Successfully hacked {defenderName} using {hack}! You just won {prize} GoodBoyTokenz!")
.AddEmbed(embed.Build())
.AsEphemeral(true)
let responseSuccessfulHackTrainer (hack : BattleItem) =
let responseSuccessfulHack (hack : BattleItem) =
let embed = DiscordEmbedBuilder()
embed.ImageUrl <- getHackGif (enum<HackId>(hack.Id))
@ -82,11 +74,11 @@ let responseSuccessfulHackTrainer (hack : BattleItem) =
.AddEmbed(embed.Build())
.AsEphemeral(true)
let responseCreatedShield shield =
DiscordInteractionResponseBuilder()
.AddEmbed(DiscordEmbedBuilder().WithImageUrl(getShieldGif shield))
let responseCreatedShield (shield : BattleItem) =
DiscordFollowupMessageBuilder()
.AddEmbed(DiscordEmbedBuilder().WithImageUrl(getShieldGif (enum<ShieldId>(shield.Id))))
.AsEphemeral(true)
.WithContent($"Mounted a {shield} defense for 6 hours")
.WithContent($"Mounted {shield.Name} shield for {TimeSpan.FromMinutes(int shield.Cooldown).Hours} hours")
let responseCreatedShieldTrainer (shield : BattleItem) =
DiscordFollowupMessageBuilder()
@ -120,11 +112,14 @@ let storeListing store =
store
|> Array.groupBy (fun (bi : BattleItem) -> bi.Type)
|> Array.map (fun ( itemType , items ) ->
items
|> Array.map (fun item -> { Name = item.Name ; Cost = string item.Cost ; Class = string item.Class })
|> Formatter.Format
|> sprintf "**%As**\n``` %s ```" itemType
|> constructEmbed)
let msg =
items
|> Array.map (fun item -> { Name = item.Name ; Cost = string item.Cost ; Class = string item.Class })
|> Formatter.Format
|> sprintf "**%As**\n``` %s ```" itemType
DiscordEmbedBuilder()
.WithDescription(msg)
.Build())
DiscordInteractionResponseBuilder()
.AddEmbeds(embeds)

View File

@ -1,15 +1,24 @@
module Degenz.Game
open System
open System.Threading.Tasks
open DSharpPlus
open DSharpPlus.Entities
open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Degenz.DbService
open Microsoft.VisualBasic
let HackPrize = 10<GBT>
let ShieldPrize = 5<GBT>
let executePlayerInteraction (ctx : InteractionContext) (dispatch : PlayerData -> Async<unit>) =
async {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- "Content"
do! ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, builder)
|> Async.AwaitTask
let! playerResult = tryFindPlayer ctx.Member.Id
match playerResult with
| Some player -> do! dispatch player
@ -18,12 +27,17 @@ let executePlayerInteraction (ctx : InteractionContext) (dispatch : PlayerData -
:> Task
// TODO: Create an abstraction for these two helper functions
let executePlayerEvent (ctx : ComponentInteractionCreateEventArgs) (dispatch : PlayerData -> Async<unit>) =
let executePlayerEvent (event : ComponentInteractionCreateEventArgs) (dispatch : PlayerData -> Async<unit>) =
async {
let! playerResult = tryFindPlayer ctx.User.Id
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- "Content"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, builder)
|> Async.AwaitTask
let! playerResult = tryFindPlayer event.User.Id
match playerResult with
| Some player -> do! dispatch player
| None -> do! Messaging.sendInteractionEvent ctx "You are currently not a hacker, first use the /redpill command to become one"
| None -> do! Messaging.sendInteractionEvent event "You are currently not a hacker, first use the /redpill command to become one"
} |> Async.StartAsTask
:> Task

View File

@ -79,9 +79,10 @@ let successfulHack (event : ComponentInteractionCreateEventArgs) attacker defend
async {
do! updateCombatants attacker defender hack Game.HackPrize
let embed = Embeds.responseSuccessfulHack defender.Name hack Game.HackPrize
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
let embed = Embeds.responseSuccessfulHack (Armory.getItem (int hack))
do! event.Interaction.CreateFollowupMessageAsync(embed)
|> Async.AwaitTask
|> Async.Ignore
let builder = Embeds.eventSuccessfulHack event defender.DiscordId Game.HackPrize
let channel = event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle)
@ -122,28 +123,29 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
|> function
| Ok _ ->
let embed = Embeds.pickHack "Attack" attacker defender
ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
ctx.FollowUpAsync(embed)
|> Async.AwaitTask
|> Async.Ignore
| Error msg ->
let builder =
DiscordInteractionResponseBuilder()
DiscordFollowupMessageBuilder()
.WithContent(msg)
.AsEphemeral(true)
ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
ctx.FollowUpAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
| None -> do! sendSimpleResponse ctx "Your target is not connected to the network, they must join first by using the /redpill command"
})
let handleAttack (event : ComponentInteractionCreateEventArgs) =
async {
Game.executePlayerEvent event (fun attacker -> async {
let split = event.Id.Split("-")
let hack = enum<HackId>(int split.[1])
let ( resultId , targetId ) = UInt64.TryParse split.[2]
let! resultPlayer = DbService.tryFindPlayer event.User.Id
let! resultTarget = DbService.tryFindPlayer targetId
match resultPlayer , resultTarget , true , resultId with
| Some attacker , Some defender , true , true ->
match resultTarget , true , resultId with
| Some defender , true , true ->
do! attacker
|> Player.removeExpiredActions
|> checkForExistingTarget defender.DiscordId
@ -154,103 +156,78 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
|> function
| false -> successfulHack event attacker defender hack
| true -> failedHack event attacker defender hack
| Error msg ->
let builder =
DiscordInteractionResponseBuilder()
.WithContent(msg)
.AsEphemeral(true)
event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| _ ->
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- "Error occurred processing attack"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
| Error msg -> Messaging.sendFollowUpMessage event msg
| _ -> do! Messaging.sendFollowUpMessage event "Error occurred processing attack"
})
let defend (ctx : InteractionContext) =
Game.executePlayerInteraction ctx (fun player -> async {
if Player.shields player |> Array.length > 0 then
let embed = Embeds.pickDefense "Defend" player
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
do! ctx.FollowUpAsync(embed)
|> Async.AwaitTask
|> Async.Ignore
else
let builder = DiscordInteractionResponseBuilder()
builder.Content <- $"You currently do not have any Shields to protect you. Please go to the <#{GuildEnvironment.channelArmory}> and purchase one."
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
let msg = $"You currently do not have any Shields to protect you. Please go to the <#{GuildEnvironment.channelArmory}> and purchase one."
do! Messaging.sendFollowUpMessageFromCtx ctx msg
})
let handleDefense (event : ComponentInteractionCreateEventArgs) =
async {
Game.executePlayerEvent event (fun player -> async {
let split = event.Id.Split("-")
let shield = enum<ShieldId>(int split.[1])
let! playerResult = DbService.tryFindPlayer event.User.Id
match playerResult with
| Some player ->
let updatedDefenses = player |> Player.removeExpiredActions |> Player.defenses
let alreadyUsedShield = updatedDefenses |> Array.exists (fun d -> d.ActionId = int shield)
let shieldId = enum<ShieldId>(int split.[1])
let updatedDefenses = player |> Player.removeExpiredActions |> Player.defenses
let alreadyUsedShield = updatedDefenses |> Array.exists (fun d -> d.ActionId = int shieldId)
match alreadyUsedShield , updatedDefenses.Length < 2 with
| false , true ->
let embed = Embeds.responseCreatedShield shield
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask
let defense = { ActionId = int shield ; Type = Defense ; Timestamp = DateTime.UtcNow }
do! DbService.updatePlayer <| { player with Actions = Array.append [| defense |] player.Actions }
let builder = DiscordMessageBuilder()
builder.WithContent($"{event.User.Username} has protected their system!") |> ignore
let channel = event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle)
do! channel.SendMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
| _ , false ->
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
let timestamp = updatedDefenses |> Array.rev |> Array.head |> fun a -> a.Timestamp // This should be the next expiring timestamp
let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(6)) timestamp
builder.Content <- $"You are only allowed two shields at a time. Wait {cooldown} minutes to add another shield"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
do! DbService.updatePlayer <| { player with Actions = updatedDefenses }
| true , _ ->
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
let timestamp = updatedDefenses |> Array.find (fun d -> d.ActionId = int shield) |> fun a -> a.Timestamp
let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(6)) timestamp
builder.Content <- $"{shield} shield is already in use. Wait {cooldown} minutes to use this shield again"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
do! DbService.updatePlayer <| { player with Actions = updatedDefenses }
| _ ->
let builder = DiscordInteractionResponseBuilder()
match alreadyUsedShield , updatedDefenses.Length < 2 with
| false , true ->
let embed = Embeds.responseCreatedShield (Armory.getItem (int shieldId))
do! event.Interaction.CreateFollowupMessageAsync(embed)
|> Async.AwaitTask
|> Async.Ignore
let defense = { ActionId = int shieldId ; Type = Defense ; Timestamp = DateTime.UtcNow }
do! DbService.updatePlayer <| { player with Actions = Array.append [| defense |] player.Actions }
let builder = DiscordMessageBuilder()
builder.WithContent($"{event.User.Username} has protected their system!") |> ignore
let channel = event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle)
do! channel.SendMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
| _ , false ->
let builder = DiscordFollowupMessageBuilder()
builder.IsEphemeral <- true
builder.Content <- "Error parsing Button Id"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
let timestamp = updatedDefenses |> Array.rev |> Array.head |> fun a -> a.Timestamp // This should be the next expiring timestamp
let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(6)) timestamp
builder.Content <- $"You are only allowed two shields at a time. Wait {cooldown} minutes to add another shield"
do! event.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
do! DbService.updatePlayer <| { player with Actions = updatedDefenses }
| true , _ ->
let builder = DiscordFollowupMessageBuilder()
builder.IsEphemeral <- true
let timestamp = updatedDefenses |> Array.find (fun d -> d.ActionId = int shieldId) |> fun a -> a.Timestamp
let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(6)) timestamp
builder.Content <- $"{shieldId} shield is already in use. Wait {cooldown} minutes to use this shield again"
do! event.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
do! DbService.updatePlayer <| { player with Actions = updatedDefenses }
})
let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
let task =
match event.Id with
| id when id.StartsWith("Attack") -> handleAttack event
| id when id.StartsWith("Defend") -> handleDefense event
| id when id.StartsWith("Trainer") -> Trainer.handleButtonEvent event
| _ ->
async {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Incorrect Action identifier {event.Id}"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
async {
return! task
} |> Async.StartAsTask
:> Task
match event.Id with
| id when id.StartsWith("Attack") -> handleAttack event
| id when id.StartsWith("Defend") -> handleDefense event
| id when id.StartsWith("Trainer") -> Trainer.handleButtonEvent event |> Async.StartAsTask :> Task
| _ ->
task {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Incorrect Action identifier {event.Id}"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
type HackerGame() =
inherit ApplicationCommandModule ()
@ -273,7 +250,6 @@ type HackerGame() =
member this.TestAutoComplete (ctx : InteractionContext) =
async {
let builder = DiscordInteractionResponseBuilder()
// builder.WithContent("Not working")
builder.IsEphemeral <- true
do! ctx.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask

View File

@ -49,7 +49,7 @@
},
"Cost": 100,
"Power": 50,
"Cooldown": 240
"Cooldown": 600
},
{
"Id": 7,
@ -62,7 +62,7 @@
},
"Cost": 100,
"Power": 50,
"Cooldown": 240
"Cooldown": 600
},
{
"Id": 8,
@ -75,6 +75,6 @@
},
"Cost": 100,
"Power": 50,
"Cooldown": 240
"Cooldown": 600
}
]

View File

@ -25,11 +25,11 @@ let buyItem (ctx : InteractionContext) itemId =
if not playerHasItem then
let p = { player with Bank = newBalance ; Arsenal = Array.append [| item |] player.Arsenal }
do! DbService.updatePlayer p
do! sendSimpleResponse ctx $"Successfully purchased {item.Name}! You now have {newBalance} remaining"
do! sendFollowUpMessageFromCtx ctx $"Successfully purchased {item.Name}! You now have {newBalance} 💰$GBT remaining"
else
do! sendSimpleResponse ctx $"You already own this item!"
do! sendFollowUpMessageFromCtx ctx $"You already own this item!"
else
do! sendSimpleResponse ctx $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
do! sendFollowUpMessageFromCtx ctx $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
})
@ -37,7 +37,7 @@ let sell (ctx : InteractionContext) =
Game.executePlayerInteraction ctx (fun player -> async {
let hasInventoryToSell = Array.length player.Arsenal > 0
if hasInventoryToSell then
let builder = DiscordInteractionResponseBuilder()
let builder = DiscordFollowupMessageBuilder()
builder.AddEmbed (constructEmbed "Pick the item you wish to sell.") |> ignore
Array.chunkBySize 5 player.Arsenal
@ -50,8 +50,9 @@ let sell (ctx : InteractionContext) =
|> ignore)
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
do! ctx.FollowUpAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
else
do! sendSimpleResponse ctx "You currently have no inventory to sell"
})
@ -65,11 +66,11 @@ let handleBuyItem (ctx : InteractionContext) itemId =
if not playerHasItem then
let p = { player with Bank = newBalance ; Arsenal = Array.append [| item |] player.Arsenal }
do! DbService.updatePlayer p
do! sendSimpleResponse ctx $"Successfully purchased {item.Name}! You now have {newBalance} remaining"
do! sendFollowUpMessageFromCtx ctx $"Successfully purchased {item.Name}! You now have {newBalance} 💰$GBT remaining"
else
do! sendSimpleResponse ctx $"You already own this item!"
do! sendFollowUpMessageFromCtx ctx $"You already own this item!"
else
do! sendSimpleResponse ctx $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
do! sendFollowUpMessageFromCtx ctx $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
})
let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
@ -78,23 +79,25 @@ let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCrea
let item = Armory.getItem 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()
let builder = DiscordFollowupMessageBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Sold {item.Type} {item.Name} for {item.Cost}! Current Balance: {updatedPlayer.Bank}"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
do! event.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
})
let status (ctx : InteractionContext) =
Game.executePlayerInteraction ctx (fun player -> async {
let updatedPlayer = Player.removeExpiredActions player
let builder = DiscordInteractionResponseBuilder()
let builder = DiscordFollowupMessageBuilder()
let embed = DiscordEmbedBuilder()
embed.AddField("Arsenal", Messaging.statusFormat updatedPlayer) |> ignore
builder.AddEmbed(embed) |> ignore
builder.IsEphemeral <- true
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
do! ctx.FollowUpAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
do! DbService.updatePlayer updatedPlayer
})

View File

@ -30,14 +30,15 @@ let sendInitialEmbed (client : DiscordClient) =
let handleTrainerStep1 (event : ComponentInteractionCreateEventArgs) =
Game.executePlayerEvent event (fun player -> async {
let weaponName = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
let shieldMessage =
let shieldMessage , weaponName =
if Player.shields player |> Array.isEmpty
then $"You do not have any Shields in your arsenal, take this {defaultShield.Name}, you can use it for now.\n\n"
else $"Looks like you have `{weaponName}` in your arsenal… 👀\n\n"
then $"You do not have any Shields in your arsenal, take this {defaultShield.Name}, you can use it for now.\n\n" , defaultShield.Name
else
let name = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
$"Looks like you have `{name}` in your arsenal… 👀\n\n" , name
do! sendInteractionEvent event
do! sendFollowUpMessage event
("Beautopia© is a dangerous place...\n"
+ "Quick, put up a SHIELD 🛡 before another Degen hacks you, and steals your 💰$GBT.\n"
+ shieldMessage
@ -51,10 +52,12 @@ let defend (ctx : InteractionContext) =
match player.Arsenal with
| [||] -> { player with Arsenal = [| defaultShield |] }
| _ -> player
let embed = Embeds.pickDefense "Trainer-2" playerWithShields
do! ctx.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
do! ctx.FollowUpAsync(embed)
|> Async.AwaitTask
|> Async.Ignore
})
let handleDefenseMsg = {
@ -69,8 +72,6 @@ let handleDefenseMsg = {
let handleDefense (event : ComponentInteractionCreateEventArgs) =
Game.executePlayerEvent event (fun player -> async {
let sendMessage' = sendFollowUpMessage event
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask
let shield = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield
let embed = Embeds.responseCreatedShieldTrainer shield
do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
@ -84,20 +85,19 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) =
let handleTrainerStep3 (event : ComponentInteractionCreateEventArgs) =
Game.executePlayerEvent event (fun player -> async {
let weaponName = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
do! updateMessageWithGreyedOutButtons event handleDefenseMsg
let hackMessage =
let hackMessage , weaponName =
if Player.shields player |> Array.isEmpty
then $"You do not have any Hacks in your arsenal, take this {defaultHack.Name}, you can use it for now.\n\n"
else $"Looks like you have `{weaponName}` in your arsenal...\n\n"
then $"You do not have any Hacks in your arsenal, take this `{defaultHack.Name}`, you can use it for now.\n\n" , defaultHack.Name
else
let name = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultHack |> fun w -> w.Name
$"Looks like you have `{name}` in your arsenal...\n\n" , name
do! sendFollowUpMessage event
("Now lets **HACK!** 💻\n\n"
+ "I want you to **HACK ME**, and try to steal my 💰$GBT...\n\n"
+ hackMessage
+ "To deploy it, you need to run the `/hack` slash command.\n"
+ $"Type the `/hack` command now, then choose me - <@{GuildEnvironment.botHackerBattle}> as your target, and select - `{weaponName}`")
+ $"Type the `/hack` command now, then choose me - <@{GuildEnvironment.botHackerBattle}> as your target, and select `{weaponName}`")
})
let attack (ctx : InteractionContext) (target : DiscordUser) =
@ -111,26 +111,26 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
| _ -> player
let embed = Embeds.pickHack "Trainer-4" playerWithAttacks player
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
do! ctx.FollowUpAsync(embed)
|> Async.AwaitTask
|> Async.Ignore
| false ->
let builder = DiscordInteractionResponseBuilder()
let builder = DiscordFollowupMessageBuilder()
builder.Content <- "You picked the wrong target, you dufus. Try again, this time pick me!"
builder.IsEphemeral <- true
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
do! ctx.FollowUpAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
})
let handleAttack (event : ComponentInteractionCreateEventArgs) =
Game.executePlayerEvent event (fun player -> async {
let sendMessage' = sendFollowUpMessage event
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask
do! Async.Sleep 1000
let hack = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultHack
let embed = Embeds.responseSuccessfulHackTrainer hack
let embed = Embeds.responseSuccessfulHack hack
do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
do! Async.Sleep 3000
do! sendMessage'

View File

@ -137,17 +137,17 @@ module Messaging =
actions
|> Array.map (fun act ->
match act.Type with
| Attack atk -> $"Hacked {atk.Target} at {act.Timestamp.ToLongDateString()}"
| Attack atk -> $"Hacked {atk.Target.Name} at {act.Timestamp.ToShortTimeString()}"
| Defense ->
let item = Armory.getItem act.ActionId
let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromMinutes(int item.Cooldown))
let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromMinutes(int item.Cooldown)) act.Timestamp
$"{item.Name} active for {cooldown}")
|> String.concat "\n"
let statusFormat p =
$"**Hacks:** {Player.hacks p |> battleItemFormat}\n
**Shields:** {Player.shields p |> battleItemFormat}\n
**Hack Attacks:** {Player.attacks p |> actionFormat}\n
**Hack Attacks:**\n{Player.attacks p |> actionFormat}\n
**Active Shields:** {Player.defenses p |> actionFormat}"
let constructButtons (actionType: string) (playerInfo: string) (weapons: BattleItem array) =
@ -173,6 +173,16 @@ module Messaging =
|> Async.Ignore
}
let sendFollowUpMessageFromCtx (ctx : InteractionContext) msg =
async {
let builder = DiscordFollowupMessageBuilder()
builder.IsEphemeral <- true
builder.Content <- msg
do! ctx.FollowUpAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
}
let sendFollowUpMessageWithEmbed (event : ComponentInteractionCreateEventArgs) (embed : DiscordEmbed) msg =
async {
let builder =
@ -206,7 +216,6 @@ module Messaging =
builder.Content <- interactiveMessage.Message
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|> Async.AwaitTask
|> Async.Ignore
}
let sendInteractionEvent (event : ComponentInteractionCreateEventArgs) msg =