Implement new Trainer improvements and clean up a few more things

This commit is contained in:
Joseph Ferano 2022-02-01 22:45:27 +07:00
parent ef3d5c58f5
commit e772a6d6f3
11 changed files with 135 additions and 200 deletions

View File

@ -74,7 +74,7 @@ let run (client : DiscordClient) =
do! client.ConnectAsync () |> Async.AwaitTask do! client.ConnectAsync () |> Async.AwaitTask
} }
//Trainer.sendInitialEmbed hackerBattleBot Trainer.sendInitialEmbed hackerBattleBot
clients clients
|> Array.map run |> Array.map run

View File

@ -73,12 +73,12 @@ let responseSuccessfulHack defenderName hack prize =
.AddEmbed(embed.Build()) .AddEmbed(embed.Build())
.AsEphemeral(true) .AsEphemeral(true)
let responseSuccessfulHackTrainer defenderName (hack : BattleItem) prize = let responseSuccessfulHackTrainer (hack : BattleItem) =
let embed = DiscordEmbedBuilder() let embed = DiscordEmbedBuilder()
embed.ImageUrl <- getHackGif (enum<HackId>(hack.Id)) embed.ImageUrl <- getHackGif (enum<HackId>(hack.Id))
DiscordFollowupMessageBuilder() DiscordFollowupMessageBuilder()
.WithContent($"Successfully hacked {defenderName} using {hack.Name}! You just won {prize} GoodBoyTokenz!") .WithContent($"You successfully hacked <@{GuildEnvironment.botHackerBattle}> using {hack.Name}, and stole 💰$GBT {Game.HackPrize} from them!")
.AddEmbed(embed.Build()) .AddEmbed(embed.Build())
.AsEphemeral(true) .AsEphemeral(true)

View File

