discord-bot-game/Bot/Trainer.fs
2022-02-24 20:22:15 +07:00

213 lines
9.7 KiB
Forth
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module Degenz.Trainer
open System.Text
open System.Threading.Tasks
open DSharpPlus
open DSharpPlus.Entities
open DSharpPlus.EventArgs
open Degenz.Types
open Degenz.Messaging
let trainerAchievement = "FINISHED_TRAINER"
let Sensei = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
let defaultHack = Armory.battleItems |> Array.find (fun i -> i.Id = int HackId.Virus)
let defaultShield = Armory.battleItems |> Array.find (fun i -> i.Id = int ShieldId.Firewall)
let TrainerEvents = [|
{ Timestamp = System.DateTime.UtcNow
Cooldown = 2<mins>
Type = Hacking {
Adversary = Sensei
Success = true
IsInstigator = true
HackId = defaultHack.Id } }
{ Timestamp = System.DateTime.UtcNow
Cooldown = defaultShield.Cooldown
Type = Shielding defaultShield.Id }
|]
let sendInitialEmbed (client : DiscordClient) =
async {
try
let! channel = client.GetChannelAsync(GuildEnvironment.channelTraining) |> Async.AwaitTask
let builder = DiscordMessageBuilder()
let embed = DiscordEmbedBuilder()
embed.ImageUrl <- "https://s10.gifyu.com/images/MasterTraining_Degenz.gif"
builder.AddEmbed embed |> ignore
builder.Content <- "Welcome Degen… To the Hacker Training Program.\n"
+ "Here you will learn how to defend yourself, and hack other Degenz to take their 💰$GBT.\n"
+ "Are you ready?"
let button = DiscordButtonComponent(ButtonStyle.Success, $"Trainer-1", $"LFG") :> DiscordComponent
builder.AddComponents [| button |] |> ignore
do! channel.SendMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
with e ->
printfn $"Error trying to get channel {GuildEnvironment.channelTraining}\n\n{e.Message}"
} |> Async.RunSynchronously
let handleTrainerStep1 (ctx : IDiscordContext) =
async {
let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
do! ctx.GetDiscordMember().GrantRoleAsync(role)
|> Async.AwaitTask
let msg = "Beautopia© is a dangerous place... quick, put up a SHIELD 🛡 before another Degen hacks you, and takes your 💰$GBT.\n\n"
+ "To enable it, you need to run the `/shield` slash command.\n\n"
+ $"Type the `/shield` command now, then select - `{defaultShield.Name}`\n"
let builder =
DiscordInteractionResponseBuilder()
.WithContent(msg)
.AsEphemeral(true)
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
} |> Async.StartAsTask :> Task
let defend (ctx : IDiscordContext) =
async {
do! Messaging.defer ctx
let m = ctx.GetDiscordMember()
let name = if System.String.IsNullOrEmpty m.Nickname then m.DisplayName else m.Nickname
let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [| defaultShield |] ; Name = name } true
do! ctx.FollowUp(embed) |> Async.AwaitTask
} |> Async.StartAsTask :> Task
let handleDefenseMsg hackId = {
ButtonId = "Trainer-3"
ButtonText = "Got it"
Message = $"🎉 Congratulations you successfully defended my {hackId} hack!\n\n"
+ "Shields only protect you for a LIMITED TIME, so remember to keep them mounted at all times, or risk getting hacked!"
}
let handleDefense (ctx : IDiscordContext) =
async {
do! Messaging.defer ctx
let sendMessage' = sendFollowUpMessage ctx
let tokens = ctx.GetInteractionId().Split("-")
let shieldId = enum<ShieldId>(int tokens.[2])
let shield = Armory.getItem (int shieldId)
let playerName = tokens.[4]
let embed = Embeds.responseCreatedShield shield
do! ctx.FollowUp embed |> Async.AwaitTask
do! Async.Sleep 4000
do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **{defaultHack.Name}**"
do! Async.Sleep 5000
do! sendMessage' $"❌ HACKING FAILED!\n\n{playerName} defended hack from <@{Sensei.Id}>!"
do! Async.Sleep 4000
do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHack.Name)
} |> Async.StartAsTask :> Task
let handleTrainerStep3 (ctx : IDiscordContext) =
async {
let builder =
DiscordInteractionResponseBuilder()
.AsEphemeral(true)
.WithContent
( "Now lets **HACK** 💻... I want you to **HACK ME**!\n\n"
+ "To **hack**, you need to run the `/hack` slash command.\n"
+ $"Type the `/hack` command now, then choose me - <@{Sensei.Id}> as your target, and select `{defaultHack.Name}`")
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
} |> Async.StartAsTask :> Task
let hack (target : DiscordUser) (ctx : IDiscordContext) =
async {
do! Messaging.defer ctx
let isRightTarget = target.Id = Sensei.Id
match isRightTarget with
| true ->
let bot = { PlayerData.empty with DiscordId = Sensei.Id ; Name = Sensei.Name }
let embed = Embeds.pickHack "Trainer-4" { PlayerData.empty with Inventory = [| defaultHack |] } bot true
do! ctx.FollowUp(embed) |> Async.AwaitTask
| false ->
let builder =
DiscordFollowupMessageBuilder()
.WithContent("You picked the wrong target, you dufus. Try again, this time pick me!")
.AsEphemeral(true)
do! ctx.FollowUp(builder) |> Async.AwaitTask
} |> Async.StartAsTask :> Task
let handleHack (ctx : IDiscordContext) =
Game.executePlayerAction ctx (fun player -> async {
let sendMessage' = sendFollowUpMessage ctx
do! Async.Sleep 1000
let embed = Embeds.responseSuccessfulHack false Sensei.Id defaultHack.Power defaultHack
do! ctx.FollowUp(embed) |> Async.AwaitTask
do! Async.Sleep 4000
do! sendMessage'
("🎉 **Congratulations**\n\n"
+ "You successfully **HACKED** me, and are now an **Elite Haxor!**\n\n"
+ "When you **HACK** other Degenz, you **TAKE** their 💰$GBT.\n"
+ "But remember, hacks take time to recover, so use them wisely.")
do! Async.Sleep 5000
let sb = StringBuilder("Here, ")
let! completed = DbService.checkHasAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement
if not completed then
do! DbService.addAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement
|> Async.Ignore
sb.Append($"I'm going to gift you a hack,`{defaultHack.Name}` and a shield, `{defaultShield.Name}`") |> ignore
sb.Append(", you'll need em to survive\n\n") |> ignore
sb.AppendLine("To finish your training and collect the loot, type the `/arsenal` command **NOW**") |> ignore
do! Async.Sleep 1000
do! sendFollowUpMessage ctx (sb.ToString())
else
do! sendFollowUpMessage ctx ($"Your training is now complete. If you want to buy more **HACKS & SHIELDS**, go to the <#{GuildEnvironment.channelArmory}> and type the `/buy-hack` and `/buy-shield` commands!")
let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
do! ctx.GetDiscordMember().RevokeRoleAsync(role)
|> Async.AwaitTask
})
let handleArsenal (ctx : IDiscordContext) =
Game.executePlayerAction ctx (fun player -> async {
let hasStockWeapons = Player.getHacks player |> Array.exists (fun item -> item.Id = defaultHack.Id)
let updatedPlayer =
if not hasStockWeapons then {
Player.removeExpiredActions player with
Events = TrainerEvents |> Array.append player.Events
Inventory = [| defaultHack ; defaultShield |] |> Array.append player.Inventory
}
else
Player.removeExpiredActions player
if not hasStockWeapons then
do!
[ DbService.addPlayerEvent GuildEnvironment.pgDb player.DiscordId TrainerEvents.[0]
DbService.addPlayerEvent GuildEnvironment.pgDb player.DiscordId TrainerEvents.[1]
DbService.updatePlayer GuildEnvironment.pgDb updatedPlayer ]
|> Async.Parallel
|> Async.Ignore
let embed = Embeds.getArsenalEmbed updatedPlayer
do! ctx.FollowUp(embed) |> Async.AwaitTask
let! completed = DbService.checkHasAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement
if not completed then
do! Async.Sleep 3000
let rewards = [ $"{defaultHack.Name} Hack" ; $"{defaultShield.Name} Shield" ]
let embed = Embeds.getAchievementEmbed rewards "You completed the Training Dojo and collected loot." trainerAchievement
do! ctx.FollowUp(embed) |> Async.AwaitTask
do! Async.Sleep 2000
let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
do! ctx.GetDiscordMember().RevokeRoleAsync(role) |> Async.AwaitTask
do! sendFollowUpMessage ctx $"Now get out of there and go hack other Degenz in the <#{GuildEnvironment.channelBattle}> channel!"
})
let handleButtonEvent (ctx : IDiscordContext) =
async {
let tokens = ctx.GetInteractionId().Split("-")
match int tokens.[1] with
| 1 -> do! handleTrainerStep1 ctx |> Async.AwaitTask
| 2 -> do! handleDefense ctx |> Async.AwaitTask
| 3 -> do! handleTrainerStep3 ctx |> Async.AwaitTask
| 4 -> do! handleHack ctx |> Async.AwaitTask
| _ -> do! sendFollowUpMessage ctx "No action found"
}