diff --git a/Bot/DbService.fs b/Bot/DbService.fs index 6c99a5e..522a50d 100644 --- a/Bot/DbService.fs +++ b/Bot/DbService.fs @@ -34,36 +34,6 @@ let getPlayerEvents (did : uint64) = ) |> Async.AwaitTask -let getLastPlayedSlotFromPlayer (did : uint64) = async { - let! events = - connStr - |> Sql.connect - |> Sql.parameters [ "did", Sql.string (string did) ] - |> Sql.query """ - SELECT player_event.updated_at FROM player_event - JOIN "user" u on u.id = player_event.user_id - WHERE u.discord_id = @did AND event_type = 'PlayingSlot' - """ - |> Sql.executeAsync (fun read -> read.dateTime "updated_at" ) - |> Async.AwaitTask - match events with - | [] -> return None - | es -> return Some (List.head es) -} - -let updateSlotPlayedFromPlayer (did : uint64) = - connStr - |> Sql.connect - |> Sql.parameters [ "did", Sql.string (string did) ] - |> Sql.query """ - WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did) - UPDATE player_event SET updated_at = now() at time zone 'utc' - FROM usr WHERE usr.id = user_id AND player_event.event_type = 'PlayingSlot'; - """ - |> Sql.executeNonQueryAsync - |> Async.AwaitTask - |> Async.Ignore - let updatePlayerStats (player : PlayerData) = connStr |> Sql.connect diff --git a/Bot/GameTypes.fs b/Bot/GameTypes.fs index 5f04ce7..5f85b57 100644 --- a/Bot/GameTypes.fs +++ b/Bot/GameTypes.fs @@ -2,7 +2,6 @@ module Degenz.Types open System -open Degenz [] type mins @@ -102,6 +101,7 @@ type Item = { Id : int Name : string Price : int + MaxAllowed : int Attributes : ItemAttributes } diff --git a/Bot/Games/SlotMachine.fs b/Bot/Games/SlotMachine.fs index aac21e9..37ea635 100644 --- a/Bot/Games/SlotMachine.fs +++ b/Bot/Games/SlotMachine.fs @@ -103,30 +103,6 @@ let reel1 = getReel (fun s -> s.reel1Count) let reel2 = getReel (fun s -> s.reel2Count) let reel3 = getReel (fun s -> s.reel3Count) -let slots = - [| "https://s7.gifyu.com/images/aneye.png" - "https://s7.gifyu.com/images/anonmask.png" - "https://s7.gifyu.com/images/circuitboard.png" - "https://s7.gifyu.com/images/obey.png" - "https://s7.gifyu.com/images/oldtv.png" - "https://s7.gifyu.com/images/pills.png" - "https://s7.gifyu.com/images/pizza0d47578733961746.png" - "https://s7.gifyu.com/images/ramen0515f00869e1f4eb.png" - "https://s7.gifyu.com/images/rat69609f842a0eb9f5.png" - "https://s7.gifyu.com/images/alcohol.png" - "https://s7.gifyu.com/images/bigbrother.png" - "https://s7.gifyu.com/images/sushi.png" |] -// [| "https://s7.gifyu.com/images/A-bottle-of-pills0a3006d0170e08df.png" -// "https://s7.gifyu.com/images/an-eyec362d8152ae2382b.png" -// "https://s7.gifyu.com/images/anon-face-mask6c7624821c89fc08.png" -// "https://s7.gifyu.com/images/a-piece-of-sushi77071d30f60a89c6.png" -// "https://s7.gifyu.com/images/Circuit-board89056017b80f1d13.png" -// "https://s7.gifyu.com/images/OBEYf2a8234109836c03.png" -// "https://s7.gifyu.com/images/old-tv-screendc6bc9d4b6c1fd65.png" -// "https://s7.gifyu.com/images/pizza030ffc00ff50da0e.png" -// "https://s7.gifyu.com/images/ramen08336d448018c98f.png" -// "https://s7.gifyu.com/images/rat14f65f54f0d75036.png" |] - let slotEmojiNames = [| "sushi" "bigbrother" @@ -172,6 +148,36 @@ let resetJackpot amount = |> Sql.executeNonQueryAsync |> Async.AwaitTask +let getLastPlayedSlotFromPlayer (did : uint64) = async { + let! events = + GuildEnvironment.connectionString + |> Sql.connect + |> Sql.parameters [ "did", Sql.string (string did) ] + |> Sql.query """ + SELECT player_event.updated_at FROM player_event + JOIN "user" u on u.id = player_event.user_id + WHERE u.discord_id = @did AND event_type = 'PlayingSlot' + """ + |> Sql.executeAsync (fun read -> read.dateTime "updated_at" ) + |> Async.AwaitTask + match events with + | [] -> return None + | es -> return Some (List.head es) +} + +let updateSlotPlayedFromPlayer (did : uint64) = + GuildEnvironment.connectionString + |> Sql.connect + |> Sql.parameters [ "did", Sql.string (string did) ] + |> Sql.query """ + WITH usr AS (SELECT id FROM "user" WHERE discord_id = @did) + UPDATE player_event SET updated_at = now() at time zone 'utc' + FROM usr WHERE usr.id = user_id AND player_event.event_type = 'PlayingSlot'; + """ + |> Sql.executeNonQueryAsync + |> Async.AwaitTask + |> Async.Ignore + let handlePrizeTable (ctx : IDiscordContext) = task { do! Messaging.defer ctx @@ -321,10 +327,10 @@ let spin multiplier (ctx : IDiscordContext) = } PlayerInteractions.executePlayerAction ctx (fun player -> async { if player.Bank >= playAmount then - match! DbService.getLastPlayedSlotFromPlayer player.DiscordId with + match! getLastPlayedSlotFromPlayer player.DiscordId with | Some timestamp -> if DateTime.UtcNow - timestamp > TimeSpan.FromSeconds(8) then - do! DbService.updateSlotPlayedFromPlayer player.DiscordId + do! updateSlotPlayedFromPlayer player.DiscordId do! execute player else do! Messaging.sendFollowUpMessage ctx "Wait till you finish the current spin!" diff --git a/Bot/Games/Store.fs b/Bot/Games/Store.fs index aa63c08..0b0887e 100644 --- a/Bot/Games/Store.fs +++ b/Bot/Games/Store.fs @@ -182,6 +182,57 @@ let handleStoreEvents (_ : DiscordClient) (event : ComponentInteractionCreateEve do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask } +let showInventoryEmbed (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction ctx (fun player -> async { + let embeds , buttons = + player.Inventory + |> List.map (fun item -> + let embed = DiscordEmbedBuilder() + match item with + | Hack hack -> + embed.AddField($"$GBT Reward |", string hack.Power, true) + .AddField("Cooldown |", $"{TimeSpan.FromMinutes(int hack.Cooldown).Minutes} minutes", true) + .WithColor(DiscordColor.Red) + .WithThumbnail(Embeds.getItemIcon item.Id) + |> ignore + | Shield shield -> + embed.AddField($"Strong against |", WeaponClass.getGoodAgainst shield.Class |> snd |> string, true) +// .AddField($"Defensive Strength |", string item.Power, true) + .AddField("Active For |", $"{TimeSpan.FromMinutes(int shield.Cooldown).Hours} hours", true) + .WithColor(DiscordColor.SapGreen) + .WithThumbnail(Embeds.getItemIcon item.Id) + |> ignore + | Food food -> + embed.AddField($"Stat |", $"{food.TargetStat}", true) + .WithColor(DiscordColor.Azure) + .AddField($"Amount |", $"+{food.BoostAmount}", true) |> ignore + | Accessory accessory -> + embed.AddField($"Stat |", $"{accessory.TargetStat}", true) + .WithColor(DiscordColor.Goldenrod) |> ignore + if accessory.FloorBoost > 0 then + embed.AddField($"Min Boost |", $"+{accessory.FloorBoost}", true) |> ignore + if accessory.CeilBoost > 0 then + embed.AddField($"Max Boost |", $"+{accessory.CeilBoost}", true) |> ignore + embed + .AddField("Price 💰", (if item.Price = 0 then "Free" else $"{item.Price} $GBT"), true) + .WithTitle($"{item.Name}") + |> ignore + let button = +// if playerInventory |> List.exists (fun i -> i.Id = item.Id) +// then DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Buy-{item.Id}", $"Own {item.Name}", true) +// else DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Buy-{item.Id}", $"Buy {item.Name}") + DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Sell-{item.Id}", $"Sell {item.Name}") + ( embed.Build() , button :> DiscordComponent )) + |> List.unzip + + let builder = + DiscordFollowupMessageBuilder() + .AddEmbeds(embeds) +// .AddComponents(buttons) + .AsEphemeral(true) + do! ctx.FollowUp builder |> Async.AwaitTask +}) + + type Store() = inherit ApplicationCommandModule () @@ -194,21 +245,22 @@ type Store() = do! Messaging.sendSimpleResponse ctx msg } +// let checkChannel (ctx : IDiscordContext) (storeFn : IDiscordContext -> Task) = let checkChannel (ctx : IDiscordContext) = match ctx.GetChannel().Id with -// | id when id = GuildEnvironment.channelBackAlley -> buy (Inventory.getItemsByType ItemType.Hack) ctx + | id when id = GuildEnvironment.channelBackAlley -> buy ItemType.Hack ctx | id when id = GuildEnvironment.channelArmory -> buy ItemType.Shield ctx -// | id when id = GuildEnvironment.channelMarket -> buy (Inventory.getItemsByType ItemType.Food) ctx -// | id when id = GuildEnvironment.channelAccessoryShop -> buy (Inventory.getItemsByType ItemType.Accessory) ctx + | id when id = GuildEnvironment.channelMarket -> buy ItemType.Food ctx + | id when id = GuildEnvironment.channelAccessoryShop -> buy ItemType.Accessory ctx | _ -> task { - let msg = $"This channel doesn't have any items to sell" + let msg = $"This channel doesn't have any items to sell. Try <#{GuildEnvironment.channelArmory}>" do! Messaging.sendSimpleResponse ctx msg } -// [] -// member _.BuyItem (ctx : InteractionContext) = checkChannel (DiscordInteractionContext(ctx)) -// + [] + member _.BuyItem (ctx : InteractionContext) = checkChannel (DiscordInteractionContext ctx) + [] member _.BuyHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy ItemType.Hack) @@ -217,9 +269,6 @@ type Store() = member this.BuyShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy ItemType.Shield) -// [] -// member this.BuyFood (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy (Inventory.getItemsByType ItemType.Food)) -// [] member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Hacks" (Inventory.getItemsByType ItemType.Hack)) @@ -228,9 +277,9 @@ type Store() = [] member this.Consume (ctx : InteractionContext) = - enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" (Inventory.getItemsByType ItemType.Food)) + enforceChannel (DiscordInteractionContext ctx) (sell "Shields" (Inventory.getItemsByType ItemType.Food)) -// [] -// member this.Inventory (ctx : InteractionContext) = -// enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" (Inventory.getItemsByType ItemType)) + [] + member this.Inventory (ctx : InteractionContext) = + showInventoryEmbed (DiscordInteractionContext ctx) diff --git a/Bot/GuildEnvironment.fs b/Bot/GuildEnvironment.fs index a384b1e..952b12a 100644 --- a/Bot/GuildEnvironment.fs +++ b/Bot/GuildEnvironment.fs @@ -34,9 +34,9 @@ let channelWhitelist = getId "CHANNEL_WHITELIST" //let channelTosserTed = getId "CHANNEL_TOSSERTED" let channelShelters = getId "CHANNEL_SHELTERS" let channelSlots = getId "CHANNEL_SLOTS" -//let channelBackAlley = getId "CHANNEL_BACKALLEY" -//let channelMarket = getId "CHANNEL_MARKET" -//let channelAccessoryShop = getId "CHANNEL_ACCESSORIES" +let channelBackAlley = getId "CHANNEL_BACKALLEY" +let channelMarket = getId "CHANNEL_MARKET" +let channelAccessoryShop = getId "CHANNEL_ACCESSORIES" //let channelThievery = getId "CHANNEL_THIEVERY" let botIdHackerBattle = getId "BOT_HACKER_BATTLE" diff --git a/Bot/Items.json b/Bot/Items.json index 959d33a..0012b85 100644 --- a/Bot/Items.json +++ b/Bot/Items.json @@ -10,6 +10,7 @@ "Id": 0, "Name": "Virus", "Price": 250, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : true, @@ -32,6 +33,7 @@ "Id": 1, "Name": "Remote Access", "Price": 250, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : true, @@ -54,6 +56,7 @@ "Id": 2, "Name": "Worm", "Price": 250, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : true, @@ -75,6 +78,7 @@ "Id": 6, "Name": "Firewall", "Price": 100, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : true, @@ -96,6 +100,7 @@ "Id": 7, "Name": "Encryption", "Price": 100, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : true, @@ -117,6 +122,7 @@ "Id": 8, "Name": "Cypher", "Price": 100, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : true, @@ -138,6 +144,7 @@ "Id": 12, "Name": "Protein Powder", "Price": 50, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : false, @@ -159,6 +166,7 @@ "Id": 13, "Name": "Toro Loco", "Price": 50, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : false, @@ -180,6 +188,7 @@ "Id": 14, "Name": "Oldports Cigs", "Price": 50, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : false, @@ -201,6 +210,7 @@ "Id": 15, "Name": "Moon Pie", "Price": 50, + "MaxAllowed": 1, "Attributes": { "CanBuy" : true, "CanSell" : false, @@ -222,6 +232,7 @@ "Item": { "Id": 20, "Name": "Kettlebell", + "MaxAllowed": 1, "Price": 250, "Attributes": { "CanBuy" : true, @@ -244,6 +255,7 @@ "Item": { "Id": 21, "Name": "Headphones", + "MaxAllowed": 1, "Price": 250, "Attributes": { "CanBuy" : true, @@ -266,6 +278,7 @@ "Item": { "Id": 22, "Name": "Rolox Watch", + "MaxAllowed": 1, "Price": 250, "Attributes": { "CanBuy" : true, @@ -288,6 +301,7 @@ "Item": { "Id": 23, "Name": "Buddha Keychain", + "MaxAllowed": 1, "Price": 250, "Attributes": { "CanBuy" : true,