namespace Degenz open System open DSharpPlus open DSharpPlus.Entities open Degenz module Inventory = let getItemsByType itemType inventory = match itemType with | ItemType.Hack -> inventory |> List.filter (fun item -> match item.Type with ItemType.Hack _ -> true | _ -> false) | ItemType.Shield -> inventory |> List.filter (fun item -> match item.Type with ItemType.Shield _ -> true | _ -> false) | ItemType.Food -> inventory |> List.filter (fun item -> match item.Type with ItemType.Food _ -> true | _ -> false) | ItemType.Accessory -> inventory |> List.filter (fun item -> match item.Type with ItemType.Accessory _ -> true | _ -> false) | ItemType.Jpeg -> inventory |> List.filter (fun item -> match item.Type with ItemType.Jpeg _ -> true | _ -> false) | ItemType.Misc -> inventory |> List.filter (fun item -> match item.Type with ItemType.Misc _ -> true | _ -> false) let findItemById id (inventory : Inventory) = inventory |> List.find (fun item -> item.Id = id) let getBuyPrice item = match item.Attributes with CanBuy price -> price | _ -> 0 let getHackItem item = match item.Type , item.Attributes with | ItemType.Hack , CanBuy buyPrice & CanSell _ & CanAttack power & CanRateLimit cooldown & CanClass ``class``-> Some { Id = item.Id Name = item.Name Price = buyPrice Cooldown = cooldown IconUrl = item.IconUrl ImageUrl = item.ImageUrl Power = power Class = ``class`` } | _ -> None let getShieldItem item = match item.Type , item.Attributes with | ItemType.Shield , CanBuy buyPrice & CanSell _ & CanDefend resistance & CanRateLimit cooldown & CanClass ``class`` -> Some { Id = item.Id Name = item.Name Price = buyPrice Cooldown = cooldown IconUrl = item.IconUrl ImageUrl = item.ImageUrl Resistance = resistance Class = ``class`` } | _ -> None // let findHackById id inventory = // inventory |> List.pick (fun item -> match item with | Hack h -> (if h.Item.Id = id then Some h else None) | _ -> None) // let findShieldById id inventory = // inventory |> List.pick (fun item -> match item with | Shield s -> (if s.Item.Id = id then Some s else None) | _ -> None) // let findFoodById id inventory = // inventory |> List.pick (fun item -> match item with | Food f -> (if f.Item.Id = id then Some f else None) | _ -> None) // let findAccessoryById id inventory = // inventory |> List.pick (fun item -> match item with | Accessory a -> (if a.Item.Id = id then Some a else None) | _ -> None) // let getHacks inventory = inventory |> List.choose getHackItem let getShields inventory = inventory |> List.choose getShieldItem let getFoods inventory = inventory |> List.choose (fun item -> match item.Type with | ItemType.Food -> Some item | _ -> None) let getAccessories inventory = inventory |> List.choose (fun item -> match item.Type with | ItemType.Accessory -> Some item | _ -> None) module WeaponClass = let SameTargetAttackCooldown = TimeSpan.FromHours(4) let getClassButtonColor item = match item.Attributes with | CanClass "NETWORK" -> ButtonStyle.Danger | CanClass "EXPLOIT" -> ButtonStyle.Primary | CanClass "PENETRATION" -> ButtonStyle.Success | _ -> ButtonStyle.Primary let getClassEmbedColor item = match item.Attributes with | CanClass "NETWORK" -> DiscordColor.Red | CanClass "EXPLOIT" -> DiscordColor.Blurple | CanClass "PENETRATION" -> DiscordColor.Green | _ -> DiscordColor.Blurple let getGoodAgainst = function | "NETWORK" -> ( ItemId.FIREWALL , ItemId.VIRUS ) | "EXPLOIT" -> ( ItemId.ENCRYPTION , ItemId.REMOTE ) | "PENETRATION" -> ( ItemId.CYPHER , ItemId.WORM ) | _ -> ( ItemId.FIREWALL , ItemId.VIRUS ) module Player = let getHackEvents player = player.Events |> List.filter (fun act -> match act.Type with PlayerEventType.Hacking h -> h.IsInstigator | _ -> false) let getShieldEvents player = player.Events |> List.filter (fun act -> match act.Type with PlayerEventType.Shielding _ -> true | _ -> false) let removeExpiredActions player = let actions = player.Events |> List.filter (fun (act : PlayerEvent) -> let cooldown = TimeSpan.FromMinutes(int act.Cooldown) DateTime.UtcNow - act.Timestamp < cooldown) { player with Events = actions } let modifyBank (player : PlayerData) amount = { player with Bank = max (player.Bank + amount) 0 } module Arsenal = let weapons = DbService.getWeapons () |> Async.RunSynchronously let battleItemFormat (items : Inventory) = match items with | [] -> "None" | _ -> items |> List.map (fun item -> item.Name) |> String.concat ", " let actionFormat items (actions : PlayerEvent List) = match actions with | [] -> "None" | acts -> acts |> List.map (fun event -> match event.Type with | Hacking h -> let item = items |> Inventory.findItemById h.HackId let cooldown = Messaging.getTimeText false WeaponClass.SameTargetAttackCooldown event.Timestamp $"Hacked {h.Adversary.Name} with {item.Name} {cooldown} ago" | Shielding id -> let item = items |> Inventory.findItemById id let cooldown = Messaging.getTimeText true (TimeSpan.FromMinutes(int event.Cooldown)) event.Timestamp $"{item.Name} Shield active for {cooldown}" | _ -> "") |> List.filter (String.IsNullOrWhiteSpace >> not) |> String.concat "\n" let statusFormat p = let hacks = Player.getHackEvents p $"**Hacks:** {Inventory.getItemsByType ItemType.Hack p.Inventory |> battleItemFormat}\n **Shields:** {Inventory.getItemsByType ItemType.Shield p.Inventory |> battleItemFormat}\n **Hack Attacks:**\n{hacks |> List.take (min hacks.Length 10) |> actionFormat weapons}\n **Active Shields:**\n{Player.getShieldEvents p |> actionFormat weapons}"