Move some stuff around

This commit is contained in:
Joseph Ferano 2022-02-01 19:54:52 +07:00
parent 69545bf3a6
commit ef3d5c58f5
12 changed files with 270 additions and 286 deletions

View File

@ -1,6 +1,5 @@
module Degenz.Bot
open System
open System.Threading.Tasks
open DSharpPlus
open DSharpPlus.SlashCommands

View File

@ -11,8 +11,8 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="paket.references" />
<Compile Include="GameConfig.fs" />
<Compile Include="GuildEnvironment.fs" />
<Compile Include="Game.fs" />
<Compile Include="Embeds.fs" />
<Compile Include="Store.fs" />
<Compile Include="Trainer.fs" />

View File

@ -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<DiscordComponent>
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<DiscordComponent>
let embed =

15
Bot/Game.fs Normal file
View File

@ -0,0 +1,15 @@
module Degenz.Game
open System.Threading.Tasks
open DSharpPlus.SlashCommands
open Degenz.DbService
let executePlayerAction (ctx : InteractionContext) (dispatch : PlayerData -> Async<unit>) =
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

View File

@ -1 +0,0 @@
module Degenz.GameConfig

View File

@ -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<GBT> } ; 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,10 +171,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
}
let defend (ctx : InteractionContext) =
async {
let! player = DbService.tryFindPlayer ctx.Member.Id
match player with
| Some player ->
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)
@ -189,9 +182,7 @@ let defend (ctx : InteractionContext) =
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
| None -> do! notYetAHackerMsg ctx
} |> Async.StartAsTask
:> Task
})
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

View File

@ -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
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 <- statusFormat updatedPlayer
builder.Content <- Messaging.statusFormat updatedPlayer
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
do! DbService.updatePlayer updatedPlayer
| None -> do! notYetAHackerMsg ctx
} |> Async.StartAsTask
:> Task
})
type PlayerInteractions() =
inherit ApplicationCommandModule ()

View File

@ -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,11 +13,8 @@ type SlotMachine() =
inherit ApplicationCommandModule ()
[<SlashCommand("spin", "Want to try your luck?")>]
member this.AttackCommand (ctx : InteractionContext) =
async {
let! playerResult = DbService.tryFindPlayer ctx.Member.Id
match playerResult with
| Some player ->
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)]
@ -73,8 +70,5 @@ type SlotMachine() =
do! ctx.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
})
| None -> do! notYetAHackerMsg ctx
} |> Async.StartAsTask
:> Task

View File

