Implement new Trainer improvements and clean up a few more things
This commit is contained in:
parent
ef3d5c58f5
commit
e772a6d6f3
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
16
Bot/Game.fs
16
Bot/Game.fs
@ -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
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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)]
|
||||||
|
12
Bot/Store.fs
12
Bot/Store.fs
@ -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)
|
||||||
|
252
Bot/Trainer.fs
252
Bot/Trainer.fs
@ -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
|
let weaponName = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
|
||||||
|
|
||||||
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|
let shieldMessage =
|
||||||
|> Async.AwaitTask
|
if Player.shields player |> Array.isEmpty
|
||||||
match maybePlayer with
|
then $"You do not have any Shields in your arsenal, take this {defaultShield.Name}, you can use it for now"
|
||||||
| Some _ ->
|
else $"Looks like you have `{weaponName}` in your arsenal… 👀\n"
|
||||||
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) =
|
do! sendInteractionEvent event
|
||||||
async {
|
("Beautopia© is a dangerous place...\n"
|
||||||
let! result = DbService.tryFindPlayer event.User.Id
|
+ "Quick, put up a DEFENSE 🛡 before another Degen hacks you, and steals your 💰$GBT.\n"
|
||||||
match result with
|
+ shieldMessage
|
||||||
| Some player ->
|
+ "To enable it, you need to run the `/shield` slash command.\n\n"
|
||||||
let weaponName = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
|
+ $"Type the `/shield` command now, then select - `{weaponName}`\n")
|
||||||
do! 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! sendFollowUpMessage event
|
|
||||||
($"First things first, let's get your system protected. Let's enable a shield to protect you from potential hackers. "
|
|
||||||
+ $"{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! sendFollowUpMessage event $"Something went wrong, please contact a moderator"
|
|
||||||
}
|
|
||||||
|
|
||||||
let defend (ctx : InteractionContext) =
|
let defend (ctx : InteractionContext) =
|
||||||
async {
|
Game.executePlayerInteraction ctx (fun player -> async {
|
||||||
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
|
let playerWithShields =
|
||||||
match playerResult with
|
match player.Arsenal with
|
||||||
| Some player ->
|
| [||] -> { player with Arsenal = [| defaultShield |] }
|
||||||
let playerWithShields =
|
| _ -> player
|
||||||
match player.Arsenal with
|
let embed = Embeds.pickDefense "Trainer-2" playerWithShields
|
||||||
| [||] -> { player with Arsenal = [| defaultShield |] }
|
|
||||||
| _ -> player
|
|
||||||
let embed = Embeds.pickDefense "Trainer-3" 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) =
|
||||||
let sendMessage' = sendFollowUpMessage event
|
Game.executePlayerEvent event (fun player -> async {
|
||||||
async {
|
let sendMessage' = sendFollowUpMessage event
|
||||||
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|
||||||
|> Async.AwaitTask
|
|> Async.AwaitTask
|
||||||
let! maybePlayer = DbService.tryFindPlayer event.User.Id
|
let shield = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield
|
||||||
match maybePlayer with
|
let embed = Embeds.responseCreatedShieldTrainer shield
|
||||||
| Some player ->
|
do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
|
||||||
let prize = 0.223f
|
do! Async.Sleep 2000
|
||||||
let shield = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield
|
do! sendMessage' "Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now"
|
||||||
let embed = Embeds.responseCreatedShieldTrainer shield
|
do! Async.Sleep 4000
|
||||||
do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
|
do! sendMessage' $"❌ HACKING FAILED! ❌\n\n{player.Name} defended the hack from <@{GuildEnvironment.botHackerBattle}>, and stole 💰$GBT {Game.ShieldPrize} from them!"
|
||||||
do! Async.Sleep 2000
|
do! Async.Sleep 3000
|
||||||
do! sendMessage' "Ok, good, let me make sure that worked. I'll try to hack you now"
|
do! sendFollowUpMessageWithButton event handleDefenseMsg
|
||||||
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
|
|
||||||
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
|
let weaponName = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
|
||||||
match result with
|
do! updateMessageWithGreyedOutButtons event handleDefenseMsg
|
||||||
| Some player ->
|
|
||||||
let weaponName = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
|
|
||||||
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 let’s **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) =
|
||||||
let sendMessage' = sendFollowUpMessage event
|
Game.executePlayerEvent event (fun player -> async {
|
||||||
async {
|
let sendMessage' = sendFollowUpMessage event
|
||||||
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|
||||||
|> Async.AwaitTask
|
|> Async.AwaitTask
|
||||||
let! result = DbService.tryFindPlayer event.User.Id
|
do! Async.Sleep 1000
|
||||||
match result with
|
let hack = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultHack
|
||||||
| Some player ->
|
let embed = Embeds.responseSuccessfulHackTrainer hack
|
||||||
let prize = 2
|
do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
|
||||||
do! Async.Sleep 1000
|
do! Async.Sleep 3000
|
||||||
let hack = player.Arsenal |> Array.tryHead |> Option.defaultValue defaultHack
|
do! sendMessage' ("🎉 **Congratulations** 🎉\n\n"
|
||||||
let embed = Embeds.responseSuccessfulHackTrainer $"<@{GuildEnvironment.botHackerBattle}>" hack prize
|
+ "You successfully **HACKED** me, and are now an **Elite Haxor!**\n\n"
|
||||||
do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
|
+ "When you **HACK** other Degenz, you **STEAL** their 💰**$GBT.**\n"
|
||||||
do! Async.Sleep 3000
|
+ "But remember, hacks take time to recover, so use them wisely.")
|
||||||
do! sendMessage' ("Look at that, you are now officially an elite haxor! By successfully hacking other people you can earn GoodBoyTokenz. "
|
do! Async.Sleep 7000
|
||||||
+ "Hacks take time to recover so check back in later once you've used all your hacks.")
|
do! sendFollowUpMessage event ("Your training is **complete!**\n\n"
|
||||||
do! Async.Sleep 7000
|
+ "But, you’re going to need more **HACKS & DEFENSES** 🛡 to survive in **Beautopia©...**\n"
|
||||||
do! sendFollowUpMessageWithButton event handleAttackMsg
|
+ $"You can purchase them from <@{GuildEnvironment.botArmory}>, at <#{GuildEnvironment.channelArmory}> anytime you want...\n\n"
|
||||||
| None ->
|
+ "Go there **NOW** to buy **HACKS** & **SHIELDS** before you get hacked! 😱")
|
||||||
do! sendMessage' $"Something went wrong, please contact a moderator"
|
})
|
||||||
}
|
|
||||||
|
|
||||||
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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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> }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user