Add hacker gif when issuing a hack command. Disable slot machine

This commit is contained in:
Joseph Ferano 2022-01-21 14:50:57 +07:00
parent a007f55c55
commit 9af3f7ef9d
9 changed files with 234 additions and 188 deletions

View File

@ -19,9 +19,10 @@ let playerInteractionsConfig = DiscordConfiguration()
let trainerConfig = DiscordConfiguration() let trainerConfig = DiscordConfiguration()
let hackerBattleConfig = DiscordConfiguration() let hackerBattleConfig = DiscordConfiguration()
let storeConfig = DiscordConfiguration() let storeConfig = DiscordConfiguration()
let slotMachineConfig = DiscordConfiguration() //let slotMachineConfig = DiscordConfiguration()
let configs = [| playerInteractionsConfig ; trainerConfig ; hackerBattleConfig ; storeConfig ; slotMachineConfig ; |] //let configs = [| playerInteractionsConfig ; trainerConfig ; hackerBattleConfig ; storeConfig ; slotMachineConfig ; |]
let configs = [| playerInteractionsConfig ; trainerConfig ; hackerBattleConfig ; storeConfig |]
for conf in configs do for conf in configs do
conf.TokenType <- TokenType.Bot conf.TokenType <- TokenType.Bot
@ -36,7 +37,7 @@ playerInteractionsConfig.Token <- Environment.GetEnvironmentVariable("BOT_PLAYER
trainerConfig.Token <- Environment.GetEnvironmentVariable("BOT_TRAINER") trainerConfig.Token <- Environment.GetEnvironmentVariable("BOT_TRAINER")
hackerBattleConfig.Token <- Environment.GetEnvironmentVariable("BOT_HACKER_BATTLE") hackerBattleConfig.Token <- Environment.GetEnvironmentVariable("BOT_HACKER_BATTLE")
storeConfig.Token <- Environment.GetEnvironmentVariable("BOT_STORE") storeConfig.Token <- Environment.GetEnvironmentVariable("BOT_STORE")
slotMachineConfig.Token <- Environment.GetEnvironmentVariable("BOT_SLOT_MACHINE") //slotMachineConfig.Token <- Environment.GetEnvironmentVariable("BOT_SLOT_MACHINE")
//config.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace //config.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace
@ -44,24 +45,26 @@ let playerInteractionsBot = new DiscordClient(playerInteractionsConfig)
let trainerBot = new DiscordClient(trainerConfig) let trainerBot = new DiscordClient(trainerConfig)
let hackerBattleBot = new DiscordClient(hackerBattleConfig) let hackerBattleBot = new DiscordClient(hackerBattleConfig)
let storeBot = new DiscordClient(storeConfig) let storeBot = new DiscordClient(storeConfig)
let slotMachineBot = new DiscordClient(slotMachineConfig) //let slotMachineBot = new DiscordClient(slotMachineConfig)
hackerBattleBot.add_ComponentInteractionCreated(AsyncEventHandler(HackerBattle.handleButtonEvent)) hackerBattleBot.add_ComponentInteractionCreated(AsyncEventHandler(HackerBattle.handleButtonEvent))
trainerBot.add_ComponentInteractionCreated(AsyncEventHandler(Trainer.handleButtonEvent)) trainerBot.add_ComponentInteractionCreated(AsyncEventHandler(Trainer.handleButtonEvent))
storeBot.add_ComponentInteractionCreated(AsyncEventHandler(Store.handleSellButtonEvents))
let clients = [| playerInteractionsBot ; trainerBot ; hackerBattleBot ; storeBot ; slotMachineBot |] //let clients = [| storeBot ; trainerBot ; hackerBattleBot ; playerInteractionsBot ; slotMachineBot |]
let clients = [| storeBot ; trainerBot ; hackerBattleBot ; playerInteractionsBot |]
let sc1 = playerInteractionsBot.UseSlashCommands() let sc1 = playerInteractionsBot.UseSlashCommands()
let sc2 = trainerBot.UseSlashCommands() let sc2 = trainerBot.UseSlashCommands()
let sc3 = hackerBattleBot.UseSlashCommands() let sc3 = hackerBattleBot.UseSlashCommands()
let sc4 = storeBot.UseSlashCommands() let sc4 = storeBot.UseSlashCommands()
let sc5 = slotMachineBot.UseSlashCommands() //let sc5 = slotMachineBot.UseSlashCommands()
sc1.RegisterCommands<PlayerInteractions>(guild); sc1.RegisterCommands<PlayerInteractions>(guild);
sc2.RegisterCommands<Trainer>(guild); sc2.RegisterCommands<Trainer>(guild);
sc3.RegisterCommands<HackerGame>(guild); sc3.RegisterCommands<HackerGame>(guild);
sc4.RegisterCommands<Store>(guild); sc4.RegisterCommands<Store>(guild);
sc5.RegisterCommands<SlotMachine>(guild); //sc5.RegisterCommands<SlotMachine>(guild);
let run (client : DiscordClient) = let run (client : DiscordClient) =
async { async {

View File

@ -27,8 +27,13 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
|> removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp) |> removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp)
do! DbService.updatePlayer <| { attacker with Attacks = updatedAttacks } do! DbService.updatePlayer <| { attacker with Attacks = updatedAttacks }
if updatedAttacks.Length < 2 then if updatedAttacks.Length < 2 then
let embed = DiscordEmbedBuilder()
embed.Color <- Optional(DiscordColor.PhthaloGreen)
embed.Description <- "Pick the hack that you want to use"
embed.ImageUrl <- "https://s10.gifyu.com/images/Hacker-Degenz-V2.gif"
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (constructEmbed "Pick the hack you wish to use.") |> ignore builder.AddEmbed (embed.Build()) |> ignore
let defenderInfo = $"{defender.DiscordId}-{target.Username}" let defenderInfo = $"{defender.DiscordId}-{target.Username}"
constructButtons "Attack" defenderInfo attacker.Weapons constructButtons "Attack" defenderInfo attacker.Weapons
@ -94,10 +99,10 @@ let defend (ctx : InteractionContext) =
let handleAttack (event : ComponentInteractionCreateEventArgs) = let handleAttack (event : ComponentInteractionCreateEventArgs) =
let updatePlayer amount attack p = let updatePlayer amount attack p =
{ p with Attacks = Array.append [| attack |] p.Attacks ; Bank = MathF.Max(p.Bank + amount, 0f) } { p with Attacks = Array.append [| attack |] p.Attacks ; Bank = Math.Max(p.Bank + amount, 0) }
async { async {
let split = event.Id.Split("-") let split = event.Id.Split("-")
let weapon = Enum.Parse(typedefof<Weapon>, split.[1]) :?> Weapon let weapon = Enum.Parse(typedefof<Hack>, split.[1]) :?> Hack
let ( resultId , targetId ) = UInt64.TryParse split.[2] let ( resultId , targetId ) = UInt64.TryParse split.[2]
let! resultPlayer = DbService.tryFindPlayer event.User.Id let! resultPlayer = DbService.tryFindPlayer event.User.Id
let! resultTarget = DbService.tryFindPlayer targetId let! resultTarget = DbService.tryFindPlayer targetId
@ -114,7 +119,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
match wasSuccessfulHack with match wasSuccessfulHack with
| false -> | false ->
let prize = 1.337f // LEET let prize = 1.337f // LEET
let attack = { HackType = enum<Weapon>(int weapon) ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } } let attack = { HackType = enum<Hack>(int weapon) ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } }
// TODO: Make a single update instead of two // TODO: Make a single update instead of two
do! DbService.updatePlayer <| updatePlayer prize attack player do! DbService.updatePlayer <| updatePlayer prize attack player
do! DbService.updatePlayer { target with Bank = MathF.Max(target.Bank - prize, 0f)} do! DbService.updatePlayer { target with Bank = MathF.Max(target.Bank - prize, 0f)}
@ -139,7 +144,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|> Async.AwaitTask |> Async.AwaitTask
let attack = { HackType = enum<Weapon>(int weapon) ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } } let attack = { HackType = enum<Hack>(int weapon) ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } }
do! DbService.updatePlayer <| updatePlayer -prize attack player do! DbService.updatePlayer <| updatePlayer -prize attack player
do! DbService.updatePlayer { target with Bank = target.Bank + prize } do! DbService.updatePlayer { target with Bank = target.Bank + prize }

