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 getHackItem item = match item.Type , item.Attributes with | ItemType.Hack , CanBuy buyPrice & CanSell _ & CanAttack power & CanExpire cooldown & CanClass ``class``-> Some { Id = item.Id Name = item.Name Price = buyPrice Cooldown = cooldown Power = power Class = ``class`` } | _ -> None let getShieldItem item = match item.Type , item.Attributes with | ItemType.Shield , CanBuy buyPrice & CanSell _ & CanDefend resistance & CanExpire cooldown & CanClass ``class`` -> Some { Id = item.Id Name = item.Name Price = buyPrice Cooldown = cooldown 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 "0" -> ButtonStyle.Danger | CanClass "1" -> ButtonStyle.Primary | CanClass "2" -> ButtonStyle.Success | _ -> ButtonStyle.Primary let getClassEmbedColor item = match item.Attributes with | CanClass "0" -> DiscordColor.Red | CanClass "1" -> DiscordColor.Blurple | CanClass "2" -> DiscordColor.Green | _ -> DiscordColor.Blurple let getGoodAgainst = function | "0" -> ( ItemId.Firewall , ItemId.Virus ) | "1" -> ( ItemId.Encryption , ItemId.RemoteAccess ) | _ -> ( ItemId.Cypher , ItemId.Worm ) 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 PlayerStats = // 2.09f would go from 100 to 0 in roughly 48 hours let Strength = { Id = StatId.Strength ; BaseDecayRate = 2.09 ; BaseRange = Range.normalized } let Focus = { Id = StatId.Focus ; BaseDecayRate = 2.09 ; BaseRange = Range.normalized } let Luck = { Id = StatId.Luck ; BaseDecayRate = 2.09 ; BaseRange = Range.normalized } let Charisma = { Id = StatId.Charisma ; BaseDecayRate = 2.09 ; BaseRange = Range.normalized } let stats = [ Strength ; Focus ; Charisma ; Luck ] let getPlayerStat (statConfig : StatConfig) player = match statConfig.Id with | StatId.Strength -> player.Stats.Strength | StatId.Focus -> player.Stats.Focus | StatId.Charisma -> player.Stats.Charisma | StatId.Luck -> player.Stats.Luck | _ -> player.Stats.Luck let calculateActiveStat statId amount items = let statConfig = stats |> List.find (fun s -> s.Id = statId) // let hoursElapsed = (DateTime.UtcNow - lastRead).Hours // let totalDecay = float hoursElapsed * statConfig.BaseDecayRate let modMinMax = let min = items |> List.choose (fun i -> match i.Attributes with CanModify fx -> Some fx | _ -> None) |> List.concat |> List.sumBy (fun fx -> match fx.Effect with | Min x -> x | _ -> 0) let max = items |> List.choose (fun i -> match i.Attributes with CanModify fx -> Some fx | _ -> None) |> List.concat |> List.sumBy (fun fx -> match fx.Effect with | Max x -> x | _ -> 0) Range.create (statConfig.BaseRange.Min + min) (statConfig.BaseRange.Max + max) let amountAfterDecay = modMinMax |> Range.constrain amount { Id = statId ; Amount = amountAfterDecay ; ModRange = modMinMax ; LastRead = DateTime.UtcNow } module Arsenal = 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 p.Inventory}\n **Active Shields:**\n{Player.getShieldEvents p |> actionFormat p.Inventory}"