183 lines
8.8 KiB
Forth
183 lines
8.8 KiB
Forth
module Degenz.Store
|
|
|
|
open System.Threading.Tasks
|
|
open DSharpPlus.Entities
|
|
open DSharpPlus
|
|
open DSharpPlus.EventArgs
|
|
open DSharpPlus.SlashCommands
|
|
open Degenz
|
|
open Degenz.Embeds
|
|
open Degenz.Shared
|
|
open Newtonsoft.Json
|
|
|
|
let store =
|
|
try
|
|
let file = System.IO.File.ReadAllText("Items.json")
|
|
JsonConvert.DeserializeObject<Item array>(file)
|
|
|> Array.groupBy (fun (i : Item) -> i.ItemType)
|
|
with _ -> [||]
|
|
|
|
let viewStore (ctx : InteractionContext) =
|
|
async {
|
|
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, Embeds.storeListing store)
|
|
|> Async.AwaitTask
|
|
} |> Async.StartAsTask
|
|
:> Task
|
|
|
|
let getItems itemType = store |> Array.find (fun ( t , _ ) -> t = itemType) |> snd
|
|
|
|
let buyHack (ctx : InteractionContext) hackId =
|
|
async {
|
|
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
|
|
let weapons = getItems ItemType.Hack
|
|
let weaponResult = weapons |> Array.tryFind (fun w -> w.Name = string hackId)
|
|
return!
|
|
match playerResult , weaponResult with
|
|
| Some player , Some item ->
|
|
async {
|
|
let newBalance = player.Bank - item.Cost
|
|
if newBalance >= 0 then
|
|
let playerHasItem = player.Weapons |> Array.exists (fun w -> item.Name = string w)
|
|
if not playerHasItem then
|
|
let weapon = weaponInventory |> Array.find (fun w -> item.Name = string w)
|
|
let p = { player with Bank = newBalance ; Weapons = Array.append [| weapon |] player.Weapons }
|
|
do! DbService.updatePlayer p
|
|
do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx
|
|
else
|
|
do! createSimpleResponseAsync $"You already own this item!" ctx
|
|
else
|
|
do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx
|
|
}
|
|
| None , _ -> notYetAHackerMsg ctx
|
|
| _ -> createSimpleResponseAsync "Something is wrong" ctx
|
|
} |> Async.StartAsTask
|
|
:> Task
|
|
|
|
let buyShield (ctx : InteractionContext) shieldId =
|
|
async {
|
|
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
|
|
let shieldResult =
|
|
getItems ItemType.Shield
|
|
|> Array.tryFind (fun w -> w.Name = string shieldId)
|
|
return!
|
|
match playerResult , shieldResult with
|
|
| Some player , Some item ->
|
|
async {
|
|
let newBalance = player.Bank - item.Cost
|
|
if newBalance >= 0 then
|
|
let playerHasItem = player.Shields |> Array.exists (fun w -> item.Name = string w)
|
|
if not playerHasItem then
|
|
let shield = shieldInventory |> Array.find (fun w -> item.Name = string w)
|
|
let p = { player with Bank = newBalance ; Shields = Array.append [| shield |] player.Shields }
|
|
do! DbService.updatePlayer p
|
|
do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx
|
|
else
|
|
do! createSimpleResponseAsync $"You already own this item!" ctx
|
|
else
|
|
do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx
|
|
}
|
|
| None , _ -> notYetAHackerMsg ctx
|
|
| _ -> createSimpleResponseAsync "Something is wrong" ctx
|
|
} |> Async.StartAsTask
|
|
:> Task
|
|
|
|
let constructItemButtons playerInfo itemType (items : 'a array) =
|
|
items
|
|
|> Seq.map (fun item -> DiscordButtonComponent(ButtonStyle.Primary, $"{playerInfo}-{itemType}-{item}", $"{item}"))
|
|
|
|
let sellItem (ctx : InteractionContext) =
|
|
async {
|
|
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
|
|
match playerResult with
|
|
| Some player ->
|
|
let hasInventoryToSell = Array.length player.Weapons + Array.length player.Shields > 0
|
|
if hasInventoryToSell then
|
|
let builder = DiscordInteractionResponseBuilder()
|
|
builder.AddEmbed (constructEmbed "Pick the item you wish to sell.") |> ignore
|
|
|
|
Array.chunkBySize 3 player.Weapons
|
|
|> Array.iter
|
|
(fun wps ->
|
|
wps
|
|
|> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Primary, $"Hack-{w}", $"{w}"))
|
|
|> Seq.cast<DiscordComponent>
|
|
|> builder.AddComponents
|
|
|> ignore)
|
|
Array.chunkBySize 3 player.Shields
|
|
|> Array.iter
|
|
(fun shs ->
|
|
shs
|
|
|> Array.map (fun s -> DiscordButtonComponent(ButtonStyle.Primary, $"Shield-{s}", $"{s}"))
|
|
|> Seq.cast<DiscordComponent>
|
|
|> builder.AddComponents
|
|
|> ignore)
|
|
|
|
builder.AsEphemeral true |> ignore
|
|
|
|
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|
|
|> Async.AwaitTask
|
|
else
|
|
do! createSimpleResponseAsync "You currently have no inventory to sell" ctx
|
|
| None -> do! notYetAHackerMsg ctx
|
|
return ()
|
|
} |> Async.StartAsTask
|
|
:> Task
|
|
|
|
let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
|
|
async {
|
|
let! playerResult = DbService.tryFindPlayer event.User.Id
|
|
match playerResult with
|
|
| Some player ->
|
|
let split = event.Id.Split("-")
|
|
let itemType = match split.[0] with "Hack" -> ItemType.Hack | _ -> ItemType.Shield
|
|
let itemName = split.[1]
|
|
match itemType with
|
|
| ItemType.Hack ->
|
|
let item = getItems ItemType.Hack |> Array.find (fun w -> w.Name = itemName)
|
|
let salePrice = item.Cost / 2
|
|
let updatedWeapons = player.Weapons |> Array.filter (fun (w : Hack) -> string w <> itemName)
|
|
let updatedPlayer = { player with Bank = player.Bank + salePrice ; Weapons = updatedWeapons }
|
|
do! DbService.updatePlayer updatedPlayer
|
|
let builder = DiscordInteractionResponseBuilder()
|
|
builder.IsEphemeral <- true
|
|
builder.Content <- $"Sold hack {itemName} for {salePrice}! Current Balance: {updatedPlayer.Bank}"
|
|
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|
|
|> Async.AwaitTask
|
|
| ItemType.Shield ->
|
|
let item = getItems ItemType.Shield |> Array.find (fun s -> s.Name = itemName)
|
|
let salePrice = item.Cost / 2
|
|
let updatedShields = player.Shields |> Array.filter (fun (s : Shield) -> string s <> itemName)
|
|
let updatedPlayer = { player with Bank = player.Bank + salePrice ; Shields = updatedShields }
|
|
do! DbService.updatePlayer updatedPlayer
|
|
let builder = DiscordInteractionResponseBuilder()
|
|
builder.IsEphemeral <- true
|
|
builder.Content <- $"Sold shield {itemName} for {salePrice}! Current Balance: {updatedPlayer.Bank}"
|
|
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|
|
|> Async.AwaitTask
|
|
| None ->
|
|
let builder = DiscordInteractionResponseBuilder()
|
|
builder.IsEphemeral <- true
|
|
builder.Content <- "An error occurred and the user doesn't not exist"
|
|
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|
|
|> Async.AwaitTask
|
|
} |> Async.StartAsTask
|
|
:> Task
|
|
|
|
type Store() =
|
|
inherit ApplicationCommandModule ()
|
|
|
|
[<SlashCommand("store", "View items available for purchase")>]
|
|
member _.ViewStore (ctx : InteractionContext) = viewStore ctx
|
|
|
|
[<SlashCommand("buy-hack", "Purchase a hack attack you can use to earn GoodBoyTokenz")>]
|
|
member _.BuyHack (ctx : InteractionContext, [<Option("hack-id", "The ID of the hack you wish to purchase")>] hackId : Hack) =
|
|
buyHack ctx hackId
|
|
|
|
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GoodBoyTokenz")>]
|
|
member this.BuyShield (ctx : InteractionContext, [<Option("shield-id", "The ID of the shield you wish to purchase")>] shieldId : Shield) =
|
|
buyShield ctx shieldId
|
|
|
|
[<SlashCommand("sell", "Sell an item in your inventory for GoodBoyTokenz")>]
|
|
member this.SellItem (ctx : InteractionContext) = sellItem ctx
|
|
|