View File

@ -1,32 +1,32 @@
[ [
{ {
"Name" : "Virus", "Name" : "Virus",
"ItemType" : { "Case" : "Weapon" }, "ItemType" : { "Case" : "Hack" },
"Cost" : 5.0 "Cost" : 5.0
}, },
{ {
"Name" : "Ransom", "Name" : "Ransom",
"ItemType" : { "Case" : "Weapon" }, "ItemType" : { "Case" : "Hack" },
"Cost" : 10.0 "Cost" : 10.0
}, },
{ {
"Name" : "Worm", "Name" : "Worm",
"ItemType" : { "Case" : "Weapon" }, "ItemType" : { "Case" : "Hack" },
"Cost" : 5.0 "Cost" : 5.0
}, },
{ {
"Name" : "DDos", "Name" : "DDos",
"ItemType" : { "Case" : "Weapon" }, "ItemType" : { "Case" : "Hack" },
"Cost" : 10.0 "Cost" : 10.0
}, },
{ {
"Name" : "Crack", "Name" : "Crack",
"ItemType" : { "Case" : "Weapon" }, "ItemType" : { "Case" : "Hack" },
"Cost" : 5.0 "Cost" : 5.0
}, },
{ {
"Name" : "Injection", "Name" : "Injection",
"ItemType" : { "Case" : "Weapon" }, "ItemType" : { "Case" : "Hack" },
"Cost" : 10.0 "Cost" : 10.0
}, },
{ {
@ -39,24 +39,24 @@
"ItemType" : { "Case" : "Shield" }, "ItemType" : { "Case" : "Shield" },
"Cost" : 10.0 "Cost" : 10.0
}, },
{
"Name" : "Cypher",
"ItemType" : { "Case" : "Shield" },
"Cost" : 5.0
},
{ {
"Name" : "Encryption", "Name" : "Encryption",
"ItemType" : { "Case" : "Shield" }, "ItemType" : { "Case" : "Shield" },
"Cost" : 10.0
},
{
"Name" : "Sanitation",
"ItemType" : { "Case" : "Shield" },
"Cost" : 5.0 "Cost" : 5.0
}, },
{ {
"Name" : "Hardening", "Name" : "Hardening",
"ItemType" : { "Case" : "Shield" }, "ItemType" : { "Case" : "Shield" },
"Cost" : 10.0 "Cost" : 10.0
},
{
"Name" : "Cypher",
"ItemType" : { "Case" : "Shield" },
"Cost" : 5.0
},
{
"Name" : "Sanitation",
"ItemType" : { "Case" : "Shield" },
"Cost" : 10.0
} }
] ]

