diff --git a/Bot/Bot.fs b/Bot/Bot.fs
index d328966..8efcaf0 100644
--- a/Bot/Bot.fs
+++ b/Bot/Bot.fs
@@ -1,6 +1,5 @@
module Degenz.Bot
-open System
open System.Threading.Tasks
open DSharpPlus
open DSharpPlus.SlashCommands
diff --git a/Bot/Bot.fsproj b/Bot/Bot.fsproj
index 81c8a2a..c3c069f 100644
--- a/Bot/Bot.fsproj
+++ b/Bot/Bot.fsproj
@@ -11,8 +11,8 @@
PreserveNewest
-
+
diff --git a/Bot/Embeds.fs b/Bot/Embeds.fs
index 2cf51a4..abbc6ee 100644
--- a/Bot/Embeds.fs
+++ b/Bot/Embeds.fs
@@ -1,7 +1,7 @@
module Degenz.Embeds
open DSharpPlus.EventArgs
-open Degenz.Shared
+open Degenz.Types
open DSharpPlus.Entities
open AsciiTableFormatter
@@ -34,7 +34,7 @@ let constructEmbed message =
let pickDefense actionId player =
let buttons =
- constructButtons actionId (string player.DiscordId) (Player.shields player)
+ Messaging.constructButtons actionId (string player.DiscordId) (Player.shields player)
|> Seq.cast
let embed =
@@ -50,7 +50,7 @@ let pickDefense actionId player =
let pickHack actionId attacker defender =
let buttons =
- constructButtons actionId $"{defender.DiscordId}-{defender.Name}" (Player.hacks attacker)
+ Messaging.constructButtons actionId $"{defender.DiscordId}-{defender.Name}" (Player.hacks attacker)
|> Seq.cast
let embed =
diff --git a/Bot/Game.fs b/Bot/Game.fs
new file mode 100644
index 0000000..76ea0b9
--- /dev/null
+++ b/Bot/Game.fs
@@ -0,0 +1,15 @@
+module Degenz.Game
+
+open System.Threading.Tasks
+open DSharpPlus.SlashCommands
+open Degenz.DbService
+
+let executePlayerAction (ctx : InteractionContext) (dispatch : PlayerData -> Async) =
+ async {
+ let! playerResult = tryFindPlayer ctx.Member.Id
+ match playerResult with
+ | Some player -> do! dispatch player
+ | None -> do! Messaging.sendSimpleResponse ctx "You are currently not a hacker, first use the /redpill command to become one"
+ } |> Async.StartAsTask
+ :> Task
+
diff --git a/Bot/GameConfig.fs b/Bot/GameConfig.fs
deleted file mode 100644
index a4d0894..0000000
--- a/Bot/GameConfig.fs
+++ /dev/null
@@ -1 +0,0 @@
-module Degenz.GameConfig
diff --git a/Bot/HackerBattle.fs b/Bot/HackerBattle.fs
index d4ae65d..0c27523 100644
--- a/Bot/HackerBattle.fs
+++ b/Bot/HackerBattle.fs
@@ -7,8 +7,7 @@ open DSharpPlus.Entities
open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Degenz
-open Degenz.Shared
-open Degenz.Store
+open Degenz.Messaging
let getTimeTillCooldownFinishes (timespan : TimeSpan) timestamp =
let timeRemaining = timespan - (DateTime.UtcNow - timestamp)
@@ -26,8 +25,8 @@ let checkIfPlayerIsAttackingThemselves defender attacker =
let checkForExistingHack defenderId attacker =
attacker.Actions
- |> removeExpiredActions
- |> getAttacksFlat
+ |> Player.removeExpiredActions
+ |> Player.getAttacksFlat
|> Array.tryFind (fun (_,t,_) -> t.Id = defenderId)
|> function
| Some ( atk , target , _ ) ->
@@ -47,7 +46,7 @@ let checkIfHackHasCooldown hackId attacker =
Ok attacker
else
let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromMinutes(5)) mostRecentHackAttack
- let item = armoury |> Array.find (fun i -> i.Id = hackId)
+ let item = Armoury.battleItems |> Array.find (fun i -> i.Id = hackId)
Error $"{item.Name} is currently on cooldown, wait {cooldown} to use it again."
let checkIfInventoryIsEmpty attacker =
@@ -62,8 +61,8 @@ let calculateDamage (hack : BattleItem) (shield : BattleItem) =
let runHackerBattle defender hack =
Player.defenses defender
- |> removeExpiredActions
- |> Array.map (fun dfn -> armoury |> Array.find (fun w -> w.Id = dfn.ActionId))
+ |> Player.removeExpiredActions
+ |> Array.map (fun dfn -> Armoury.battleItems |> Array.find (fun w -> w.Id = dfn.ActionId))
|> Array.map (calculateDamage (hack))
|> Array.contains Weak
@@ -74,7 +73,7 @@ let updateCombatants attacker defender hack prize =
let attack = { ActionId = int hack ; Type = Attack { Target = target ; Result = prize > 0 } ; Timestamp = DateTime.UtcNow }
[ DbService.updatePlayer <| updatePlayer prize attack attacker
- DbService.updatePlayer <| modifyPlayerBank defender -prize ]
+ DbService.updatePlayer <| Player.modifyBank defender -prize ]
|> Async.Parallel
|> Async.Ignore
@@ -115,11 +114,10 @@ let failedHack (event : ComponentInteractionCreateEventArgs) attacker defender h
}
let attack (ctx : InteractionContext) (target : DiscordUser) =
- async {
- let! attacker = DbService.tryFindPlayer ctx.Member.Id
+ Game.executePlayerAction ctx (fun attacker -> async {
let! defender = DbService.tryFindPlayer target.Id
- match attacker , defender with
- | Some attacker , Some defender ->
+ match defender with
+ | Some defender ->
let hackAttempt =
checkForExistingHack defender.DiscordId attacker
|> Result.bind checkIfInventoryIsEmpty
@@ -136,10 +134,8 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
.AsEphemeral(true)
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
- | None , _ -> do! notYetAHackerMsg ctx
- | _ , None -> do! createSimpleResponseAsync "Your target is not connected to the network, they must join first by using the /redpill command" ctx
- } |> Async.StartAsTask
- :> Task
+ | None -> do! sendSimpleResponse ctx "Your target is not connected to the network, they must join first by using the /redpill command"
+ })
let handleAttack (event : ComponentInteractionCreateEventArgs) =
async {
@@ -155,7 +151,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
|> Result.bind (checkIfHackHasCooldown (int hack))
|> function
| Ok _ ->
- runHackerBattle defender (getItemFromArmoury <| int hack)
+ runHackerBattle defender (Armoury.getItem (int hack))
|> function
| false -> successfulHack event attacker defender hack
| true -> failedHack event attacker defender hack
@@ -175,23 +171,18 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
}
let defend (ctx : InteractionContext) =
- async {
- let! player = DbService.tryFindPlayer ctx.Member.Id
- match player with
- | Some player ->
- if Player.shields player |> Array.length > 0 then
- let embed = Embeds.pickDefense "Defend" player
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
- |> Async.AwaitTask
- else
- let builder = DiscordInteractionResponseBuilder()
- builder.Content <- $"You currently do not have any Shields to protect your system. Please go to the armoury and purchase one."
- builder.AsEphemeral true |> ignore
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
- |> Async.AwaitTask
- | None -> do! notYetAHackerMsg ctx
- } |> Async.StartAsTask
- :> Task
+ Game.executePlayerAction ctx (fun player -> async {
+ if Player.shields player |> Array.length > 0 then
+ let embed = Embeds.pickDefense "Defend" player
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
+ |> Async.AwaitTask
+ else
+ let builder = DiscordInteractionResponseBuilder()
+ builder.Content <- $"You currently do not have any Shields to protect your system. Please go to the armoury and purchase one."
+ builder.AsEphemeral true |> ignore
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
+ |> Async.AwaitTask
+ })
let handleDefense (event : ComponentInteractionCreateEventArgs) =
async {
@@ -200,7 +191,7 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) =
let! playerResult = DbService.tryFindPlayer event.User.Id
match playerResult with
| Some player ->
- let updatedDefenses = Player.defenses player |> removeExpiredActions
+ let updatedDefenses = Player.defenses player |> Player.removeExpiredActions
let alreadyUsedShield = updatedDefenses |> Array.exists (fun d -> d.ActionId = int shield)
match alreadyUsedShield , updatedDefenses.Length < 2 with
diff --git a/Bot/PlayerInteractions.fs b/Bot/PlayerInteractions.fs
index 548b121..6592805 100644
--- a/Bot/PlayerInteractions.fs
+++ b/Bot/PlayerInteractions.fs
@@ -5,15 +5,15 @@ open DSharpPlus.Entities
open DSharpPlus
open DSharpPlus.SlashCommands
open Degenz.Store
-open Degenz.Shared
+open Degenz.Types
module Commands =
let newPlayer nickname (membr : uint64) =
let rand = System.Random(System.Guid.NewGuid().GetHashCode())
let randHack = rand.Next(0, 3)
let randShield = rand.Next(6, 9)
- let hack = armoury |> Array.find (fun i -> i.Id = randHack)
- let shield = armoury |> Array.find (fun i -> i.Id = randShield)
+ let hack = Armoury.battleItems |> Array.find (fun i -> i.Id = randHack)
+ let shield = Armoury.battleItems |> Array.find (fun i -> i.Id = randShield)
{ DiscordId = membr
Name = nickname
@@ -72,21 +72,16 @@ module Commands =
// :> Task
let status (ctx : InteractionContext) =
- async {
- let! maybePlayer = DbService.tryFindPlayer ctx.Member.Id
- match maybePlayer with
- | Some player ->
- let updatedActions = removeExpiredActions player.Actions
- let updatedPlayer = { player with Actions = updatedActions }
- let builder = DiscordInteractionResponseBuilder()
- builder.IsEphemeral <- true
- builder.Content <- statusFormat updatedPlayer
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
- |> Async.AwaitTask
- do! DbService.updatePlayer updatedPlayer
- | None -> do! notYetAHackerMsg ctx
- } |> Async.StartAsTask
- :> Task
+ Game.executePlayerAction ctx (fun player -> async {
+ let updatedActions = Player.removeExpiredActions player.Actions
+ let updatedPlayer = { player with Actions = updatedActions }
+ let builder = DiscordInteractionResponseBuilder()
+ builder.IsEphemeral <- true
+ builder.Content <- Messaging.statusFormat updatedPlayer
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
+ |> Async.AwaitTask
+ do! DbService.updatePlayer updatedPlayer
+ })
type PlayerInteractions() =
inherit ApplicationCommandModule ()
diff --git a/Bot/SlotMachine.fs b/Bot/SlotMachine.fs
index 153bc14..a46b4de 100644
--- a/Bot/SlotMachine.fs
+++ b/Bot/SlotMachine.fs
@@ -5,7 +5,7 @@ open System.Threading.Tasks
open DSharpPlus
open DSharpPlus.Entities
open DSharpPlus.SlashCommands
-open Degenz.Shared
+open Degenz.Types
let slots = [| "https://i.ibb.co/pKqZdr7/cherry.png" ; "https://i.ibb.co/JnghQsL/lemon.jpg" ; "https://i.ibb.co/1JTFPSs/seven.png" |]
@@ -13,68 +13,62 @@ type SlotMachine() =
inherit ApplicationCommandModule ()
[]
- member this.AttackCommand (ctx : InteractionContext) =
- async {
- let! playerResult = DbService.tryFindPlayer ctx.Member.Id
- match playerResult with
- | Some player ->
- let sleepTime = 1000
- let random = Random(System.Guid.NewGuid().GetHashCode())
- let results = [ random.Next(0, 3) ; random.Next(0, 3) ; random.Next(0, 3)]
+ member this.Spin (ctx : InteractionContext) =
+ Game.executePlayerAction ctx (fun player -> async {
+ let sleepTime = 1000
+ let random = Random(System.Guid.NewGuid().GetHashCode())
+ let results = [ random.Next(0, 3) ; random.Next(0, 3) ; random.Next(0, 3)]
- let winConditions = (results.[0] = results.[1] && results.[0] = results.[2])
- || (results.[0] <> results.[1] && results.[1] <> results.[2] && results.[0] <> results.[2])
+ let winConditions = (results.[0] = results.[1] && results.[0] = results.[2])
+ || (results.[0] <> results.[1] && results.[1] <> results.[2] && results.[0] <> results.[2])
- if winConditions then
- do! DbService.updatePlayer { player with Bank = player.Bank + 10 }
- else
- do! DbService.updatePlayer { player with Bank = max (player.Bank - 1) 0 }
+ if winConditions then
+ do! DbService.updatePlayer { player with Bank = player.Bank + 10 }
+ else
+ do! DbService.updatePlayer { player with Bank = max (player.Bank - 1) 0 }
- do! ctx.Interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource)
- |> Async.AwaitTask
+ do! ctx.Interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource)
+ |> Async.AwaitTask
+ do! Async.Sleep sleepTime
+ let builder = DiscordFollowupMessageBuilder()
+ let embed = DiscordEmbedBuilder()
+ embed.ImageUrl <- slots.[results.[0]]
+ builder.AddEmbed(embed.Build()) |> ignore
+ do! ctx.Interaction.CreateFollowupMessageAsync(builder)
+ |> Async.AwaitTask
+ |> Async.Ignore
+
+ do! Async.Sleep sleepTime
+ let builder = DiscordFollowupMessageBuilder()
+ embed.ImageUrl <- slots.[results.[1]]
+ builder.AddEmbed(embed.Build()) |> ignore
+ do! ctx.Interaction.CreateFollowupMessageAsync(builder)
+ |> Async.AwaitTask
+ |> Async.Ignore
+
+ do! Async.Sleep sleepTime
+ let builder = DiscordFollowupMessageBuilder()
+ embed.ImageUrl <- slots.[results.[2]]
+ builder.AddEmbed(embed.Build()) |> ignore
+ do! ctx.Interaction.CreateFollowupMessageAsync(builder)
+ |> Async.AwaitTask
+ |> Async.Ignore
+
+ if winConditions then
do! Async.Sleep sleepTime
let builder = DiscordFollowupMessageBuilder()
- let embed = DiscordEmbedBuilder()
- embed.ImageUrl <- slots.[results.[0]]
- builder.AddEmbed(embed.Build()) |> ignore
+ builder.Content <- "You win 10 GBT!"
do! ctx.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
-
+ else
do! Async.Sleep sleepTime
let builder = DiscordFollowupMessageBuilder()
- embed.ImageUrl <- slots.[results.[1]]
- builder.AddEmbed(embed.Build()) |> ignore
+ builder.Content <- "You lose 0.5 GBT! Try your luck again!"
do! ctx.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
+ })
- do! Async.Sleep sleepTime
- let builder = DiscordFollowupMessageBuilder()
- embed.ImageUrl <- slots.[results.[2]]
- builder.AddEmbed(embed.Build()) |> ignore
- do! ctx.Interaction.CreateFollowupMessageAsync(builder)
- |> Async.AwaitTask
- |> Async.Ignore
-
- if winConditions then
- do! Async.Sleep sleepTime
- let builder = DiscordFollowupMessageBuilder()
- builder.Content <- "You win 10 GBT!"
- do! ctx.Interaction.CreateFollowupMessageAsync(builder)
- |> Async.AwaitTask
- |> Async.Ignore
- else
- do! Async.Sleep sleepTime
- let builder = DiscordFollowupMessageBuilder()
- builder.Content <- "You lose 0.5 GBT! Try your luck again!"
- do! ctx.Interaction.CreateFollowupMessageAsync(builder)
- |> Async.AwaitTask
- |> Async.Ignore
-
- | None -> do! notYetAHackerMsg ctx
-
- } |> Async.StartAsTask
- :> Task
diff --git a/Bot/Store.fs b/Bot/Store.fs
index 2d7faae..21c2ccf 100644
--- a/Bot/Store.fs
+++ b/Bot/Store.fs
@@ -8,83 +8,51 @@ open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Degenz
open Degenz.Embeds
-open Degenz.Shared
-open Newtonsoft.Json
-
-let getItemFromArmoury id = armoury |> Array.find (fun w -> w.Id = id)
-
-let removeExpiredActions actions =
- actions
- |> Array.filter (fun (act : Action) ->
- let item = armoury |> Array.find (fun w -> w.Id = act.ActionId)
- DateTime.UtcNow - act.Timestamp < TimeSpan.FromMinutes(int item.Cooldown))
+open Degenz.Messaging
let viewStore (ctx : InteractionContext) =
async {
- do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, Embeds.storeListing armoury)
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, Embeds.storeListing Armoury.battleItems)
|> Async.AwaitTask
} |> Async.StartAsTask
:> Task
-let buyItem (ctx : InteractionContext) itemId =
- async {
- let! playerResult = DbService.tryFindPlayer ctx.Member.Id
- let item = armoury |> Array.find (fun w -> w.Id = itemId)
- match playerResult with
- | Some player ->
- let newBalance = player.Bank - item.Cost
- if newBalance >= 0 then
- let playerHasItem = player.Arsenal |> Array.exists (fun w -> item.Id = w.Id)
- if not playerHasItem then
- let p = { player with Bank = newBalance ; Arsenal = Array.append [| item |] player.Arsenal }
- 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 -> do! notYetAHackerMsg ctx
- } |> Async.StartAsTask
- :> Task
+let buyItem (ctx : InteractionContext) itemType =
+ Game.executePlayerAction ctx (fun player -> async {
+ let embed = DiscordEmbedBuilder()
-let constructItemButtons playerInfo itemType (items : 'a array) =
- items
- |> Seq.map (fun item -> DiscordButtonComponent(ButtonStyle.Primary, $"{playerInfo}-{itemType}-{item}", $"{item}"))
+// embed.Fields
+
+ do! ctx.CreateResponseAsync(embed, true)
+ |> Async.AwaitTask
+ })
let sell (ctx : InteractionContext) =
- async {
- let! playerResult = DbService.tryFindPlayer ctx.Member.Id
- match playerResult with
- | Some player ->
- let hasInventoryToSell = Array.length player.Arsenal > 0
- if hasInventoryToSell then
- let builder = DiscordInteractionResponseBuilder()
- builder.AddEmbed (constructEmbed "Pick the item you wish to sell.") |> ignore
+ Game.executePlayerAction ctx (fun player -> async {
+ let hasInventoryToSell = Array.length player.Arsenal > 0
+ if hasInventoryToSell then
+ let builder = DiscordInteractionResponseBuilder()
+ builder.AddEmbed (constructEmbed "Pick the item you wish to sell.") |> ignore
- Array.chunkBySize 5 player.Arsenal
- |> Array.iter
- (fun wps ->
- wps
- |> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Primary, $"{w.Type}-{w.Id}", $"{w.Name}"))
- |> Seq.cast
- |> builder.AddComponents
- |> ignore)
- builder.AsEphemeral true |> ignore
+ Array.chunkBySize 5 player.Arsenal
+ |> Array.iter
+ (fun wps ->
+ wps
+ |> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Primary, $"{w.Type}-{w.Id}", $"{w.Name}"))
+ |> Seq.cast
+ |> 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 updateArsenal player salePrice updatedArsenal = { player with Bank = player.Bank + salePrice ; Arsenal = updatedArsenal }
+ do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
+ |> Async.AwaitTask
+ else
+ do! sendSimpleResponse ctx "You currently have no inventory to sell"
+ })
let sellItem (event : ComponentInteractionCreateEventArgs) player itemId =
async {
- let item = armoury |> Array.find (fun i -> i.Id = itemId)
+ let item = Armoury.battleItems |> Array.find (fun i -> i.Id = itemId)
let updatedPlayer = { player with Bank = player.Bank + item.Cost ; Arsenal = player.Arsenal |> Array.filter (fun w -> w.Id <> itemId)}
do! DbService.updatePlayer updatedPlayer
let builder = DiscordInteractionResponseBuilder()
@@ -94,6 +62,22 @@ let sellItem (event : ComponentInteractionCreateEventArgs) player itemId =
|> Async.AwaitTask
}
+let handleBuyItem (ctx : InteractionContext) itemId =
+ Game.executePlayerAction ctx (fun player -> async {
+ let item = Armoury.battleItems |> Array.find (fun w -> w.Id = itemId)
+ let newBalance = player.Bank - item.Cost
+ if newBalance >= 0 then
+ let playerHasItem = player.Arsenal |> Array.exists (fun w -> item.Id = w.Id)
+ if not playerHasItem then
+ let p = { player with Bank = newBalance ; Arsenal = Array.append [| item |] player.Arsenal }
+ do! DbService.updatePlayer p
+ do! sendSimpleResponse ctx $"Successfully purchased {item.Name}! You now have {newBalance} remaining"
+ else
+ do! sendSimpleResponse ctx $"You already own this item!"
+ else
+ do! sendSimpleResponse ctx $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
+ })
+
let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
async {
let! playerResult = DbService.tryFindPlayer event.User.Id
@@ -112,17 +96,15 @@ let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCrea
type Store() =
inherit ApplicationCommandModule ()
+// []
- []
- member _.ViewStore (ctx : InteractionContext) = viewStore ctx
+// member _.ViewStore (ctx : InteractionContext) = viewStore ctx
[]
- member _.BuyHack (ctx : InteractionContext, [