@ -1,10 +1,14 @@
module Degenz.Game module Degenz.Game
open System.Threading.Tasks open System.Threading.Tasks
open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands open DSharpPlus.SlashCommands
open Degenz.DbService open Degenz.DbService
let executePlayerAction (ctx : InteractionContext) (dispatch : PlayerData -> Async<unit>) = let HackPrize = 10<GBT>
let ShieldPrize = 5<GBT>
let executePlayerInteraction (ctx : InteractionContext) (dispatch : PlayerData -> Async<unit>) =
async { async {
let! playerResult = tryFindPlayer ctx.Member.Id let! playerResult = tryFindPlayer ctx.Member.Id
match playerResult with match playerResult with
@ -13,3 +17,13 @@ let executePlayerAction (ctx : InteractionContext) (dispatch : PlayerData -> Asy
} |> Async.StartAsTask } |> Async.StartAsTask
:> Task :> Task
// TODO: Create an abstraction for these two helper functions
let executePlayerEvent (ctx : ComponentInteractionCreateEventArgs) (dispatch : PlayerData -> Async<unit>) =
async {
let! playerResult = tryFindPlayer ctx.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"
} |> Async.StartAsTask
:> Task

View File

@ -16,5 +16,7 @@ let tokenHackerBattle = getVar "TOKEN_HACKER_BATTLE"
let tokenStore = getVar "TOKEN_STORE" let tokenStore = getVar "TOKEN_STORE"
let channelEventsHackerBattle = getId "CHANNEL_EVENTS_HACKER_BATTLE" let channelEventsHackerBattle = getId "CHANNEL_EVENTS_HACKER_BATTLE"
let channelTraining = getId "CHANNEL_TRAINING" let channelTraining = getId "CHANNEL_TRAINING"
let channelArmory = getId "CHANNEL_ARMORY"
let botHackerBattle = getId "BOT_HACKER_BATTLE" let botHackerBattle = getId "BOT_HACKER_BATTLE"
let botArmory = getId "BOT_ARMORY"
let roleTrainee = getId "ROLE_TRAINEE" let roleTrainee = getId "ROLE_TRAINEE"

View File

@ -46,12 +46,12 @@ let checkIfHackHasCooldown hackId attacker =
Ok attacker Ok attacker
else else
let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromMinutes(5)) mostRecentHackAttack let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromMinutes(5)) mostRecentHackAttack
let item = Armoury.battleItems |> Array.find (fun i -> i.Id = hackId) let item = Armory.battleItems |> Array.find (fun i -> i.Id = hackId)
Error $"{item.Name} is currently on cooldown, wait {cooldown} to use it again." Error $"{item.Name} is currently on cooldown, wait {cooldown} to use it again."
let checkIfInventoryIsEmpty attacker = let checkIfInventoryIsEmpty attacker =
match attacker.Arsenal with match attacker.Arsenal with
| [||] -> Error $"You currently do not have any Hacks to use against others. Please go to the store and purchase one." | [||] -> Error $"You currently do not have any Hacks to steal 💰$GBT from others. Please go to the <#{GuildEnvironment.channelArmory}> and purchase one."
| _ -> Ok attacker | _ -> Ok attacker
let calculateDamage (hack : BattleItem) (shield : BattleItem) = let calculateDamage (hack : BattleItem) (shield : BattleItem) =
@ -62,7 +62,7 @@ let calculateDamage (hack : BattleItem) (shield : BattleItem) =
let runHackerBattle defender hack = let runHackerBattle defender hack =
Player.defenses defender Player.defenses defender
|> Player.removeExpiredActions |> Player.removeExpiredActions
|> Array.map (fun dfn -> Armoury.battleItems |> Array.find (fun w -> w.Id = dfn.ActionId)) |> Array.map (fun dfn -> Armory.battleItems |> Array.find (fun w -> w.Id = dfn.ActionId))
|> Array.map (calculateDamage (hack)) |> Array.map (calculateDamage (hack))
|> Array.contains Weak |> Array.contains Weak
@ -79,15 +79,13 @@ let updateCombatants attacker defender hack prize =
let successfulHack (event : ComponentInteractionCreateEventArgs) attacker defender hack = let successfulHack (event : ComponentInteractionCreateEventArgs) attacker defender hack =
async { async {
let prize = 3<GBT> do! updateCombatants attacker defender hack Game.HackPrize
do! updateCombatants attacker defender hack prize let embed = Embeds.responseSuccessfulHack defender.Name hack Game.HackPrize
let embed = Embeds.responseSuccessfulHack defender.Name hack prize
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed) do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask |> Async.AwaitTask
let builder = Embeds.eventSuccessfulHack event defender.DiscordId prize let builder = Embeds.eventSuccessfulHack event defender.DiscordId Game.HackPrize
let channel = event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle) let channel = event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle)
do! channel.SendMessageAsync(builder) do! channel.SendMessageAsync(builder)
|> Async.AwaitTask |> Async.AwaitTask
@ -97,16 +95,15 @@ let successfulHack (event : ComponentInteractionCreateEventArgs) attacker defend
let failedHack (event : ComponentInteractionCreateEventArgs) attacker defender hack = let failedHack (event : ComponentInteractionCreateEventArgs) attacker defender hack =
async { async {
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
let prize = 2<GBT>
builder.IsEphemeral <- true builder.IsEphemeral <- true
builder.Content <- $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {prize} GoodBoyTokenz!" builder.Content <- $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {Game.ShieldPrize} GoodBoyTokenz!"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask |> Async.AwaitTask
do! updateCombatants attacker defender hack -prize do! updateCombatants attacker defender hack -Game.ShieldPrize
let builder = DiscordMessageBuilder() let builder = DiscordMessageBuilder()
builder.WithContent($"Hacking attempt failed! <@{defender.DiscordId}> defended hack from {event.User.Username} and took {prize} from them! ") |> ignore builder.WithContent($"Hacking attempt failed! <@{defender.DiscordId}> defended hack from {event.User.Username} and took {Game.ShieldPrize} from them! ") |> ignore
let channel = (event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle)) let channel = (event.Guild.GetChannel(GuildEnvironment.channelEventsHackerBattle))
do! channel.SendMessageAsync(builder) do! channel.SendMessageAsync(builder)
|> Async.AwaitTask |> Async.AwaitTask
@ -114,7 +111,7 @@ let failedHack (event : ComponentInteractionCreateEventArgs) attacker defender h
} }
let attack (ctx : InteractionContext) (target : DiscordUser) = let attack (ctx : InteractionContext) (target : DiscordUser) =
Game.executePlayerAction ctx (fun attacker -> async { Game.executePlayerInteraction ctx (fun attacker -> async {
let! defender = DbService.tryFindPlayer target.Id let! defender = DbService.tryFindPlayer target.Id
match defender with match defender with
| Some defender -> | Some defender ->
@ -151,7 +148,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
|> Result.bind (checkIfHackHasCooldown (int hack)) |> Result.bind (checkIfHackHasCooldown (int hack))
|> function |> function
| Ok _ -> | Ok _ ->
runHackerBattle defender (Armoury.getItem (int hack)) runHackerBattle defender (Armory.getItem (int hack))
|> function |> function
| false -> successfulHack event attacker defender hack | false -> successfulHack event attacker defender hack
| true -> failedHack event attacker defender hack | true -> failedHack event attacker defender hack
@ -171,14 +168,14 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
} }
let defend (ctx : InteractionContext) = let defend (ctx : InteractionContext) =
Game.executePlayerAction ctx (fun player -> async { Game.executePlayerInteraction ctx (fun player -> async {
if Player.shields player |> Array.length > 0 then if Player.shields player |> Array.length > 0 then
let embed = Embeds.pickDefense "Defend" player let embed = Embeds.pickDefense "Defend" player
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed) do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask |> Async.AwaitTask
else else
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
builder.Content <- $"You currently do not have any Shields to protect your system. Please go to the armoury and purchase one." 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 builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask |> Async.AwaitTask
@ -263,8 +260,8 @@ type HackerGame() =
else else
attack ctx target attack ctx target
[<SlashCommand("defend", "Create a passive defense that will last 24 hours")>] [<SlashCommand("shield", "Create a passive defense that will last 24 hours")>]
member this.DefendCommand (ctx : InteractionContext) = member this.ShieldCommand (ctx : InteractionContext) =
if ctx.Channel.Id = GuildEnvironment.channelTraining then if ctx.Channel.Id = GuildEnvironment.channelTraining then
Trainer.defend ctx Trainer.defend ctx
else else

View File

@ -12,8 +12,8 @@ module Commands =
let rand = System.Random(System.Guid.NewGuid().GetHashCode()) let rand = System.Random(System.Guid.NewGuid().GetHashCode())
let randHack = rand.Next(0, 3) let randHack = rand.Next(0, 3)
let randShield = rand.Next(6, 9) let randShield = rand.Next(6, 9)
let hack = Armoury.battleItems |> Array.find (fun i -> i.Id = randHack) let hack = Armory.battleItems |> Array.find (fun i -> i.Id = randHack)
let shield = Armoury.battleItems |> Array.find (fun i -> i.Id = randShield) let shield = Armory.battleItems |> Array.find (fun i -> i.Id = randShield)
{ DiscordId = membr { DiscordId = membr
Name = nickname Name = nickname
@ -72,7 +72,7 @@ module Commands =
// :> Task // :> Task
let status (ctx : InteractionContext) = let status (ctx : InteractionContext) =
Game.executePlayerAction ctx (fun player -> async { Game.executePlayerInteraction ctx (fun player -> async {
let updatedActions = Player.removeExpiredActions player.Actions let updatedActions = Player.removeExpiredActions player.Actions
let updatedPlayer = { player with Actions = updatedActions } let updatedPlayer = { player with Actions = updatedActions }
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()

View File

@ -14,7 +14,7 @@ type SlotMachine() =
[<SlashCommand("spin", "Want to try your luck?")>] [<SlashCommand("spin", "Want to try your luck?")>]
member this.Spin (ctx : InteractionContext) = member this.Spin (ctx : InteractionContext) =
Game.executePlayerAction ctx (fun player -> async { Game.executePlayerInteraction ctx (fun player -> async {
let sleepTime = 1000 let sleepTime = 1000
let random = Random(System.Guid.NewGuid().GetHashCode()) let random = Random(System.Guid.NewGuid().GetHashCode())
let results = [ random.Next(0, 3) ; random.Next(0, 3) ; random.Next(0, 3)] let results = [ random.Next(0, 3) ; random.Next(0, 3) ; random.Next(0, 3)]

View File

@ -12,13 +12,13 @@ open Degenz.Messaging
let viewStore (ctx : InteractionContext) = let viewStore (ctx : InteractionContext) =
async { async {
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, Embeds.storeListing Armoury.battleItems) do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, Embeds.storeListing Armory.battleItems)
|> Async.AwaitTask |> Async.AwaitTask
} |> Async.StartAsTask } |> Async.StartAsTask
:> Task :> Task
let buyItem (ctx : InteractionContext) itemType = let buyItem (ctx : InteractionContext) itemType =
Game.executePlayerAction ctx (fun player -> async { Game.executePlayerInteraction ctx (fun player -> async {
let embed = DiscordEmbedBuilder() let embed = DiscordEmbedBuilder()
// embed.Fields // embed.Fields
@ -28,7 +28,7 @@ let buyItem (ctx : InteractionContext) itemType =
}) })
let sell (ctx : InteractionContext) = let sell (ctx : InteractionContext) =
Game.executePlayerAction ctx (fun player -> async { Game.executePlayerInteraction ctx (fun player -> async {
let hasInventoryToSell = Array.length player.Arsenal > 0 let hasInventoryToSell = Array.length player.Arsenal > 0
if hasInventoryToSell then if hasInventoryToSell then
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
@ -52,7 +52,7 @@ let sell (ctx : InteractionContext) =
let sellItem (event : ComponentInteractionCreateEventArgs) player itemId = let sellItem (event : ComponentInteractionCreateEventArgs) player itemId =
async { async {
let item = Armoury.battleItems |> Array.find (fun i -> i.Id = itemId) let item = Armory.battleItems |> 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 do! DbService.updatePlayer updatedPlayer
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
@ -63,8 +63,8 @@ let sellItem (event : ComponentInteractionCreateEventArgs) player itemId =
} }
let handleBuyItem (ctx : InteractionContext) itemId = let handleBuyItem (ctx : InteractionContext) itemId =
Game.executePlayerAction ctx (fun player -> async { Game.executePlayerInteraction ctx (fun player -> async {
let item = Armoury.battleItems |> Array.find (fun w -> w.Id = itemId) let item = Armory.battleItems |> Array.find (fun w -> w.Id = itemId)
let newBalance = player.Bank - item.Cost let newBalance = player.Bank - item.Cost
if newBalance >= 0<GBT> then if newBalance >= 0<GBT> then
let playerHasItem = player.Arsenal |> Array.exists (fun w -> item.Id = w.Id) let playerHasItem = player.Arsenal |> Array.exists (fun w -> item.Id = w.Id)

View File

@ -8,8 +8,8 @@ open DSharpPlus.SlashCommands
open Degenz.Types open Degenz.Types
open Degenz.Messaging open Degenz.Messaging
let defaultHack = Armoury.battleItems |> Array.find (fun i -> i.Id = int HackId.Virus) let defaultHack = Armory.battleItems |> Array.find (fun i -> i.Id = int HackId.Virus)
let defaultShield = Armoury.battleItems |> Array.find (fun i -> i.Id = int ShieldId.Firewall) let defaultShield = Armory.battleItems |> Array.find (fun i -> i.Id = int ShieldId.Encryption)
let sendInitialEmbed (client : DiscordClient) = let sendInitialEmbed (client : DiscordClient) =
async { async {
@ -18,145 +18,102 @@ let sendInitialEmbed (client : DiscordClient) =
let embed = DiscordEmbedBuilder() let embed = DiscordEmbedBuilder()
embed.ImageUrl <- "https://s10.gifyu.com/images/MasterTraining_Degenz.gif" embed.ImageUrl <- "https://s10.gifyu.com/images/MasterTraining_Degenz.gif"
builder.AddEmbed embed |> ignore builder.AddEmbed embed |> ignore
builder.Content <- "Welcome to the hacker dojo you degenerate, are you ready to get started?" builder.Content <- "Welcome Degen… To the Hacker Training Program.\n"
let button = DiscordButtonComponent(ButtonStyle.Success, $"Trainer-1", $"Get started") :> DiscordComponent + "Here you will learn how to defend yourself, and hack other Degenz to steal their 💰$GBT.\n"
+ "Are you ready?"
let button = DiscordButtonComponent(ButtonStyle.Success, $"Trainer-1", $"LFG") :> DiscordComponent
builder.AddComponents [| button |] |> ignore builder.AddComponents [| button |] |> ignore
do! channel.SendMessageAsync(builder) do! channel.SendMessageAsync(builder)
|> Async.AwaitTask |> Async.AwaitTask
|> Async.Ignore |> Async.Ignore
} |> Async.RunSynchronously } |> 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) = let handleTrainerStep1 (event : ComponentInteractionCreateEventArgs) =
async { Game.executePlayerEvent event (fun player -> async {
let! maybePlayer = DbService.tryFindPlayer event.User.Id
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask
match maybePlayer with
| Some _ ->
do! sendFollowUpMessageWithButton event step1Msg
| None ->
let msg = "Looks like an error occurred, you're not a registered degenerate. Please contact a moderator."
do! sendFollowUpMessage event msg
}
let handleTrainerStep2 (event : ComponentInteractionCreateEventArgs) =
async {
let! result = DbService.tryFindPlayer event.User.Id
match result with
| Some player ->
let weaponName = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name let weaponName = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
do! updateMessageWithGreyedOutButtons event step1Msg
let shieldMessage = let shieldMessage =
if Player.shields player |> Array.isEmpty 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" then $"You do not have any Shields in your arsenal, take this {defaultShield.Name}, you can use it for now"
else $"You currently have {weaponName} in your arsenal" else $"Looks like you have `{weaponName}` in your arsenal… 👀\n"
do! sendFollowUpMessage event do! sendInteractionEvent event
($"First things first, let's get your system protected. Let's enable a shield to protect you from potential hackers. " ("Beautopia© is a dangerous place...\n"
+ $"{shieldMessage}. To enable it and protect your system, you can use the `/defend` slash command to choose a shield." + "Quick, put up a DEFENSE 🛡 before another Degen hacks you, and steals your 💰$GBT.\n"
+ $"\n\nRun the `/defend` command now and then select '{weaponName}'.") + shieldMessage
| None -> + "To enable it, you need to run the `/shield` slash command.\n\n"
do! sendFollowUpMessage event $"Something went wrong, please contact a moderator" + $"Type the `/shield` command now, then select - `{weaponName}`\n")
} })
let defend (ctx : InteractionContext) = let defend (ctx : InteractionContext) =
async { Game.executePlayerInteraction ctx (fun player -> async {
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match playerResult with
| Some player ->
let playerWithShields = let playerWithShields =
match player.Arsenal with match player.Arsenal with
| [||] -> { player with Arsenal = [| defaultShield |] } | [||] -> { player with Arsenal = [| defaultShield |] }
| _ -> player | _ -> player
let embed = Embeds.pickDefense "Trainer-3" playerWithShields let embed = Embeds.pickDefense "Trainer-2" playerWithShields
do! ctx.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed) do! ctx.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask |> Async.AwaitTask
| None -> })
let builder = DiscordInteractionResponseBuilder()
builder.Content <- "Error, please contact a moderator"
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
let handleDefenseMsg = { let handleDefenseMsg = {
ButtonId = "Trainer-4" ButtonId = "Trainer-3"
ButtonText = "Got it" 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. " Message = "🎉 Congratulations 🎉\n\n"
+ "Shields only protect you for a certain amount of time, so remember to keep your system protected at all times." + "You successfully defended my hack!\n\n"
+ "Because I tried hacking you when you had your defense up, you stole money from me...\n"
+ "Defenses only protect you for a LIMITED TIME, so remember to keep at least 1 defense up at all times, or risk getting hacked!"
} }
let handleDefense (event : ComponentInteractionCreateEventArgs) = let handleDefense (event : ComponentInteractionCreateEventArgs) =
Game.executePlayerEvent event (fun player -> async {
let sendMessage' = sendFollowUpMessage event let sendMessage' = sendFollowUpMessage event
async {
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate) do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask |> Async.AwaitTask
let! maybePlayer = DbService.tryFindPlayer event.User.Id
match maybePlayer with
| Some player ->
let prize = 0.223f
let shield = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield let shield = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield
let embed = Embeds.responseCreatedShieldTrainer shield let embed = Embeds.responseCreatedShieldTrainer shield
do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
do! Async.Sleep 2000 do! Async.Sleep 2000
do! sendMessage' "Ok, good, let me make sure that worked. I'll try to hack you now" do! sendMessage' "Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now"
do! Async.Sleep 4000 do! Async.Sleep 4000
do! sendMessage' $"Hacking attempt failed! {player.Name} defended hack from Degenz-Trainer and took {prize} from them! " do! sendMessage' $"❌ HACKING FAILED! ❌\n\n{player.Name} defended the hack from <@{GuildEnvironment.botHackerBattle}>, and stole 💰$GBT {Game.ShieldPrize} from them!"
do! Async.Sleep 3000 do! Async.Sleep 3000
do! sendFollowUpMessageWithButton event handleDefenseMsg do! sendFollowUpMessageWithButton event handleDefenseMsg
| None -> })
do! sendMessage' $"Something went wrong, please contact a moderator"
}
let handleTrainerStep4 (event : ComponentInteractionCreateEventArgs) = let handleTrainerStep3 (event : ComponentInteractionCreateEventArgs) =
async { Game.executePlayerEvent event (fun player -> async {
let! result = DbService.tryFindPlayer event.User.Id
match result with
| Some player ->
let weaponName = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name let weaponName = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
do! updateMessageWithGreyedOutButtons event handleDefenseMsg do! updateMessageWithGreyedOutButtons event handleDefenseMsg
let hackMessage = let hackMessage =
if Player.shields player |> Array.isEmpty 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" then $"You do not have any Hacks in your arsenal, take this {defaultHack.Name}, you can use it for now"
else $"You currently have {weaponName} in your arsenal" else $"Looks like you have `{weaponName}` in your arsenal..."
do! sendFollowUpMessage event do! sendFollowUpMessage event
($"Next why don't you try hacking me. {hackMessage}. To hack me and get some money, " ("Now lets **HACK!** 💻\n\n"
+ $" you can use the '/hack' slash command and select a user to hack, then choose the hack attack you wish to use." + "I want you to **HACK ME**, and try to steal my 💰$GBT...\n\n"
+ $"\n\nRun the `/hack` command now and pick me as your target, then click on the '{weaponName}' button.") + hackMessage
| None -> + "To deploy it, you need to run the `/hack` slash command.\n"
do! sendInteractionEvent event $"Something went wrong, please contact a moderator" + $"Type the `/hack` command now, then choose me - <@{GuildEnvironment.botHackerBattle}> as your target, and select - `{weaponName}`")
} })
let attack (ctx : InteractionContext) (target : DiscordUser) = let attack (ctx : InteractionContext) (target : DiscordUser) =
async { Game.executePlayerInteraction ctx (fun player -> async {
let isRightTarget = target.Id = GuildEnvironment.botHackerBattle let isRightTarget = target.Id = GuildEnvironment.botHackerBattle
let! playerResult = DbService.tryFindPlayer ctx.Member.Id match isRightTarget with
match isRightTarget , playerResult with | true ->
| true , Some player ->
let playerWithAttacks = let playerWithAttacks =
match player.Arsenal with match player.Arsenal with
| [||] -> { player with Arsenal = [| defaultHack |] } | [||] -> { player with Arsenal = [| defaultHack |] }
| _ -> player | _ -> player
let embed = Embeds.pickHack "Trainer-5" playerWithAttacks player let embed = Embeds.pickHack "Trainer-4" playerWithAttacks player
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed) do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
|> Async.AwaitTask |> Async.AwaitTask
| false , _ -> | false ->
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
builder.Content <- "You picked the wrong target, you dufus. Try again, this time pick me!" builder.Content <- "You picked the wrong target, you dufus. Try again, this time pick me!"
@ -164,72 +121,37 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask |> Async.AwaitTask
| _ -> })
let builder = DiscordInteractionResponseBuilder()
builder.Content <- "Error, please contact a moderator"
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
} |> 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 handleAttack (event : ComponentInteractionCreateEventArgs) =
Game.executePlayerEvent event (fun player -> async {
let sendMessage' = sendFollowUpMessage event let sendMessage' = sendFollowUpMessage event
async {
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate) do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask |> Async.AwaitTask
let! result = DbService.tryFindPlayer event.User.Id
match result with
| Some player ->
let prize = 2
do! Async.Sleep 1000 do! Async.Sleep 1000
let hack = player.Arsenal |> Array.tryHead |> Option.defaultValue defaultHack let hack = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultHack
let embed = Embeds.responseSuccessfulHackTrainer $"<@{GuildEnvironment.botHackerBattle}>" hack prize let embed = Embeds.responseSuccessfulHackTrainer hack
do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
do! Async.Sleep 3000 do! Async.Sleep 3000
do! sendMessage' ("Look at that, you are now officially an elite haxor! By successfully hacking other people you can earn GoodBoyTokenz. " do! sendMessage' ("🎉 **Congratulations** 🎉\n\n"
+ "Hacks take time to recover so check back in later once you've used all your hacks.") + "You successfully **HACKED** me, and are now an **Elite Haxor!**\n\n"
+ "When you **HACK** other Degenz, you **STEAL** their 💰**$GBT.**\n"
+ "But remember, hacks take time to recover, so use them wisely.")
do! Async.Sleep 7000 do! Async.Sleep 7000
do! sendFollowUpMessageWithButton event handleAttackMsg do! sendFollowUpMessage event ("Your training is **complete!**\n\n"
| None -> + "But, youre going to need more **HACKS & DEFENSES** 🛡 to survive in **Beautopia©...**\n"
do! sendMessage' $"Something went wrong, please contact a moderator" + $"You can purchase them from <@{GuildEnvironment.botArmory}>, at <#{GuildEnvironment.channelArmory}> anytime you want...\n\n"
} + "Go there **NOW** to buy **HACKS** & **SHIELDS** before you get hacked! 😱")
})
let handleTrainerStep6 (event : ComponentInteractionCreateEventArgs) =
async {
// let! membr = event.Guild.GetMemberAsync(event.User.Id) |> Async.AwaitTask
// let role = event.Guild.GetRole(GuildEnvironment.roleTrainee)
// do! membr.RevokeRoleAsync(role) |> Async.AwaitTask
let builder = DiscordFollowupMessageBuilder()
builder.IsEphemeral <- true
builder.Content <- "Get out of here!"
do! updateMessageWithGreyedOutButtons event handleAttackMsg
do! event.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
}
let handleButtonEvent (event : ComponentInteractionCreateEventArgs) = let handleButtonEvent (event : ComponentInteractionCreateEventArgs) =
async { async {
let split = event.Id.Split("-") let split = event.Id.Split("-")
match int split.[1] with match int split.[1] with
| 1 -> do! handleTrainerStep1 event | 1 -> do! handleTrainerStep1 event |> Async.AwaitTask
| 2 -> do! handleTrainerStep2 event | 2 -> do! handleDefense event |> Async.AwaitTask
| 3 -> do! handleDefense event | 3 -> do! handleTrainerStep3 event |> Async.AwaitTask
| 4 -> do! handleTrainerStep4 event | 4 -> do! handleAttack event |> Async.AwaitTask
| 5 -> do! handleAttack event
| 6 -> do! handleTrainerStep6 event
| _ -> do! sendFollowUpMessage event "No action found" | _ -> do! sendFollowUpMessage event "No action found"
} }

View File

@ -63,7 +63,7 @@ let private playerMap (player : PlayerData) = {
let private mapBack (player : PlayerEntry) : PlayerData = { let private mapBack (player : PlayerEntry) : PlayerData = {
DiscordId = player.DiscordId DiscordId = player.DiscordId
Name = player.Name Name = player.Name
Arsenal = player.Arsenal |> Array.map (fun w -> Armoury.battleItems |> Array.find (fun w' -> w = w'.Id)) Arsenal = player.Arsenal |> Array.map (fun w -> Armory.battleItems |> Array.find (fun w' -> w = w'.Id))
Actions = Actions =
let atks = player.Attacks |> Array.map attackToAction let atks = player.Attacks |> Array.map attackToAction
let dfns = player.Defenses |> Array.map defenseToAction let dfns = player.Defenses |> Array.map defenseToAction

View File

@ -77,7 +77,7 @@ module Types =
Bank : int<GBT> } Bank : int<GBT> }
module Armoury = module Armory =
let battleItems = let battleItems =
let file = System.IO.File.ReadAllText("Items.json") let file = System.IO.File.ReadAllText("Items.json")
JsonConvert.DeserializeObject<BattleItem array>(file) JsonConvert.DeserializeObject<BattleItem array>(file)
@ -95,7 +95,7 @@ module Player =
let removeExpiredActions actions = let removeExpiredActions actions =
actions actions
|> Array.filter (fun (act : Action) -> |> Array.filter (fun (act : Action) ->
let item = Armoury.battleItems |> Array.find (fun w -> w.Id = act.ActionId) let item = Armory.battleItems |> Array.find (fun w -> w.Id = act.ActionId)
DateTime.UtcNow - act.Timestamp < TimeSpan.FromMinutes(int item.Cooldown)) DateTime.UtcNow - act.Timestamp < TimeSpan.FromMinutes(int item.Cooldown))
let modifyBank player amount = { player with Bank = max (player.Bank + amount) 0<GBT> } let modifyBank player amount = { player with Bank = max (player.Bank + amount) 0<GBT> }