125 lines
5.4 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.Messaging
let checkHasSufficientFunds (item : BattleItem) player =
if player.Bank - item.Cost >= 0<GBT>
then Ok player
else Error $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
let checkAlreadyOwnsItem (item : BattleItem) player =
if player.Arsenal |> Array.exists (fun w -> item.Id = w.Id)
then Error $"You already own {item.Name}!"
else Ok player
let checkSoldItemAlready (item : BattleItem) player =
if player.Arsenal |> Array.exists (fun w -> item.Id = w.Id)
then Ok player
else Error $"{item.Name} not found in your arsenal! Looks like you sold it already."
let checkHasItemsInArsenal itemType player =
if player.Arsenal |> Array.filter (fun i -> i.Type = itemType ) |> Array.length > 0
then Ok player
else Error $"You currently have no {itemType}s in your arsenal to sell!"
let buy itemType (ctx : InteractionContext) =
Game.executePlayerInteraction ctx (fun player -> async {
let itemStore = Embeds.getBuyItemsEmbed player itemType Armory.battleItems
do! ctx.Interaction.CreateFollowupMessageAsync(itemStore)
|> Async.AwaitTask
|> Async.Ignore
})
let sell itemType (ctx : InteractionContext) =
Game.executePlayerInteraction ctx (fun player -> async {
match checkHasItemsInArsenal itemType player with
| Ok _ ->
let itemStore = Embeds.getSellItemsEmbed itemType player
do! ctx.FollowUpAsync(itemStore)
|> Async.AwaitTask
|> Async.Ignore
| Error e -> do! sendFollowUpMessageFromCtx ctx e
})
// TODO: When you buy a shield, prompt the user to activate it
let handleBuyItem (event : ComponentInteractionCreateEventArgs) itemId =
Game.executePlayerEvent event (fun player -> async {
let item = Armory.battleItems |> Array.find (fun w -> w.Id = itemId)
do! player
|> checkHasSufficientFunds item
>>= checkAlreadyOwnsItem item
|> handleResultWithResponseFromEvent event (fun player -> async {
let newBalance = player.Bank - item.Cost
let p = { player with Bank = newBalance ; Arsenal = Array.append [| item |] player.Arsenal }
do! DbService.updatePlayer p
do! sendFollowUpMessage event $"Successfully purchased {item.Name}! You now have {newBalance} 💰$GBT remaining"
})
})
let handleSell (event : ComponentInteractionCreateEventArgs) itemId =
Game.executePlayerEvent event (fun player -> async {
let item = Armory.getItem itemId
do! player
|> checkSoldItemAlready item
|> handleResultWithResponseFromEvent event (fun player -> async {
let updatedPlayer = {
player with
Bank = player.Bank + item.Cost
Arsenal = player.Arsenal |> Array.filter (fun i -> i.Id <> itemId)
Actions =
if item.Type = ItemType.Shield
then player.Actions |> Array.filter (fun a -> a.ActionId <> itemId)
else player.Actions
}
do! DbService.updatePlayer updatedPlayer
do! sendFollowUpMessage event $"Sold {item.Type} {item.Name} for {item.Cost}! Current Balance: {updatedPlayer.Bank}"
})
})
let handleStoreEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
let itemId = int <| event.Id.Split("-").[1]
match event.Id with
| id when id.StartsWith("Buy") -> handleBuyItem event itemId
| id when id.StartsWith("Sell") -> handleSell event itemId
| _ ->
task {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Incorrect Action identifier {event.Id}"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
type Store() =
inherit ApplicationCommandModule ()
let enforceChannel (ctx : InteractionContext) (storeFn : InteractionContext -> Task) =
match ctx.Channel.Id with
| id when id = GuildEnvironment.channelArmory -> storeFn ctx
| _ ->
task {
let msg = $"You must go to <#{GuildEnvironment.channelArmory}> channel to buy or sell weapons"
do! Messaging.sendSimpleResponse ctx msg
}
[<SlashCommand("buy-hack", "Purchase a hack attack you can use to earn GoodBoyTokenz")>]
member _.BuyHack (ctx : InteractionContext) = enforceChannel ctx (buy ItemType.Hack)
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GoodBoyTokenz")>]
member this.BuyShield (ctx : InteractionContext) = enforceChannel ctx (buy ItemType.Shield)
[<SlashCommand("sell-hack", "Sell a hack for GoodBoyTokenz")>]
member this.SellHack (ctx : InteractionContext) = enforceChannel ctx (sell ItemType.Hack)
[<SlashCommand("sell-shield", "Sell a shield for GoodBoyTokenz")>]
member this.SellShield (ctx : InteractionContext) = enforceChannel ctx (sell ItemType.Shield)