115 lines
5.3 KiB
Forth

namespace Degenz
open System.Threading.Tasks
open DSharpPlus
open DSharpPlus.Entities
open DSharpPlus.EventArgs
open DSharpPlus.SlashCommands
open Degenz.DbService
module Game =
let HackPrize = 10<GBT>
let ShieldPrize = 5<GBT>
let SameTargetAttackCooldown = System.TimeSpan.FromHours(6)
let getClassButtonColor = function
| Network -> ButtonStyle.Danger
| Exploit -> ButtonStyle.Success
| Penetration -> ButtonStyle.Primary
let getClassEmbedColor = function
| Network -> DiscordColor.Red
| Penetration -> DiscordColor.Blurple
| Exploit -> DiscordColor.Green
let getGoodAgainst = function
| BattleClass.Network -> ( ShieldId.Firewall , HackId.Virus )
| BattleClass.Penetration -> ( ShieldId.Cypher , HackId.RemoteAccess )
| BattleClass.Exploit -> ( ShieldId.Encryption , HackId.Worm )
let executePlayerInteraction (ctx : InteractionContext) (dispatch : PlayerData -> Async<unit>) =
async {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- "Content"
do! ctx.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, builder)
|> Async.AwaitTask
let! playerResult = tryFindPlayer ctx.Member.Id
match playerResult with
| Some player -> do! dispatch player
| None -> do! Messaging.sendFollowUpMessageFromCtx ctx "You are currently not a hacker, first use the /redpill command to become one"
} |> Async.StartAsTask
:> Task
// TODO J: Create an abstraction for these two helper functions
let executePlayerEvent (event : ComponentInteractionCreateEventArgs) (dispatch : PlayerData -> Async<unit>) =
async {
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- "Content"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.DeferredChannelMessageWithSource, builder)
|> Async.AwaitTask
let! playerResult = tryFindPlayer event.User.Id
match playerResult with
| Some player -> do! dispatch player
| None -> do! Messaging.sendInteractionEvent event "You are currently not a hacker, first use the /redpill command to become one"
} |> Async.StartAsTask
:> Task
module Player =
let getItems itemType (player : PlayerData) = player.Arsenal |> Array.filter (fun i -> i.Type = itemType)
let getHacks (player : PlayerData) = getItems ItemType.Hack player
let getShields (player : PlayerData) = getItems ItemType.Shield player
let getAttacks player =
player.Actions
|> Array.filter (fun act -> match act.Type with Attack _ -> true | _ -> false)
let getDefenses player = player.Actions |> Array.filter (fun act -> match act.Type with Defense -> true | _ -> false)
let removeExpiredActions filterByAttackCooldown player =
let actions =
player.Actions
|> Array.filter (fun (act : Action) ->
let item = Armory.getItem act.ActionId
match act.Type , filterByAttackCooldown with
| Attack _ , true -> System.DateTime.UtcNow - act.Timestamp < System.TimeSpan.FromMinutes(int item.Cooldown)
| Attack _ , false -> System.DateTime.UtcNow - act.Timestamp < Game.SameTargetAttackCooldown
| Defense , _ -> System.DateTime.UtcNow - act.Timestamp < System.TimeSpan.FromMinutes(int item.Cooldown))
{ player with Actions = actions }
let modifyBank (player : PlayerData) 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)
module Arsenal =
let battleItemFormat (items : BattleItem array) =
match items with
| [||] -> "None"
| _ -> items |> Array.toList |> List.map (fun i -> i.Name) |> String.concat ", "
let actionFormat (actions : Action array) =
match actions with
| [||] -> "None"
| _ ->
let hacks , defenses = actions |> Array.partition (fun act -> match act.Type with Attack _ -> true | Defense -> false)
let hacks = hacks |> Array.take (min hacks.Length 10)
hacks
|> Array.append defenses
|> Array.map (fun act ->
let item = Armory.getItem act.ActionId
match act.Type with
| Attack atk ->
let cooldown = Messaging.getTimeText false Game.SameTargetAttackCooldown act.Timestamp
$"Hacked {atk.Target.Name} {cooldown} ago"
| Defense ->
let cooldown = Messaging.getTimeText true (System.TimeSpan.FromMinutes(int item.Cooldown)) act.Timestamp
$"{item.Name} Shield active for {cooldown}")
|> String.concat "\n"
let statusFormat p =
$"**Hacks:** {Player.getHacks p |> battleItemFormat}\n
**Shields:** {Player.getShields p |> battleItemFormat}\n
**Hack Attacks:**\n{Player.getAttacks p |> actionFormat}\n
**Active Shields:**\n{Player.getDefenses p |> actionFormat}"