discord-bot-game/Bot/Trainer.fs

231 lines
11 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 DSharpPlus
open DSharpPlus.Entities
open DSharpPlus.EventArgs
open Degenz.Types
open Degenz.Messaging
let trainerAchievement = "FINISHED_TRAINER"
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.Encryption)
let sendInitialEmbed (client : DiscordClient) =
async {
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 steal 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
} |> Async.RunSynchronously
let handleTrainerStep1 (ctx : IDiscordContext) =
Game.executePlayerAction ctx (fun player -> async {
let shieldMessage , weaponName =
if Player.getShields player |> Array.isEmpty
then $"You do not have any Shields in your arsenal, take the `{defaultShield.Name}` shield, you can use it for now.\n\n" , defaultShield.Name
else
let name = Player.getShields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
$"Looks like you have `{name}` in your arsenal… 👀\n\n" , name
let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
do! ctx.GetDiscordMember().GrantRoleAsync(role)
|> Async.AwaitTask
do! sendFollowUpMessage ctx
("Beautopia© is a dangerous place... quick, put up a SHIELD 🛡 before another Degen hacks you, and steals your 💰$GBT.\n\n"
+ shieldMessage
+ "To enable it, you need to run the `/shield` slash command.\n\n"
+ $"Type the `/shield` command now, then select - `{weaponName}`\n")
})
let defend (ctx : IDiscordContext) =
Game.executePlayerAction ctx (fun player -> async {
let playerWithShields =
match Player.getShields player with
| [||] -> { player with Arsenal = [| defaultShield |] }
| _ -> player
let embed = Embeds.pickDefense "Trainer-2" playerWithShields true
do! ctx.FollowUp(embed) |> Async.AwaitTask
})
let handleDefenseMsg shieldId hackId = {
ButtonId = "Trainer-3"
ButtonText = "Got it"
Message = "🎉 Congratulations you successfully defended my hack!\n\n"
+ $"The `{shieldId}` shield is strong against the `{hackId}` hack, so make sure to have multiple shields up to protect from multiple attacks..."
+ "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) =
Game.executePlayerAction ctx (fun player -> async {
let sendMessage' = sendFollowUpMessage ctx
let split = ctx.GetInteractionId().Split("-")
let shieldId = enum<ShieldId>(int split.[2])
let shield = Armory.getItem (int shieldId)
let embed = Embeds.responseCreatedShield shield
do! ctx.FollowUp embed |> Async.AwaitTask
do! Async.Sleep 4000
let weakHack = Game.getGoodAgainst shield.Class
do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **{snd weakHack}**"
do! Async.Sleep 5000
do! sendMessage' $"❌ HACKING FAILED!\n\n{player.Name} defended hack from <@{GuildEnvironment.botIdHackerBattle}>!"
do! Async.Sleep 4000
do! sendFollowUpMessageWithButton ctx (handleDefenseMsg shieldId (snd weakHack))
})
let handleTrainerStep3 (ctx : IDiscordContext) =
Game.executePlayerAction ctx (fun player -> async {
let hackMessage , weaponName =
if Player.getHacks 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" , defaultHack.Name
else
let name = Player.getHacks player |> Array.tryHead |> Option.defaultValue defaultHack |> fun w -> w.Name
$"Looks like you have `{name}` in your arsenal...\n\n" , name
do! sendFollowUpMessage ctx
("Now lets **HACK!** 💻\n\n"
+ "I want you to **HACK ME**...\n\n"
+ hackMessage
+ "To deploy it, you need to run the `/hack` slash command.\n"
+ $"Type the `/hack` command now, then choose me - <@{GuildEnvironment.botIdHackerBattle}> as your target, and select `{weaponName}`")
})
let attack (target : DiscordUser) (ctx : IDiscordContext) =
Game.executePlayerAction ctx (fun player -> async {
let isRightTarget = target.Id = GuildEnvironment.botIdHackerBattle
match isRightTarget with
| true ->
let playerWithAttacks =
match Player.getHacks player with
| [||] -> { player with Arsenal = [| defaultHack |] }
| _ -> player
let bot = { player with DiscordId = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
let embed = Embeds.pickHack "Trainer-4" playerWithAttacks bot true
do! ctx.FollowUp(embed) |> Async.AwaitTask
| false ->
let builder = DiscordFollowupMessageBuilder()
builder.Content <- "You picked the wrong target, you dufus. Try again, this time pick me!"
builder.IsEphemeral <- true
do! ctx.FollowUp(builder) |> Async.AwaitTask
})
let handleAttack (ctx : IDiscordContext) =
Game.executePlayerAction ctx (fun player -> async {
let sendMessage' = sendFollowUpMessage ctx
do! Async.Sleep 1000
let hack = Player.getHacks player |> Array.tryHead |> Option.defaultValue defaultHack
let embed = Embeds.responseSuccessfulHack false GuildEnvironment.botIdHackerBattle hack
do! ctx.FollowUp(embed) |> Async.AwaitTask
do! Async.Sleep 5000
do! sendMessage'
("🎉 **Congratulations**\n\n"
+ "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 6000
let sb = StringBuilder("Here, ")
let! achievements = DbService.getAchievements player.DiscordId
let isFirstTrainer = achievements |> Option.map (Seq.contains trainerAchievement >> not) |> Option.defaultValue true
if isFirstTrainer then
do! DbService.addAchievement player.DiscordId trainerAchievement
let hasHacks = Player.getHacks player |> Array.isEmpty |> not
let hasShields = Player.getShields player |> Array.isEmpty |> not
let rand = System.Random(System.Guid.NewGuid().GetHashCode())
let freeHack = Armory.hacks.[rand.Next(0, 3)]
let freeShield = Armory.shields.[rand.Next(0, 3)]
let hackMoney = if hasHacks then defaultHack.Cost else 0<GBT>
let shieldMoney = if hasShields then defaultShield.Cost else 0<GBT>
let giftMsg =
match hasHacks , hasShields with
| true , true -> $"I'm going to give you these {hackMoney + shieldMoney} 💰$GBT"
| false , true -> $"I'm going to gift you a hack, `{freeHack.Name}` and {defaultHack.Cost} 💰$GBT"
| true , false -> $"I'm going to gift you a shield, `{freeShield.Name}` and {defaultHack.Cost} 💰$GBT"
| false , false -> $"I'm going to gift you a hack,`{freeHack.Name}` and a shield, `{freeShield.Name}`"
sb.Append(giftMsg) |> 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
let updatedPlayer = {
player with
Bank = player.Bank + hackMoney + shieldMoney
Actions = [
{ Action.Timestamp = System.DateTime.UtcNow
Action.Type =
Attack {
Result = true
Target = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
}
ActionId = defaultHack.Id
}
if not hasShields && Array.exists (fun act -> act.ActionId = freeShield.Id) player.Actions |> not then {
Action.Timestamp = System.DateTime.UtcNow
Action.Type = Defense
Action.ActionId = freeShield.Id
}
] |> Seq.toArray
|> Array.append player.Actions
Arsenal = [
if not hasHacks then freeHack
if not hasShields then freeShield
] |> Seq.toArray
|> Array.append player.Arsenal
}
do! DbService.updatePlayer updatedPlayer
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}> **NOW** 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 updatedPlayer = Player.removeExpiredActions false player
let embed = Embeds.getArsenalEmbed updatedPlayer
do! ctx.FollowUp(embed) |> Async.AwaitTask
do! Async.Sleep 3000
let embed = Embeds.getAchievementEmbed "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 split = ctx.GetInteractionId().Split("-")
match int split.[1] with
| 1 -> do! handleTrainerStep1 ctx |> Async.AwaitTask
| 2 -> do! handleDefense ctx |> Async.AwaitTask
| 3 -> do! handleTrainerStep3 ctx |> Async.AwaitTask
| 4 -> do! handleAttack ctx |> Async.AwaitTask
| _ -> do! sendFollowUpMessage ctx "No action found"
}