@ -8,54 +8,27 @@ 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<GBT> 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 ->
Game.executePlayerAction ctx (fun player -> async {
let hasInventoryToSell = Array.length player.Arsenal > 0
if hasInventoryToSell then
let builder = DiscordInteractionResponseBuilder()
@ -74,17 +47,12 @@ let sell (ctx : InteractionContext) =
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! 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<GBT> 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 ()
// [<SlashCommand("view-store", "View items available for purchase")>]
[<SlashCommand("view-store", "View items available for purchase")>]
member _.ViewStore (ctx : InteractionContext) = viewStore ctx
// 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 : HackId) =
buyItem ctx (int hackId)
member _.BuyHack (ctx : InteractionContext) = buyItem ctx Hack
[<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 : ShieldId) =
buyItem ctx (int shieldId)
member this.BuyShield (ctx : InteractionContext) = buyItem ctx Shield
[<SlashCommand("sell", "Sell an item in your inventory for GoodBoyTokenz")>]
member this.SellItem (ctx : InteractionContext) = sell ctx

View File

@ -5,11 +5,11 @@ open DSharpPlus
open DSharpPlus.Entities
open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Degenz.Shared
open Degenz.Store
open Degenz.Types
open Degenz.Messaging
let defaultHack = armoury |> Array.find (fun i -> i.Id = int HackId.Virus)
let defaultShield = armoury |> Array.find (fun i -> i.Id = int ShieldId.Firewall)
let defaultHack = Armoury.battleItems |> Array.find (fun i -> i.Id = int HackId.Virus)
let defaultShield = Armoury.battleItems |> Array.find (fun i -> i.Id = int ShieldId.Firewall)
let sendInitialEmbed (client : DiscordClient) =
async {
@ -41,10 +41,10 @@ let handleTrainerStep1 (event : ComponentInteractionCreateEventArgs) =
|> Async.AwaitTask
match maybePlayer with
| Some _ ->
do! Message.sendFollowUpMessageWithButton event step1Msg
do! sendFollowUpMessageWithButton event step1Msg
| None ->
let msg = "Looks like an error occurred, you're not a registered degenerate. Please contact a moderator."
do! Message.sendFollowUpMessage event msg
do! sendFollowUpMessage event msg
}
let handleTrainerStep2 (event : ComponentInteractionCreateEventArgs) =
@ -53,19 +53,19 @@ let handleTrainerStep2 (event : ComponentInteractionCreateEventArgs) =
match result with
| Some player ->
let weaponName = Player.shields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
do! Message.updateMessageWithGreyedOutButtons event step1Msg
do! updateMessageWithGreyedOutButtons event step1Msg
let shieldMessage =
if Player.shields player |> Array.isEmpty
then $"You do not have any Shields in your arsenal, here's a {defaultShield.Name} you can use for now"
else $"You currently have {weaponName} in your arsenal"
do! Message.sendFollowUpMessage event
do! sendFollowUpMessage event
($"First things first, let's get your system protected. Let's enable a shield to protect you from potential hackers. "
+ $"{shieldMessage}. To enable it and protect your system, you can use the `/defend` slash command to choose a shield."
+ $"\n\nRun the `/defend` command now and then select '{weaponName}'.")
| None ->
do! Message.sendFollowUpMessage event $"Something went wrong, please contact a moderator"
do! sendFollowUpMessage event $"Something went wrong, please contact a moderator"
}
let defend (ctx : InteractionContext) =
@ -100,7 +100,7 @@ let handleDefenseMsg = {
}
let handleDefense (event : ComponentInteractionCreateEventArgs) =
let sendMessage' = Message.sendFollowUpMessage event
let sendMessage' = sendFollowUpMessage event
async {
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask
@ -116,7 +116,7 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) =
do! Async.Sleep 4000
do! sendMessage' $"Hacking attempt failed! {player.Name} defended hack from Degenz-Trainer and took {prize} from them! "
do! Async.Sleep 3000
do! Message.sendFollowUpMessageWithButton event handleDefenseMsg
do! sendFollowUpMessageWithButton event handleDefenseMsg
| None ->
do! sendMessage' $"Something went wrong, please contact a moderator"
}
@ -127,19 +127,19 @@ let handleTrainerStep4 (event : ComponentInteractionCreateEventArgs) =
match result with
| Some player ->
let weaponName = Player.hacks player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
do! Message.updateMessageWithGreyedOutButtons event handleDefenseMsg
do! updateMessageWithGreyedOutButtons event handleDefenseMsg
let hackMessage =
if Player.shields player |> Array.isEmpty
then $"You do not have any Hacks in your arsenal, here's a {defaultHack.Name} you can use for now"
else $"You currently have {weaponName} in your arsenal"
do! Message.sendFollowUpMessage event
do! sendFollowUpMessage event
($"Next why don't you try hacking me. {hackMessage}. To hack me and get some money, "
+ $" you can use the '/hack' slash command and select a user to hack, then choose the hack attack you wish to use."
+ $"\n\nRun the `/hack` command now and pick me as your target, then click on the '{weaponName}' button.")
| None ->
do! Message.sendInteractionEvent event $"Something went wrong, please contact a moderator"
do! sendInteractionEvent event $"Something went wrong, please contact a moderator"
}
let attack (ctx : InteractionContext) (target : DiscordUser) =
@ -184,7 +184,7 @@ let handleAttackMsg = {
}
let handleAttack (event : ComponentInteractionCreateEventArgs) =
let sendMessage' = Message.sendFollowUpMessage event
let sendMessage' = sendFollowUpMessage event
async {
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredMessageUpdate)
|> Async.AwaitTask
@ -200,7 +200,7 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
do! sendMessage' ("Look at that, you are now officially an elite haxor! By successfully hacking other people you can earn GoodBoyTokenz. "
+ "Hacks take time to recover so check back in later once you've used all your hacks.")
do! Async.Sleep 7000
do! Message.sendFollowUpMessageWithButton event handleAttackMsg
do! sendFollowUpMessageWithButton event handleAttackMsg
| None ->
do! sendMessage' $"Something went wrong, please contact a moderator"
}
@ -214,7 +214,7 @@ let handleTrainerStep6 (event : ComponentInteractionCreateEventArgs) =
let builder = DiscordFollowupMessageBuilder()
builder.IsEphemeral <- true
builder.Content <- "Get out of here!"
do! Message.updateMessageWithGreyedOutButtons event handleAttackMsg
do! updateMessageWithGreyedOutButtons event handleAttackMsg
do! event.Interaction.CreateFollowupMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
@ -230,6 +230,6 @@ let handleButtonEvent (event : ComponentInteractionCreateEventArgs) =
| 4 -> do! handleTrainerStep4 event
| 5 -> do! handleAttack event
| 6 -> do! handleTrainerStep6 event
| _ -> do! Message.sendFollowUpMessage event "No action found"
| _ -> do! sendFollowUpMessage event "No action found"
}