View File

@ -75,6 +75,13 @@ module Commands =
} |> Async.StartAsTask } |> Async.StartAsTask
:> Task :> Task
[<CLIMutable>]
type LeaderboardEntry = {
Position : string
Amount : string
Name : string
}
let leaderboard (ctx : InteractionContext) = let leaderboard (ctx : InteractionContext) =
async { async {
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
@ -82,12 +89,12 @@ module Commands =
let! leaders = DbService.getTopPlayers 10 let! leaders = DbService.getTopPlayers 10
let content = let content =
// TODO: There's a bug, it's not in the right order
leaders leaders
|> Seq.toArray |> Seq.toArray
|> Array.mapi (fun i p -> $"{i + 1}. {p.Bank} {p.Name}") |> Array.sortByDescending (fun p -> p.Bank)
|> String.concat "\n" |> Array.mapi (fun i p -> { Position = string (i + 1) ; Amount = string p.Bank ; Name = p.Name })
builder.Content <- if not <| String.IsNullOrEmpty content then content else "There are no active hackers" |> Formatter.Format
builder.Content <- if not <| String.IsNullOrEmpty content then $"```{content}```" else "There are no active hackers"
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask |> Async.AwaitTask
} |> Async.StartAsTask } |> Async.StartAsTask

View File

