115 lines
5.3 KiB
Forth
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}"
|
|
|