View File

@ -2,7 +2,8 @@
open System
open System.Collections.Generic
open Degenz.Shared
open System.Threading.Tasks
open Degenz.Types
open MongoDB.Bson
open MongoDB.Bson.Serialization
open MongoDB.Driver
@ -62,7 +63,7 @@ let private playerMap (player : PlayerData) = {
let private mapBack (player : PlayerEntry) : PlayerData = {
DiscordId = player.DiscordId
Name = player.Name
Arsenal = player.Arsenal |> Array.map (fun w -> armoury |> Array.find (fun w' -> w = w'.Id))
Arsenal = player.Arsenal |> Array.map (fun w -> Armoury.battleItems |> Array.find (fun w' -> w = w'.Id))
Actions =
let atks = player.Attacks |> Array.map attackToAction
let dfns = player.Defenses |> Array.map defenseToAction
@ -113,6 +114,7 @@ let updatePlayer (player : PlayerData) =
return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
}
//let getTopPlayers amount =
// async {
// return! players.FindAsync()

View File

@ -1,4 +1,4 @@
module Degenz.Shared
namespace Degenz
open System
open DSharpPlus
@ -7,6 +7,9 @@ open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Newtonsoft.Json
[<Microsoft.FSharp.Core.AutoOpen>]
module Types =
[<Measure>]
type mins
@ -73,6 +76,14 @@ type PlayerData =
Actions : Action array
Bank : int<GBT> }
module Armoury =
let battleItems =
let file = System.IO.File.ReadAllText("Items.json")
JsonConvert.DeserializeObject<BattleItem array>(file)
let getItem itemId = battleItems |> Array.find (fun w -> w.Id = itemId)
module Player =
let hacks player = player.Arsenal |> Array.filter (fun bi -> bi.Type = Hack)
let shields player = player.Arsenal |> Array.filter (fun bi -> bi.Type = Shield)
@ -81,24 +92,24 @@ module Player =
|> Array.choose (fun act -> match act.Type with Attack ar -> Some (act,ar.Target,ar.Result) | Defense -> None)
let defenses player = player.Actions |> Array.filter (fun act -> match act.Type with Defense _ -> true | _ -> false)
let removeExpiredActions actions =
actions
|> Array.filter (fun (act : Action) ->
let item = Armoury.battleItems |> Array.find (fun w -> w.Id = act.ActionId)
DateTime.UtcNow - act.Timestamp < TimeSpan.FromMinutes(int item.Cooldown))
let modifyBank player amount = { player with Bank = max (player.Bank + amount) 0<GBT> }
let getAttacksFlat actions = actions |> Array.choose (fun act -> match act.Type with Attack ar -> Some (act,ar.Target,ar.Result) | Defense -> None)
let createSimpleResponseAsync msg (ctx: InteractionContext) =
async {
let builder = DiscordInteractionResponseBuilder()
builder.Content <- msg
builder.AsEphemeral true |> ignore
do!
ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
module Messaging =
type InteractiveMessage = {
ButtonId : string
ButtonText : string
Message : string
}
let notYetAHackerMsg =
createSimpleResponseAsync "You are currently not a hacker, first use the /redpill command to become one"
let hackDescription = ""
let statusFormat p =
$"Hacks: {Player.hacks p |> Array.toList}
Shields: {Player.shields p |> Array.toList}
@ -110,19 +121,15 @@ let constructButtons (actionType: string) (playerInfo: string) (weapons: BattleI
weapons
|> Array.map (fun w -> DiscordButtonComponent(ButtonStyle.Success, $"{actionType}-{w.Id}-{playerInfo}", $"{w.Name}"))
let modifyPlayerBank player amount = { player with Bank = max (player.Bank + amount) 0<GBT> }
let armoury =
let file = System.IO.File.ReadAllText("Items.json")
JsonConvert.DeserializeObject<BattleItem array>(file)
type InteractiveMessage = {
ButtonId : string
ButtonText : string
Message : string
let sendSimpleResponse (ctx: InteractionContext) msg =
async {
let builder = DiscordInteractionResponseBuilder()
builder.Content <- msg
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
module Message =
let sendFollowUpMessage (event : ComponentInteractionCreateEventArgs) msg =
async {
let builder = DiscordFollowupMessageBuilder()