@ -8,6 +8,7 @@ open DSharpPlus.SlashCommands
open Degenz open Degenz
open Degenz.Shared open Degenz.Shared
open Newtonsoft.Json open Newtonsoft.Json
open AsciiTableFormatter
let store = let store =
try try
@ -16,180 +17,209 @@ let store =
|> Array.groupBy (fun (i : Item) -> i.ItemType) |> Array.groupBy (fun (i : Item) -> i.ItemType)
with _ -> [||] with _ -> [||]
//[<Sealed>]
//type Table() =
// member val Name = "" with get , set
// member val Cost = "" with get , set
// member val Class = "" with get , set
//
[<CLIMutable>]
type Table = {
Name : string
Cost : string
Class : string
}
let storeListing = let storeListing =
store store
|> Array.map (fun ( itemType , items ) -> |> Array.map (fun ( itemType , items ) ->
let itemList = items |> Array.map (fun i -> $"{i.Name} - {i.Cost} GBT") |> String.concat "\n" let itemsData =
(constructEmbed $"{itemType}:\n{itemList}")) items
|> Array.map (fun (item : Item) ->
let itemClass =
if itemType = ItemType.Hack
then weaponInventory
|> Array.find (fun w -> item.Name = string w)
|> int
|> getClass
else shieldInventory
|> Array.find (fun w -> item.Name = string w)
|> int
|> getClass
{ Name = item.Name ; Cost = string item.Cost ; Class = string itemClass })
module Commands = let table = Formatter.Format(ResizeArray(itemsData))
let viewStore (ctx : InteractionContext) =
async {
let builder = DiscordInteractionResponseBuilder()
builder.AddEmbeds(storeListing) (constructEmbed $"**{itemType}s**\n```{table}```"))
.AsEphemeral(true)
|> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) let viewStore (ctx : InteractionContext) =
|> Async.AwaitTask async {
} |> Async.StartAsTask let builder = DiscordInteractionResponseBuilder()
:> Task
let getItems itemType = store |> Array.find (fun ( t , _ ) -> t = itemType) |> snd builder.AddEmbeds(storeListing)
.AsEphemeral(true)
|> ignore
let buyHack (ctx : InteractionContext) hackId = do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
async { |> Async.AwaitTask
let! playerResult = DbService.tryFindPlayer ctx.Member.Id } |> Async.StartAsTask
let weapons = getItems ItemType.Weapon :> Task
let weaponResult = weapons |> Array.tryFind (fun w -> w.Name = string hackId)
return! let getItems itemType = store |> Array.find (fun ( t , _ ) -> t = itemType) |> snd
match playerResult , weaponResult with
| Some player , Some item -> let buyHack (ctx : InteractionContext) hackId =
async { async {
let newBalance = player.Bank - item.Cost let! playerResult = DbService.tryFindPlayer ctx.Member.Id
if newBalance >= 0.0f then let weapons = getItems ItemType.Hack
let playerHasItem = player.Weapons |> Array.exists (fun w -> item.Name = string w) let weaponResult = weapons |> Array.tryFind (fun w -> w.Name = string hackId)
if not playerHasItem then return!
let weapon = weaponInventory |> Array.find (fun w -> item.Name = string w) match playerResult , weaponResult with
let p = { player with Bank = newBalance ; Weapons = Array.append [| weapon |] player.Weapons } | Some player , Some item ->
do! DbService.updatePlayer p async {
do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx let newBalance = player.Bank - item.Cost
else if newBalance >= 0 then
do! createSimpleResponseAsync $"You already own this item!" ctx 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 else
do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx do! createSimpleResponseAsync $"You already own this item!" ctx
} else
| None , _ -> notYetAHackerMsg ctx do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx
| _ -> createSimpleResponseAsync "Something is wrong" ctx }
} |> Async.StartAsTask | None , _ -> notYetAHackerMsg ctx
:> Task | _ -> createSimpleResponseAsync "Something is wrong" ctx
} |> Async.StartAsTask
:> Task
let buyShield (ctx : InteractionContext) shieldId = let buyShield (ctx : InteractionContext) shieldId =
async { async {
let! playerResult = DbService.tryFindPlayer ctx.Member.Id let! playerResult = DbService.tryFindPlayer ctx.Member.Id
let shieldResult = let shieldResult =
getItems ItemType.Shield getItems ItemType.Shield
|> Array.tryFind (fun w -> w.Name = string shieldId) |> Array.tryFind (fun w -> w.Name = string shieldId)
return! return!
match playerResult , shieldResult with match playerResult , shieldResult with
| Some player , Some item -> | Some player , Some item ->
async { async {
let newBalance = player.Bank - item.Cost let newBalance = player.Bank - item.Cost
if newBalance >= 0.0f then if newBalance >= 0 then
let playerHasItem = player.Shields |> Array.exists (fun w -> item.Name = string w) let playerHasItem = player.Shields |> Array.exists (fun w -> item.Name = string w)
if not playerHasItem then if not playerHasItem then
let shield = shieldInventory |> Array.find (fun w -> item.Name = string w) let shield = shieldInventory |> Array.find (fun w -> item.Name = string w)
let p = { player with Bank = newBalance ; Shields = Array.append [| shield |] player.Shields } let p = { player with Bank = newBalance ; Shields = Array.append [| shield |] player.Shields }
do! DbService.updatePlayer p do! DbService.updatePlayer p
do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx do! createSimpleResponseAsync $"Successfully purchased {item.Name}! You now have {newBalance} remaining" ctx
else
do! createSimpleResponseAsync $"You already own this item!" ctx
else else
do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx do! createSimpleResponseAsync $"You already own this item!" ctx
} else
| None , _ -> notYetAHackerMsg ctx do! createSimpleResponseAsync $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" ctx
| _ -> createSimpleResponseAsync "Something is wrong" ctx }
} |> Async.StartAsTask | None , _ -> notYetAHackerMsg ctx
:> Task | _ -> createSimpleResponseAsync "Something is wrong" ctx
} |> Async.StartAsTask
:> Task
let constructItemButtons playerInfo itemType (items : 'a array) = let constructItemButtons playerInfo itemType (items : 'a array) =
items items
|> Seq.map (fun item -> DiscordButtonComponent(ButtonStyle.Primary, $"{playerInfo}-{itemType}-{item}", $"{item}")) |> Seq.map (fun item -> DiscordButtonComponent(ButtonStyle.Primary, $"{playerInfo}-{itemType}-{item}", $"{item}"))
let sellItem (ctx : InteractionContext) = let sellItem (ctx : InteractionContext) =
async { async {
let! playerResult = DbService.tryFindPlayer ctx.Member.Id let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match playerResult with match playerResult with
| Some player -> | Some player ->
let hasInventoryToSell = Array.length player.Weapons + Array.length player.Shields > 0 let hasInventoryToSell = Array.length player.Weapons + Array.length player.Shields > 0
if hasInventoryToSell then if hasInventoryToSell then
let builder = DiscordInteractionResponseBuilder() let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (constructEmbed "Pick the item you wish to sell.") |> ignore builder.AddEmbed (constructEmbed "Pick the item you wish to sell.") |> ignore
Array.chunkBySize 3 player.Weapons Array.chunkBySize 3 player.Weapons
|> Array.iter |> Array.iter
(fun wps -> (fun wps ->
wps wps
|> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Primary, $"Weapon-{w}", $"{w}")) |> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Primary, $"Hack-{w}", $"{w}"))
|> Seq.cast<DiscordComponent> |> Seq.cast<DiscordComponent>
|> builder.AddComponents |> builder.AddComponents
|> ignore) |> ignore)
Array.chunkBySize 3 player.Shields Array.chunkBySize 3 player.Shields
|> Array.iter |> Array.iter
(fun shs -> (fun shs ->
shs shs
|> Array.map (fun s -> DiscordButtonComponent(ButtonStyle.Primary, $"Shield-{s}", $"{s}")) |> Array.map (fun s -> DiscordButtonComponent(ButtonStyle.Primary, $"Shield-{s}", $"{s}"))
|> Seq.cast<DiscordComponent> |> Seq.cast<DiscordComponent>
|> builder.AddComponents |> builder.AddComponents
|> ignore) |> ignore)
builder.AsEphemeral true |> ignore builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask |> Async.AwaitTask
else else
do! createSimpleResponseAsync "You currently have no inventory to sell" ctx do! createSimpleResponseAsync "You currently have no inventory to sell" ctx
| None -> do! notYetAHackerMsg ctx | None -> do! notYetAHackerMsg ctx
return () return ()
} |> Async.StartAsTask } |> Async.StartAsTask
:> Task :> Task
let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) = let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) =
async { async {
let! playerResult = DbService.tryFindPlayer event.User.Id let! playerResult = DbService.tryFindPlayer event.User.Id
match playerResult with match playerResult with
| Some player -> | Some player ->
let split = event.Id.Split("-") let split = event.Id.Split("-")
let itemType = match split.[0] with "Weapon" -> ItemType.Weapon | _ -> ItemType.Shield let itemType = match split.[0] with "Hack" -> ItemType.Hack | _ -> ItemType.Shield
let itemName = split.[1] let itemName = split.[1]
match itemType with match itemType with
| ItemType.Weapon -> | ItemType.Hack ->
let item = getItems ItemType.Weapon |> Array.find (fun w -> w.Name = itemName) let item = getItems ItemType.Hack |> Array.find (fun w -> w.Name = itemName)
let salePrice = item.Cost / 2.f let salePrice = item.Cost / 2
let updatedWeapons = player.Weapons |> Array.filter (fun (w : Weapon) -> string w <> itemName) let updatedWeapons = player.Weapons |> Array.filter (fun (w : Hack) -> string w <> itemName)
let updatedPlayer = { player with Bank = player.Bank + salePrice ; Weapons = updatedWeapons } let updatedPlayer = { player with Bank = player.Bank + salePrice ; Weapons = updatedWeapons }
do! DbService.updatePlayer updatedPlayer do! DbService.updatePlayer updatedPlayer
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Sold weapon {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.f
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() let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true builder.IsEphemeral <- true
builder.Content <- "An error occurred and the user doesn't not exist" builder.Content <- $"Sold hack {itemName} for {salePrice}! Current Balance: {updatedPlayer.Bank}"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|> Async.AwaitTask |> Async.AwaitTask
} |> Async.StartAsTask | ItemType.Shield ->
:> Task 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() = type Store() =
inherit ApplicationCommandModule () inherit ApplicationCommandModule ()
[<SlashCommand("store", "View items available for purchase")>] [<SlashCommand("store", "View items available for purchase")>]
member _.ViewStore (ctx : InteractionContext) = Commands.viewStore ctx member _.ViewStore (ctx : InteractionContext) = viewStore ctx
[<SlashCommand("buy-hack", "Purchase a hack attack you can use to earn GoodBoyTokenz")>] [<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 : Weapon) = member _.BuyHack (ctx : InteractionContext, [<Option("hack-id", "The ID of the hack you wish to purchase")>] hackId : Hack) =
Commands.buyHack ctx hackId buyHack ctx hackId
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GoodBoyTokenz")>] [<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) = member this.BuyShield (ctx : InteractionContext, [<Option("shield-id", "The ID of the shield you wish to purchase")>] shieldId : Shield) =
Commands.buyShield ctx shieldId buyShield ctx shieldId
[<SlashCommand("sell", "Sell an item in your inventory for GoodBoyTokenz")>] [<SlashCommand("sell", "Sell an item in your inventory for GoodBoyTokenz")>]
member this.SellItem (ctx : InteractionContext) = member this.SellItem (ctx : InteractionContext) = sellItem ctx
Commands.sellItem ctx

View File

@ -2,3 +2,4 @@ FSharp.Core
DSharpPlus DSharpPlus
DSharpPlus.SlashCommands DSharpPlus.SlashCommands
dotenv.net dotenv.net
DanielStout.AsciiTableFormatter

View File

@ -6,7 +6,7 @@ open DSharpPlus.Entities
open DSharpPlus.SlashCommands open DSharpPlus.SlashCommands
type ItemType = type ItemType =
| Weapon | Hack
| Shield | Shield
type ActionClass = type ActionClass =
@ -14,7 +14,7 @@ type ActionClass =
| Exploit | Exploit
| Penetration | Penetration
type Weapon = type Hack =
| Virus = 0 | Virus = 0
| Ransom = 1 | Ransom = 1
| Worm = 2 | Worm = 2
@ -34,20 +34,17 @@ type Shield =
type Item = { type Item = {
Name : string Name : string
ItemType : ItemType ItemType : ItemType
Cost : single Cost : int
} }
let weaponInventory = [| Weapon.Virus ; Weapon.Ransom ; Weapon.DDos ; Weapon.Worm ; Weapon.Crack ; Weapon.Injection |] let weaponInventory = [| Hack.Virus ; Hack.Ransom ; Hack.DDos ; Hack.Worm ; Hack.Crack ; Hack.Injection |]
let shieldInventory = [| Shield.Firewall ; Shield.PortScan ; Shield.Encryption ; Shield.Cypher ; Shield.Hardening ; Shield.Sanitation |] let shieldInventory = [| Shield.Firewall ; Shield.PortScan ; Shield.Encryption ; Shield.Cypher ; Shield.Hardening ; Shield.Sanitation |]
let getClass = let getClass =
function function
| 0 | 0 | 1 -> Network
| 1 -> Network | 2 | 3 -> Exploit
| 2 | 4 | _ -> Penetration
| 3 -> Exploit
| 4
| _ -> Penetration
type HackResult = type HackResult =
| Strong | Strong
@ -58,7 +55,7 @@ type DiscordPlayer = { Id: uint64; Name: string }
[<CLIMutable>] [<CLIMutable>]
type Attack = type Attack =
{ HackType: Weapon { HackType: Hack
Target: DiscordPlayer Target: DiscordPlayer
Timestamp: DateTime } Timestamp: DateTime }
@ -71,11 +68,11 @@ type Defense =
type Player = type Player =
{ DiscordId: uint64 { DiscordId: uint64
Name: string Name: string
Weapons: Weapon array Weapons: Hack array
Shields: Shield array Shields: Shield array
Attacks: Attack array Attacks: Attack array
Defenses: Defense array Defenses: Defense array
Bank: single } Bank: int }
let createSimpleResponseAsync msg (ctx: InteractionContext) = let createSimpleResponseAsync msg (ctx: InteractionContext) =

View File

@ -13,3 +13,5 @@ nuget DSharpPlus.SlashCommands >= 4.2.0-nightly-01061
nuget MongoDB.Driver nuget MongoDB.Driver
nuget dotenv.net 3.1.1 nuget dotenv.net 3.1.1
nuget DanielStout.AsciiTableFormatter

View File

@ -2,6 +2,7 @@ STORAGE: NONE
RESTRICTION: || (== net6.0) (== netstandard2.0) (== netstandard2.1) RESTRICTION: || (== net6.0) (== netstandard2.0) (== netstandard2.1)
NUGET NUGET
remote: https://api.nuget.org/v3/index.json remote: https://api.nuget.org/v3/index.json
DanielStout.AsciiTableFormatter (1.1)
DnsClient (1.5) DnsClient (1.5)
Microsoft.Win32.Registry (>= 5.0) Microsoft.Win32.Registry (>= 5.0)
System.Buffers (>= 4.5.1) - restriction: || (&& (== net6.0) (>= net471)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (< netstandard2.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= net471)) (&& (== netstandard2.1) (< netstandard2.0)) System.Buffers (>= 4.5.1) - restriction: || (&& (== net6.0) (>= net471)) (&& (== net6.0) (< netstandard2.0)) (&& (== net6.0) (< netstandard2.1)) (== netstandard2.0) (&& (== netstandard2.1) (>= net471)) (&& (== netstandard2.1) (< netstandard2.0))