diff --git a/Bot/Bot.fs b/Bot/Bot.fs index f58fcd8..93ae670 100644 --- a/Bot/Bot.fs +++ b/Bot/Bot.fs @@ -19,6 +19,7 @@ let storeConfig = DiscordConfiguration() let stealConfig = DiscordConfiguration() //let slotMachineConfig = DiscordConfiguration() //hackerBattleConfig.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace +//storeConfig.MinimumLogLevel <- Microsoft.Extensions.Logging.LogLevel.Trace //let configs = [| hackerBattleConfig ; storeConfig ; slotMachineConfig ; |] let configs = [ hackerBattleConfig ; storeConfig ; stealConfig ] @@ -99,20 +100,6 @@ stealBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously // return () //} |> Async.RunSynchronously -if guild = 922419263275425832uL then - let interactionsConfig = DiscordConfiguration() - interactionsConfig.TokenType <- TokenType.Bot - interactionsConfig.Intents <- DiscordIntents.All - interactionsConfig.Token <- GuildEnvironment.tokenPlayerInteractions - - let interactionsBot = new DiscordClient(interactionsConfig) - - let commands = interactionsBot.UseSlashCommands() - commands.RegisterCommands(guild) - - interactionsBot.ConnectAsync() |> Async.AwaitTask |> Async.RunSynchronously - - Task.Delay(-1) |> Async.AwaitTask |> Async.RunSynchronously diff --git a/Bot/DbService.fs b/Bot/DbService.fs index 45e60db..081b8d5 100644 --- a/Bot/DbService.fs +++ b/Bot/DbService.fs @@ -1,23 +1,23 @@ module Degenz.DbService -open Degenz open System open Npgsql.FSharp +open Degenz type User = { Name : string DiscordId : uint64 Bank : int Strength : int - Inventory : int array + Inventory : int list } let mapBack user : PlayerData = { DiscordId = user.DiscordId Name = user.Name - Inventory = user.Inventory |> Array.choose (fun id -> Armory.battleItems |> Array.tryFind (fun i -> i.Id = id)) + Inventory = user.Inventory |> List.choose (fun id -> Armory.battleItems |> List.tryFind (fun item -> item.Id = id)) Events = [||] - Traits = { PlayerTraits.empty with Strength = user.Strength } + Stats = [ { Id = StatId.Strength ; Amount = user.Strength } ] Bank = user.Bank } @@ -70,7 +70,7 @@ let tryFindPlayer connStr (discordId : uint64) = Name = read.string "display_name" Bank = read.int "gbt" * 1 Strength = read.int "strength" - Inventory = read.intArray "inventory" + Inventory = read.intArray "inventory" |> Array.toList }) |> Async.AwaitTask match List.tryHead user with @@ -90,8 +90,8 @@ let updatePlayer connStr (player : PlayerData) = |> Sql.parameters [ "did", Sql.string (string player.DiscordId) "gbt", Sql.int (int player.Bank) - "str", Sql.int (int player.Traits.Strength) - "inv", Sql.intArray (player.Inventory |> Array.map (fun i -> i.Id)) + "str", Sql.int (player |> Player.getStat StatId.Strength |> int) + "inv", Sql.intArray (player.Inventory |> Array.ofList |> Array.map (fun item -> item.Id)) ] |> Sql.query """ UPDATE "user" SET gbt = @gbt, strength = @str, inventory = @inv diff --git a/Bot/Embeds.fs b/Bot/Embeds.fs index c3d7097..9fd59a4 100644 --- a/Bot/Embeds.fs +++ b/Bot/Embeds.fs @@ -8,35 +8,29 @@ open DSharpPlus.Entities let hackGif = "https://s10.gifyu.com/images/Hacker-Degenz-V20ce8eb832734aa62-min.gif" let shieldGif = "https://s10.gifyu.com/images/Defense-Degenz-V2-min.gif" -let getHackIcon = function - | HackId.Virus -> "https://s10.gifyu.com/images/Virus-icon.jpg" - | HackId.RemoteAccess -> "https://s10.gifyu.com/images/Mind-Control-Degenz-V2-min.jpg" - | HackId.Worm -> "https://s10.gifyu.com/images/WormBugAttack_Degenz-min.jpg" +let getItemIcon id = + match enum(id) with + | ItemId.Virus -> "https://s10.gifyu.com/images/Virus-icon.jpg" + | ItemId.RemoteAccess -> "https://s10.gifyu.com/images/Mind-Control-Degenz-V2-min.jpg" + | ItemId.Worm -> "https://s10.gifyu.com/images/WormBugAttack_Degenz-min.jpg" + | ItemId.Firewall -> "https://s10.gifyu.com/images/Defense-GIF-1-Degenz-1.jpg" + | ItemId.Encryption -> "https://s10.gifyu.com/images/Encryption-Degenz-V2-1-min.jpg" + | ItemId.Cypher -> "https://s10.gifyu.com/images/Cypher-Smaller.jpg" | _ -> hackGif -let getShieldIcon = function - | ShieldId.Firewall -> "https://s10.gifyu.com/images/Defense-GIF-1-Degenz-1.jpg" - | ShieldId.Encryption -> "https://s10.gifyu.com/images/Encryption-Degenz-V2-1-min.jpg" - | ShieldId.Cypher -> "https://s10.gifyu.com/images/Cypher-Smaller.jpg" - | _ -> shieldGif - -let getHackGif = function - | HackId.Virus -> "https://s10.gifyu.com/images/Attack-DegenZ-1.gif" - | HackId.RemoteAccess -> "https://s10.gifyu.com/images/Mind-Control-Degenz-V2-min.gif" - | HackId.Worm -> "https://s10.gifyu.com/images/WormBugAttack_Degenz-min.gif" +let getItemGif id = + match enum(id) with + | ItemId.Virus -> "https://s10.gifyu.com/images/Attack-DegenZ-1.gif" + | ItemId.RemoteAccess -> "https://s10.gifyu.com/images/Mind-Control-Degenz-V2-min.gif" + | ItemId.Worm -> "https://s10.gifyu.com/images/WormBugAttack_Degenz-min.gif" + | ItemId.Firewall -> "https://s10.gifyu.com/images/Defense-GIF-1-Degenz-min.gif" + | ItemId.Encryption -> "https://s10.gifyu.com/images/Encryption-Degenz-V2-1-min.gif" + | ItemId.Cypher -> "https://s10.gifyu.com/images/Cypher-Smaller.gif" | _ -> hackGif -let getShieldGif = function - | ShieldId.Firewall -> "https://s10.gifyu.com/images/Defense-GIF-1-Degenz-min.gif" - | ShieldId.Encryption -> "https://s10.gifyu.com/images/Encryption-Degenz-V2-1-min.gif" - | ShieldId.Cypher -> "https://s10.gifyu.com/images/Cypher-Smaller.gif" - | _ -> shieldGif - -let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerData) itemType ignoreCooldown = - player - |> Player.getItems itemType - |> Array.sortBy (fun i -> i.Power) - |> Array.map (fun item -> +let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerData) items ignoreCooldown = + items + |> List.map (fun item -> let action = player.Events |> Array.tryFind (fun i -> @@ -44,7 +38,7 @@ let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerDat | Hacking h -> h.HackId = item.Id && h.IsInstigator | Shielding id -> id = item.Id | _ -> false) - let btnColor = WeaponClass.getClassButtonColor item.Class + let btnColor = WeaponClass.getClassButtonColor item match action , ignoreCooldown with | None , _ | Some _ , true -> DiscordButtonComponent(btnColor, $"{actionId}-{item.Id}-{buttonInfo}-{player.Name}", $"{item.Name}") @@ -54,17 +48,18 @@ let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerDat |> Seq.cast let pickDefense actionId player isTrainer = - let buttons = constructButtons actionId (string player.DiscordId) player ItemType.Shield isTrainer + let shieldItems = player |> Player.getShieldItems + let buttons = constructButtons actionId (string player.DiscordId) player shieldItems isTrainer let embed = DiscordEmbedBuilder() .WithTitle("Shield Defense") .WithDescription("Pick a shield to protect yourself from hacks") - for s in Player.getShields player |> Array.sortBy (fun i -> i.Power) do - let hours = TimeSpan.FromMinutes(int s.Cooldown).TotalHours - let against = WeaponClass.getGoodAgainst(s.Class) |> snd - embed.AddField(s.Name, $"Active {hours} hours\nDefeats {against}", true) |> ignore + for (item,sClass,cooldown) in Player.getShields player do + let hours = TimeSpan.FromMinutes(int cooldown).TotalHours + let against = WeaponClass.getGoodAgainst(sClass) |> snd + embed.AddField(item.Name, $"Active {hours} hours\nDefeats {against}", true) |> ignore DiscordFollowupMessageBuilder() .AddComponents(buttons) @@ -72,7 +67,8 @@ let pickDefense actionId player isTrainer = .AsEphemeral(true) let pickHack actionId attacker defender isTrainer = - let buttons = constructButtons actionId $"{defender.DiscordId}-{defender.Name}" attacker ItemType.Hack isTrainer + let hackItems = attacker |> Player.getHackItems + let buttons = constructButtons actionId $"{defender.DiscordId}-{defender.Name}" attacker hackItems isTrainer let stealMsg = if not isTrainer then $"{defender.Name} has **{defender.Bank} $GBT** we can take from them. " else "" let embed = @@ -81,9 +77,9 @@ let pickHack actionId attacker defender isTrainer = .WithDescription($"{stealMsg}Pick the hack you want to use.") if not isTrainer then - for h in Player.getHacks attacker |> Array.sortBy (fun i -> i.Power) do - let amount = if h.Power > int defender.Bank then int defender.Bank else h.Power - embed.AddField(h.Name, $"Cooldown {h.Cooldown} mins\nExtract {amount} $GBT", true) |> ignore + for (item,power,hClass,cooldown) in Player.getHacks attacker do + let amount = if power > int defender.Bank then int defender.Bank else power + embed.AddField(item.Name, $"Cooldown {cooldown} mins\nExtract {amount} $GBT", true) |> ignore DiscordFollowupMessageBuilder() .AddComponents(buttons) @@ -93,7 +89,7 @@ let pickHack actionId attacker defender isTrainer = let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : Item) = let embed = DiscordEmbedBuilder() - .WithImageUrl(getHackGif (enum(hack.Id))) + .WithImageUrl(getItemGif hack.Id) .WithTitle("Hack Attack") .WithDescription($"You successfully hacked <@{targetId}> using {hack.Name}" + (if earnedMoney then $", and took {amountTaken} 💰$GBT from them!" else "!")) @@ -102,10 +98,10 @@ let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : I .AddEmbed(embed.Build()) .AsEphemeral(true) -let responseCreatedShield (shield : Item) = - let embed = DiscordEmbedBuilder().WithImageUrl(getShieldGif (enum(shield.Id))) +let responseCreatedShield ((item,_,cooldown) : ShieldItem) = + let embed = DiscordEmbedBuilder().WithImageUrl(getItemGif item.Id) embed.Title <- "Mounted Shield" - embed.Description <- $"Mounted {shield.Name} shield for {TimeSpan.FromMinutes(int shield.Cooldown).Hours} hours" + embed.Description <- $"Mounted {item.Name} shield for {TimeSpan.FromMinutes(int cooldown).Hours} hours" DiscordFollowupMessageBuilder() .AddEmbed(embed) @@ -115,60 +111,52 @@ let eventSuccessfulHack (ctx : IDiscordContext) target prize = DiscordMessageBuilder() .WithContent($"{ctx.GetDiscordMember().Username} successfully hacked <@{target.DiscordId}> and took {prize} GoodBoyTokenz") -let getBuyItemsEmbed (player : PlayerData) (itemType : ItemType) (store : Item array) = +let getBuyItemsEmbed (playerInventory : Inventory) (storeInventory : Inventory) = let embeds , buttons = - store - |> Array.filter (fun i -> i.Type = itemType) - |> Array.map (fun item -> + storeInventory + |> List.map (fun item -> let embed = DiscordEmbedBuilder() match item.Type with - | ItemType.Hack -> - embed - .AddField($"$GBT Reward |", string item.Power, true) - .AddField("Cooldown |", $"{TimeSpan.FromMinutes(int item.Cooldown).Minutes} minutes", true) - .WithThumbnail(getHackIcon (enum(item.Id))) - |> ignore - | _ -> - embed + | Hack(power,_,cooldown) -> + embed.AddField($"$GBT Reward |", string power, true) + .AddField("Cooldown |", $"{TimeSpan.FromMinutes(int cooldown).Minutes} minutes", true) + .WithThumbnail(getItemIcon item.Id) + |> ignore + | Shield(shieldClass,cooldown) -> + embed.AddField($"Strong against |", WeaponClass.getGoodAgainst shieldClass |> snd |> string, true) // .AddField($"Defensive Strength |", string item.Power, true) - .AddField($"Strong against |", WeaponClass.getGoodAgainst item.Class |> snd |> string, true) - .AddField("Active For |", $"{TimeSpan.FromMinutes(int item.Cooldown).Hours} hours", true) - .WithThumbnail(getShieldIcon (enum(item.Id))) - |> ignore + .AddField("Active For |", $"{TimeSpan.FromMinutes(int cooldown).Hours} hours", true) + .WithThumbnail(getItemIcon item.Id) + |> ignore + | _ -> () embed .AddField("Price 💰", (if item.Price = 0 then "Free" else $"{item.Price} $GBT"), true) - .WithColor(WeaponClass.getClassEmbedColor item.Class) + .WithColor(WeaponClass.getClassEmbedColor item) .WithTitle($"{item.Name}") |> ignore let button = - if player.Inventory |> Array.exists (fun i -> i.Id = item.Id) - then DiscordButtonComponent(WeaponClass.getClassButtonColor item.Class, $"Buy-{item.Id}", $"Own {item.Name}", true) - else DiscordButtonComponent(WeaponClass.getClassButtonColor item.Class, $"Buy-{item.Id}", $"Buy {item.Name}") - embed.Build() , button :> DiscordComponent) - |> Array.unzip + if playerInventory |> List.exists (fun i -> i.Id = item.Id) + then DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Buy-{item.Id}", $"Own {item.Name}", true) + else DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Buy-{item.Id}", $"Buy {item.Name}") + ( embed.Build() , button :> DiscordComponent )) + |> List.unzip DiscordFollowupMessageBuilder() .AddEmbeds(embeds) .AddComponents(buttons) .AsEphemeral(true) -let getSellEmbed (itemType : ItemType) (player : PlayerData) = +let getSellEmbed (items : Item list) = let embeds , buttons = - player.Inventory - |> Array.filter (fun i -> i.Type = itemType) - |> Array.map (fun item -> - let embed = DiscordEmbedBuilder() - match item.Type with - | ItemType.Hack -> embed.WithThumbnail(getHackIcon (enum(item.Id))) |> ignore - | _ -> embed.WithThumbnail(getShieldIcon (enum(item.Id))) |> ignore - embed + items + |> List.map (fun item -> + DiscordEmbedBuilder() .AddField("Sell For 💰", $"{item.Price} $GBT", true) .WithTitle($"{item.Name}") - .WithColor(WeaponClass.getClassEmbedColor item.Class) - |> ignore - let button = DiscordButtonComponent(WeaponClass.getClassButtonColor item.Class, $"Sell-{item.Id}", $"Sell {item.Name}") - embed.Build() , button :> DiscordComponent) - |> Array.unzip + .WithColor(WeaponClass.getClassEmbedColor item) + .Build() + , DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Sell-{id}", $"Sell {item.Name}") :> DiscordComponent) + |> List.unzip DiscordFollowupMessageBuilder() .AddEmbeds(embeds) diff --git a/Bot/GameHelpers.fs b/Bot/GameHelpers.fs index 0bac34a..abe5637 100644 --- a/Bot/GameHelpers.fs +++ b/Bot/GameHelpers.fs @@ -9,35 +9,80 @@ module Armory = let file = System.IO.File.ReadAllText("Items.json") // let file = System.IO.File.ReadAllText("Bot/Items.json") JsonConvert.DeserializeObject(file) + |> Array.toList - let hacks = battleItems |> Array.filter (fun bi -> match bi.Type with ItemType.Hack -> true | _ -> false) - let shields = battleItems |> Array.filter (fun bi -> match bi.Type with ItemType.Shield -> true | _ -> false) + let hacks = battleItems |> List.filter (fun item -> match item.Type with Hack _ -> true | _ -> false) + let shields = battleItems |> List.filter (fun item -> match item.Type with Shield _ -> true | _ -> false) - let getItem itemId = battleItems |> Array.find (fun w -> w.Id = itemId) + let getItem itemId = battleItems |> List.find (fun item -> item.Id = itemId) + + let getHackItems inventory = + inventory + |> List.filter (fun item -> match item.Type with Hack _ -> true | _ -> false) + |> List.sortBy (fun item -> item.Id) + let getShieldItems inventory = + inventory + |> List.filter (fun item -> match item.Type with Shield _ -> true | _ -> false) + |> List.sortBy (fun item -> item.Id) + let getHacks : HackItem list = + battleItems + |> List.choose (fun item -> + match item.Type with + | Hack(power, hackClass, cooldown) -> Some (item , power, hackClass, cooldown) | _ -> None) + |> List.sortBy (fun (item,_,_,_) -> item.Id) + let getShields : ShieldItem list = + battleItems + |> List.choose (fun item -> + match item.Type with + | Shield(hackClass, cooldown) -> Some (item,hackClass,cooldown) | _ -> None) + |> List.sortBy (fun (item,_,_) -> item.Id) + let getHackById id = getHacks |> List.find (fun (item,_,_,_) -> item.Id = id) + let getShieldById id = getShields |> List.find (fun (item,_,_) -> item.Id = id) module WeaponClass = // TODO: Find a different place to put this let SameTargetAttackCooldown = System.TimeSpan.FromHours(1) - let getClassButtonColor = function - | 0 -> ButtonStyle.Danger - | 1 -> ButtonStyle.Primary - | _ -> ButtonStyle.Success + let getClassButtonColor item = + match item.Type with + | Hack (_,0,_) | Shield (0,_) -> ButtonStyle.Danger + | Hack (_,1,_) | Shield (1,_) -> ButtonStyle.Primary + | Hack (_,2,_) | Shield (2,_) -> ButtonStyle.Success + | _ -> ButtonStyle.Primary - let getClassEmbedColor = function - | 0 -> DiscordColor.Red - | 1 -> DiscordColor.Blurple - | _ -> DiscordColor.Green + let getClassEmbedColor item = + match item.Type with + | Hack (_,0,_) | Shield (0,_) -> DiscordColor.Red + | Hack (_,1,_) | Shield (1,_) -> DiscordColor.Blurple + | Hack (_,2,_) | Shield (2,_) -> DiscordColor.Green + | _ -> DiscordColor.Blurple let getGoodAgainst = function - | 0 -> ( ShieldId.Firewall , HackId.Virus ) - | 1 -> ( ShieldId.Encryption , HackId.RemoteAccess ) - | _ -> ( ShieldId.Cypher , HackId.Worm ) + | 0 -> ( ItemId.Firewall , ItemId.Virus ) + | 1 -> ( ItemId.Encryption , ItemId.RemoteAccess ) + | _ -> ( ItemId.Cypher , ItemId.Worm ) module Player = - let getItems itemType (player : PlayerData) = player.Inventory |> Array.filter (fun i -> i.Type = itemType) - let getHacks (player : PlayerData) = getItems ItemType.Hack player - let getShields (player : PlayerData) = getItems ItemType.Shield player + let getHackItems player = + player.Inventory + |> List.filter (fun item -> match item.Type with Hack _ -> true | _ -> false) + |> List.sortBy (fun item -> item.Id) + let getShieldItems player = + player.Inventory + |> List.filter (fun item -> match item.Type with Shield _ -> true | _ -> false) + |> List.sortBy (fun item -> item.Id) + let getHacks player : HackItem list = + player.Inventory + |> List.choose (fun item -> + match item.Type with + | Hack(power, hackClass, cooldown) -> Some (item , power, hackClass, cooldown) | _ -> None) + |> List.sortBy (fun (item,_,_,_) -> item.Id) + let getShields player : ShieldItem list = + player.Inventory + |> List.choose (fun item -> + match item.Type with + | Shield(hackClass, cooldown) -> Some (item , hackClass, cooldown) | _ -> None) + |> List.sortBy (fun (item,_,_) -> item.Id) let getHackEvents player = player.Events |> Array.filter (fun act -> match act.Type with PlayerEventType.Hacking h -> h.IsInstigator | _ -> false) @@ -55,11 +100,17 @@ module Player = let modifyBank (player : PlayerData) amount = { player with Bank = max (player.Bank + amount) 0 } + let getStat statId player = + player.Stats + |> List.tryFind (fun stat -> statId = stat.Id) + |> Option.map (fun stat -> stat.Amount) + |> Option.defaultValue 0 + module Arsenal = - let battleItemFormat (items : Item array) = + let battleItemFormat (items : Item list) = match items with - | [||] -> "None" - | _ -> items |> Array.toList |> List.map (fun i -> i.Name) |> String.concat ", " + | [] -> "None" + | _ -> items |> List.map (fun item -> item.Name) |> String.concat ", " let actionFormat (actions : PlayerEvent array) = match actions with @@ -82,8 +133,8 @@ module Arsenal = let statusFormat p = let hacks = Player.getHackEvents p - $"**Hacks:** {Player.getHacks p |> battleItemFormat}\n - **Shields:** {Player.getShields p |> battleItemFormat}\n + $"**Hacks:** {Player.getHackItems p |> battleItemFormat}\n + **Shields:** {Player.getShieldItems p |> battleItemFormat}\n **Hack Attacks:**\n{ hacks |> Array.take (min hacks.Length 10) |> actionFormat}\n **Active Shields:**\n{Player.getShieldEvents p |> actionFormat}" diff --git a/Bot/GameTypes.fs b/Bot/GameTypes.fs index 0151b3d..4f15f61 100644 --- a/Bot/GameTypes.fs +++ b/Bot/GameTypes.fs @@ -1,111 +1,111 @@ -namespace Degenz +[] +module Degenz.Types open System -[] -module Types = +[] +type mins - [] - type mins +[] +type GBT - [] - type GBT +type ItemId = + | Virus = 0 + | RemoteAccess = 1 + | Worm = 2 + | Firewall = 6 + | Encryption = 7 + | Cypher = 8 - type HackId = - | Virus = 0 - | RemoteAccess = 1 - | Worm = 2 +type StatId = + | Strength = 0 + | Focus = 1 + | Luck = 2 + | Charisma = 3 - type ShieldId = - | Firewall = 6 - | Encryption = 7 - | Cypher = 8 +type Stat = { + Id : StatId + BaseDecayRate : single + BaseMinMax : Range +} - type ItemType = - | Hack = 0 - | Shield = 1 - | Food = 1 +type ActiveStat = { + Id : StatId + Amount : int +} - type ItemAttributes = { - Sell : bool - Buy : bool - Consume : bool - Drop : bool - } - with static member empty = { Sell = false ; Buy = false ; Consume = false ; Drop = false } +module PlayerStats = + let Strength = { Id = StatId.Strength ; BaseDecayRate = 5.0f ; BaseMinMax = Range(0, 100) } + let Focus = { Id = StatId.Focus ; BaseDecayRate = 5.0f ; BaseMinMax = Range(0, 100) } + let Luck = { Id = StatId.Luck ; BaseDecayRate = 5.0f ; BaseMinMax = Range(0, 100) } + let Charisma = { Id = StatId.Charisma ; BaseDecayRate = 5.0f ; BaseMinMax = Range(0, 100) } - type Item = { - Id : int - Name : string - Price : int - Type : ItemType - Power : int - Class : int - Cooldown : int - Attributes : ItemAttributes - } - with static member empty = - { Id = -1 - Name = "None" - Price = 0 - Type = ItemType.Hack - Power = 0 - Class = -1 - Cooldown = 0 - Attributes = ItemAttributes.empty } + let stats = [| Strength ; Focus ; Luck ; Charisma |] + let statConsumableMap = + [ ( StatId.Strength , 12 ) + ( StatId.Focus , 13 ) + ( StatId.Luck , 14 ) + ( StatId.Charisma , 15 ) ] - type HackResult = - | Strong - | Weak +type HackResult = + | Strong + | Weak - [] - type DiscordPlayer = { Id: uint64; Name: string } - with static member empty = { Id = 0uL ; Name = "None" } +[] +type DiscordPlayer = { Id: uint64; Name: string } + with static member empty = { Id = 0uL ; Name = "None" } - type HackEvent = { - IsInstigator : bool - Adversary : DiscordPlayer - Success : bool - HackId : int - } +type HackEvent = { + IsInstigator : bool + Adversary : DiscordPlayer + Success : bool + HackId : int +} - type PlayerEventType = - | Hacking of HackEvent - | Shielding of shieldId : int - | Stealing of instigator : bool * adversary : DiscordPlayer - | Imprison +type PlayerEventType = + | Hacking of HackEvent + | Shielding of shieldId : int + | Stealing of instigator : bool * adversary : DiscordPlayer + | Imprison - type PlayerEvent = - { Type : PlayerEventType - Cooldown : int - Timestamp : DateTime } +type PlayerEvent = + { Type : PlayerEventType + Cooldown : int + Timestamp : DateTime } - type PlayerTraits = { - Strength : int - Focus : int - Luck : int - Charisma : int - } - with static member empty = { Strength = 0 ; Focus = 0 ; Luck = 0 ; Charisma = 0 } - - [] - type PlayerData = { - DiscordId : uint64 - Name : string - Inventory : Item array - Events : PlayerEvent array - Traits : PlayerTraits - Bank : int - } +type HackItem = Item * int * int * int +and ShieldItem = Item * int * int +and FoodItem = Item * (Item -> PlayerData -> PlayerData) +and AccessoryItem = Item * (Item -> PlayerData -> PlayerData) +and ItemType = + | Hack of power : int * hackClass : int * cooldown : int + | Shield of shieldClass : int * cooldown : int + | Food of effect : (Item -> PlayerData -> PlayerData) + | Accessory of effect : (Item -> PlayerData -> PlayerData) +and Item = { + Id : int + Name : string + Price : int + Type : ItemType +} +and Inventory = Item list +and PlayerData = { + DiscordId : uint64 + Name : string + Inventory : Inventory + Events : PlayerEvent array + Stats : ActiveStat list + Bank : int +} // Achievements : string array // XP : int - with member this.basicPlayer = { Id = this.DiscordId ; Name = this.Name } - static member empty = - { DiscordId = 0uL - Name = "None" - Inventory = [||] - Events = [||] - Traits = PlayerTraits.empty +with member this.basicPlayer = { Id = this.DiscordId ; Name = this.Name } + static member empty = + { DiscordId = 0uL + Name = "None" + Inventory = [] + Events = [||] + Stats = [] // Achievements = [||] // XP = 0 - Bank = 0 } + Bank = 0 } diff --git a/Bot/Games/HackerBattle.fs b/Bot/Games/HackerBattle.fs index b710e28..f6c3fae 100644 --- a/Bot/Games/HackerBattle.fs +++ b/Bot/Games/HackerBattle.fs @@ -45,21 +45,21 @@ let checkWeaponHasCooldown (weapon : Item) attacker = let checkHasEmptyHacks attacker = match Player.getHacks attacker with - | [||] -> Error $"You currently do not have any Hacks to take 💰$GBT from others. Please go to the <#{GuildEnvironment.channelArmory}> and purchase one." + | [] -> Error $"You currently do not have any Hacks to take 💰$GBT from others. Please go to the <#{GuildEnvironment.channelArmory}> and purchase one." | _ -> Ok attacker let checkPlayerOwnsWeapon (item : Item) player = - match player.Inventory |> Array.exists (fun i -> i.Id = item.Id) with + match player.Inventory |> List.exists (fun i -> i.Id = item.Id) with | true -> Ok player | false -> Error $"You sold your weapon already, you cheeky bastard..." -let checkPlayerHasShieldSlotsAvailable (shield : Item) player = +let checkPlayerHasShieldSlotsAvailable player = let updatedPlayer = player |> Player.removeExpiredActions let defenses = Player.getShieldEvents updatedPlayer match defenses |> Array.length >= 3 with | true -> - let timestamp = defenses |> Array.rev |> Array.head |> fun a -> a.Timestamp // This should be the next expiring timestamp - let cooldown = getTimeText true (TimeSpan.FromMinutes(int shield.Cooldown)) timestamp + let event = defenses |> Array.rev |> Array.head // This should be the next expiring timestamp + let cooldown = getTimeText true (TimeSpan.FromMinutes(int event.Cooldown)) event.Timestamp Error $"You are only allowed three shields at a time. Wait {cooldown} to add another shield" | false -> Ok updatedPlayer @@ -68,35 +68,36 @@ let checkTargetHasFunds target player = | true -> Error $"Looks like the poor bastard has no $GBT... pick a different victim." | false -> Ok player -let calculateDamage (hack : Item) (shield : Item) = - if hack.Class = shield.Class +let calculateDamage ((_,_,hackClass,_) : HackItem) ((_,shieldClass,_) : ShieldItem) = + if hackClass = shieldClass then Weak else Strong -let runHackerBattle defender hack = +let runHackerBattle defender (hack : HackItem) = defender |> Player.removeExpiredActions |> fun p -> p.Events |> Array.choose (fun event -> match event.Type with - | Shielding id -> Armory.battleItems |> Array.find (fun w -> w.Id = id) |> Some + | Shielding id -> Armory.getShields |> List.find (fun (item,_,_) -> item.Id = id) |> Some | _ -> None) |> Array.map (calculateDamage hack) |> Array.contains Weak -let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerData) (hack : Item) prize = +let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerData) (hack : HackItem) prize = + let (item, power, hackClass, cooldown) = hack let updatePlayer amount attack p = { p with Events = Array.append [| attack |] p.Events ; Bank = max (p.Bank + amount) 0 } let event isDefenderEvent = let hackEvent = { - HackId = hack.Id + HackId = item.Id Adversary = if isDefenderEvent then attacker.basicPlayer else defender.basicPlayer IsInstigator = not isDefenderEvent Success = successfulHack } { Type = Hacking hackEvent Timestamp = DateTime.UtcNow - Cooldown = if isDefenderEvent then int WeaponClass.SameTargetAttackCooldown.TotalMinutes * 1 else hack.Cooldown } + Cooldown = if isDefenderEvent then int WeaponClass.SameTargetAttackCooldown.TotalMinutes * 1 else cooldown } [ DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer prize (event false) attacker DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer -prize (event true) defender @@ -105,12 +106,13 @@ let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerDa |> Async.Parallel |> Async.Ignore -let successfulHack (ctx : IDiscordContext) attacker defender hack = +let successfulHack (ctx : IDiscordContext) attacker defender (hack : HackItem) = async { - let prizeAmount = if hack.Power < int defender.Bank then hack.Power else int defender.Bank + let (item,power,hackClass,cooldown) = hack + let prizeAmount = if power < int defender.Bank then power else int defender.Bank do! updateCombatants true attacker defender hack (prizeAmount * 1) - let embed = Embeds.responseSuccessfulHack true defender.DiscordId prizeAmount hack + let embed = Embeds.responseSuccessfulHack true defender.DiscordId prizeAmount item do! ctx.FollowUp embed |> Async.AwaitTask let builder = Embeds.eventSuccessfulHack ctx defender prizeAmount @@ -120,9 +122,10 @@ let successfulHack (ctx : IDiscordContext) attacker defender hack = |> Async.Ignore } -let failedHack (ctx : IDiscordContext) attacker defender hack = +let failedHack (ctx : IDiscordContext) attacker defender (hack : HackItem) = + let (item, power, hackClass, cooldown) = hack async { - let lostAmount = if hack.Power < int attacker.Bank then hack.Power else int attacker.Bank + let lostAmount = if power < int attacker.Bank then power else int attacker.Bank let msg = $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {lostAmount} $GBT!" do! sendFollowUpMessage ctx msg @@ -155,7 +158,7 @@ let handleAttack (ctx : IDiscordContext) = executePlayerAction ctx (fun attacker -> async { let tokens = ctx.GetInteractionId().Split("-") let hackId = int tokens.[1] - let hack = Armory.getItem hackId + let item,_,_,_ as hackItem = Armory.getHackById hackId let resultId , targetId = UInt64.TryParse tokens.[2] let! resultTarget = DbService.tryFindPlayer GuildEnvironment.pgDb targetId @@ -164,21 +167,21 @@ let handleAttack (ctx : IDiscordContext) = do! attacker |> Player.removeExpiredActions |> checkAlreadyHackedTarget defender - >>= checkPlayerOwnsWeapon hack - >>= checkWeaponHasCooldown hack + >>= checkPlayerOwnsWeapon item + >>= checkWeaponHasCooldown item |> function | Ok atkr -> - runHackerBattle defender hack + runHackerBattle defender hackItem |> function - | false -> successfulHack ctx atkr defender hack - | true -> failedHack ctx attacker defender hack + | false -> successfulHack ctx atkr defender hackItem + | true -> failedHack ctx attacker defender hackItem | Error msg -> Messaging.sendFollowUpMessage ctx msg | _ -> do! Messaging.sendFollowUpMessage ctx "Error occurred processing attack" }) let defend (ctx : IDiscordContext) = executePlayerAction ctx (fun player -> async { - if Player.getShields player |> Array.length > 0 then + if Player.getShields player |> List.length > 0 then let p = Player.removeExpiredActions player let embed = Embeds.pickDefense "Defend" p false do! ctx.FollowUp embed |> Async.AwaitTask @@ -191,18 +194,18 @@ let handleDefense (ctx : IDiscordContext) = executePlayerAction ctx (fun player -> async { let tokens = ctx.GetInteractionId().Split("-") let shieldId = int tokens.[1] - let shield = Armory.getItem shieldId + let item, shieldClass, cooldown as shield = Armory.getShields |> List.find (fun (item,_,_) -> item.Id = shieldId) do! player - |> checkPlayerOwnsWeapon shield - >>= checkPlayerHasShieldSlotsAvailable shield - >>= checkWeaponHasCooldown shield + |> checkPlayerOwnsWeapon item + >>= checkPlayerHasShieldSlotsAvailable + >>= checkWeaponHasCooldown item |> handleResultWithResponse ctx (fun p -> async { let embed = Embeds.responseCreatedShield shield do! ctx.FollowUp embed |> Async.AwaitTask let defense = { Type = Shielding shieldId - Cooldown = shield.Cooldown + Cooldown = cooldown Timestamp = DateTime.UtcNow } do! DbService.updatePlayer GuildEnvironment.pgDb p diff --git a/Bot/Games/Store.fs b/Bot/Games/Store.fs index c105a40..26caf93 100644 --- a/Bot/Games/Store.fs +++ b/Bot/Games/Store.fs @@ -15,30 +15,31 @@ let checkHasSufficientFunds (item : Item) player = else Error $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT" let checkAlreadyOwnsItem (item : Item) player = - if player.Inventory |> Array.exists (fun w -> item.Id = w.Id) + if player.Inventory |> List.exists (fun w -> item.Id = w.Id) then Error $"You already own {item.Name}!" else Ok player -let checkSoldItemAlready (item : Item) player = - if player.Inventory |> Array.exists (fun w -> item.Id = w.Id) +let checkSoldItemAlready item player = + if player.Inventory |> List.exists (fun i -> item.Id = i.Id) then Ok player - else Error $"{item.Name} not found in your arsenal! Looks like you sold it already." + else Error $"{item.Name} not found in your inventory! Looks like you sold it already." -let checkHasItemsInArsenal itemType player = - if player.Inventory |> Array.filter (fun i -> i.Type = itemType ) |> Array.length > 0 +let checkHasItemsInArsenal itemType items player = + if List.isEmpty items |> not then Ok player - else Error $"You currently have no {itemType}s in your arsenal to sell!" + else Error $"You currently have no {itemType} in your arsenal to sell!" -let buy itemType (ctx : IDiscordContext) = +let buy getItems (ctx : IDiscordContext) = executePlayerAction ctx (fun player -> async { - let itemStore = Embeds.getBuyItemsEmbed player itemType Armory.battleItems + let itemStore = Embeds.getBuyItemsEmbed (getItems player.Inventory) (getItems Armory.battleItems) do! ctx.FollowUp itemStore |> Async.AwaitTask }) -let sell itemType (ctx : IDiscordContext) = +let sell itemType getItems (ctx : IDiscordContext) = executePlayerAction ctx (fun player -> async { - match checkHasItemsInArsenal itemType player with - | Ok _ -> let itemStore = Embeds.getSellEmbed itemType player + let items = getItems player + match checkHasItemsInArsenal itemType items player with + | Ok _ -> let itemStore = Embeds.getSellEmbed items do! ctx.FollowUp(itemStore) |> Async.AwaitTask | Error e -> do! sendFollowUpMessage ctx e }) @@ -46,13 +47,13 @@ let sell itemType (ctx : IDiscordContext) = // TODO: When you buy a shield, prompt the user to activate it let handleBuyItem (ctx : IDiscordContext) itemId = executePlayerAction ctx (fun player -> async { - let item = Armory.battleItems |> Array.find (fun w -> w.Id = itemId) + let item = Armory.getItem itemId do! player |> checkHasSufficientFunds item >>= checkAlreadyOwnsItem item |> handleResultWithResponse ctx (fun player -> async { let newBalance = player.Bank - item.Price - let p = { player with Bank = newBalance ; Inventory = Array.append [| item |] player.Inventory } + let p = { player with Bank = newBalance ; Inventory = item::player.Inventory } do! DbService.updatePlayer GuildEnvironment.pgDb p |> Async.Ignore do! sendFollowUpMessage ctx $"Successfully purchased {item.Name}! You now have {newBalance} 💰$GBT remaining" }) @@ -68,7 +69,7 @@ let handleSell (ctx : IDiscordContext) itemId = let updatedPlayer = { player with Bank = player.Bank + item.Price - Inventory = player.Inventory |> Array.filter (fun i -> i.Id <> itemId) + Inventory = player.Inventory |> List.filter (fun i -> i.Id <> itemId) } do! [ DbService.updatePlayer GuildEnvironment.pgDb updatedPlayer |> Async.Ignore @@ -76,8 +77,7 @@ let handleSell (ctx : IDiscordContext) itemId = sendFollowUpMessage ctx $"Sold {item.Type} {item.Name} for {item.Price}! Current Balance: {updatedPlayer.Bank}" ] |> Async.Parallel |> Async.Ignore - - }) + }) }) let handleStoreEvents (_ : DiscordClient) (event : ComponentInteractionCreateEventArgs) = @@ -108,14 +108,14 @@ type Store() = } [] - member _.BuyHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy ItemType.Hack) + member _.BuyHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy Armory.getHackItems) [] - member this.BuyShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy ItemType.Shield) + member this.BuyShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy Armory.getShieldItems) [] - member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell ItemType.Hack) + member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Hacks" Player.getHackItems) [] - member this.SellShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell ItemType.Shield) + member this.SellShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" Player.getShieldItems) diff --git a/Bot/Games/Thief.fs b/Bot/Games/Thief.fs index fd1a196..b94ed29 100644 --- a/Bot/Games/Thief.fs +++ b/Bot/Games/Thief.fs @@ -128,7 +128,9 @@ let steal target amount (ctx : IDiscordContext) = >>= checkPrizeRequestZero amount |> handleResultWithResponse ctx (fun _ -> async { let cappedPrize , winPercentage , wasCapped = - calculateWinPercentage amount (int victim.Bank) thief.Traits.Strength victim.Traits.Strength +// calculateWinPercentage amount (int victim.Bank) thief.Stats.Strength victim.Stats.Strength + // TODO: Readd stats + calculateWinPercentage amount (int victim.Bank) 0 0 let chance = int (winPercentage * 100.0) let buttons = @@ -138,7 +140,8 @@ let steal target amount (ctx : IDiscordContext) = let cappedMsg = if wasCapped then $"They only have {cappedPrize} $GBT though... " else "" let strengthMsg = - match thief.Traits.Strength - victim.Traits.Strength with + // TODO: Readd stats + match 0 - 0 with | diff when diff < -50 -> "much stronger" | diff when diff < 0 -> "stronger" | diff when diff < 50 -> "weaker" @@ -161,7 +164,8 @@ let handleSteal (ctx : IDiscordContext) = let targetId = uint64 tokens.[2] let targetName = tokens.[3] let amount = int tokens.[4] - let prize , winPercentage , _ = calculateWinPercentage amount (int victim.Bank) thief.Traits.Strength victim.Traits.Strength + // TODO: Readd stats + let prize , winPercentage , _ = calculateWinPercentage amount (int victim.Bank) 0 0 let prize = int prize * 1 let rand = Random(Guid.NewGuid().GetHashCode()) diff --git a/Bot/Games/Trainer.fs b/Bot/Games/Trainer.fs index e8958e9..a0aa6c1 100644 --- a/Bot/Games/Trainer.fs +++ b/Bot/Games/Trainer.fs @@ -9,8 +9,8 @@ open Degenz.Messaging let trainerAchievement = "FINISHED_TRAINER" let Sensei = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" } -let defaultHack = Armory.battleItems |> Array.find (fun i -> i.Id = int HackId.Virus) -let defaultShield = Armory.battleItems |> Array.find (fun i -> i.Id = int ShieldId.Firewall) +let defaultHackItem, hackPower, hackClass, hackCooldown as defaultHack = Armory.getHackById (int ItemId.Virus) +let defaultShieldItem, shieldClass, shieldCooldown as defaultShield = Armory.getShieldById (int ItemId.Firewall) let TrainerEvents = [| { Timestamp = System.DateTime.UtcNow @@ -19,10 +19,10 @@ let TrainerEvents = [| Adversary = Sensei Success = true IsInstigator = true - HackId = defaultHack.Id } } + HackId = defaultHackItem.Id } } { Timestamp = System.DateTime.UtcNow - Cooldown = defaultShield.Cooldown - Type = Shielding defaultShield.Id } + Cooldown = shieldCooldown + Type = Shielding defaultShieldItem.Id } |] let sendInitialEmbed (client : DiscordClient) = @@ -52,7 +52,7 @@ let handleTrainerStep1 (ctx : IDiscordContext) = |> Async.AwaitTask let msg = "Beautopia© is a dangerous place... quick, put up a SHIELD 🛡 before another Degen hacks you, and takes your 💰$GBT.\n\n" + "To enable it, you need to run the `/shield` slash command.\n\n" - + $"Type the `/shield` command now, then select - `{defaultShield.Name}`\n" + + $"Type the `/shield` command now, then select - `{defaultShieldItem.Name}`\n" let builder = DiscordInteractionResponseBuilder() .WithContent(msg) @@ -66,7 +66,7 @@ let defend (ctx : IDiscordContext) = do! Messaging.defer ctx let m = ctx.GetDiscordMember() let name = if System.String.IsNullOrEmpty m.Nickname then m.DisplayName else m.Nickname - let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [| defaultShield |] ; Name = name } true + let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [ defaultShieldItem ] ; Name = name } true do! ctx.FollowUp(embed) |> Async.AwaitTask } |> Async.StartAsTask :> Task @@ -83,17 +83,16 @@ let handleDefense (ctx : IDiscordContext) = let sendMessage' = sendFollowUpMessage ctx let tokens = ctx.GetInteractionId().Split("-") - let shieldId = enum(int tokens.[2]) - let shield = Armory.getItem (int shieldId) + let shieldId = enum(int tokens.[2]) let playerName = tokens.[4] - let embed = Embeds.responseCreatedShield shield + let embed = Embeds.responseCreatedShield defaultShield do! ctx.FollowUp embed |> Async.AwaitTask do! Async.Sleep 4000 - do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **{defaultHack.Name}**" + do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **{defaultHackItem.Name}**" do! Async.Sleep 5000 do! sendMessage' $"❌ HACKING FAILED!\n\n{playerName} defended hack from <@{Sensei.Id}>!" do! Async.Sleep 4000 - do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHack.Name) + do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHackItem.Name) } |> Async.StartAsTask :> Task let handleTrainerStep3 (ctx : IDiscordContext) = @@ -104,7 +103,7 @@ let handleTrainerStep3 (ctx : IDiscordContext) = .WithContent ( "Now let’s **HACK** 💻... I want you to **HACK ME**!\n\n" + "To **hack**, you need to run the `/hack` slash command.\n" - + $"Type the `/hack` command now, then choose me - <@{Sensei.Id}> as your target, and select `{defaultHack.Name}`") + + $"Type the `/hack` command now, then choose me - <@{Sensei.Id}> as your target, and select `{defaultHackItem.Name}`") do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask } |> Async.StartAsTask :> Task @@ -117,7 +116,7 @@ let hack (target : DiscordUser) (ctx : IDiscordContext) = match isRightTarget with | true -> let bot = { PlayerData.empty with DiscordId = Sensei.Id ; Name = Sensei.Name } - let embed = Embeds.pickHack "Trainer-4" { PlayerData.empty with Inventory = [| defaultHack |] } bot true + let embed = Embeds.pickHack "Trainer-4" { PlayerData.empty with Inventory = [ defaultHackItem ] } bot true do! ctx.FollowUp(embed) |> Async.AwaitTask | false -> @@ -133,7 +132,7 @@ let handleHack (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction ctx (fun player -> async { let sendMessage' = sendFollowUpMessage ctx do! Async.Sleep 1000 - let embed = Embeds.responseSuccessfulHack false Sensei.Id defaultHack.Power defaultHack + let embed = Embeds.responseSuccessfulHack false Sensei.Id hackPower defaultHackItem do! ctx.FollowUp(embed) |> Async.AwaitTask do! Async.Sleep 4000 do! sendMessage' @@ -151,7 +150,7 @@ let handleHack (ctx : IDiscordContext) = do! DbService.addAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement |> Async.Ignore - sb.Append($"I'm going to gift you a hack,`{defaultHack.Name}` and a shield, `{defaultShield.Name}`") |> ignore + sb.Append($"I'm going to gift you a hack,`{defaultHackItem.Name}` and a shield, `{defaultShieldItem.Name}`") |> ignore sb.Append(", you'll need em to survive\n\n") |> ignore sb.AppendLine("To finish your training and collect the loot, type the `/arsenal` command **NOW**") |> ignore do! Async.Sleep 1000 @@ -166,12 +165,12 @@ let handleHack (ctx : IDiscordContext) = let handleArsenal (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction ctx (fun player -> async { - let hasStockWeapons = Player.getHacks player |> Array.exists (fun item -> item.Id = defaultHack.Id) + let hasStockWeapons = Player.getHackItems player |> List.exists (fun item -> item.Id = defaultHackItem.Id) let updatedPlayer = if not hasStockWeapons then { Player.removeExpiredActions player with Events = TrainerEvents |> Array.append player.Events - Inventory = [| defaultHack ; defaultShield |] |> Array.append player.Inventory + Inventory = defaultHackItem::defaultShieldItem::player.Inventory } else Player.removeExpiredActions player @@ -188,7 +187,7 @@ let handleArsenal (ctx : IDiscordContext) = let! completed = DbService.checkHasAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement if not completed then do! Async.Sleep 3000 - let rewards = [ $"{defaultHack.Name} Hack" ; $"{defaultShield.Name} Shield" ] + let rewards = [ $"{defaultHackItem.Name} Hack" ; $"{defaultShieldItem.Name} Shield" ] let embed = Embeds.getAchievementEmbed rewards "You completed the Training Dojo and collected loot." trainerAchievement do! ctx.FollowUp(embed) |> Async.AwaitTask do! Async.Sleep 2000 diff --git a/Bot/Items.json b/Bot/Items.json index 238bb0b..5ba6228 100644 --- a/Bot/Items.json +++ b/Bot/Items.json @@ -2,91 +2,76 @@ { "Id": 0, "Name": "Virus", - "Type": 0, "Price": 0, - "Power": 25, - "Cooldown": 1, - "Class": 0, - "Attributes": { - "Sell": false, - "Buy": false, - "Consume": false, - "Drop": false + "Type": { + "Case": "Hack", + "Fields": [ + 25, + 0, + 1 + ] } }, { "Id": 1, "Name": "RemoteAccess", - "Type": 0, "Price": 500, - "Power": 75, - "Cooldown": 3, - "Class": 1, - "Attributes": { - "Sell": true, - "Buy": true, - "Consume": false, - "Drop": true + "Type": { + "Case": "Hack", + "Fields": [ + 75, + 1, + 3 + ] } }, { "Id": 2, "Name": "Worm", - "Type": 0, "Price": 5000, - "Power": 150, - "Cooldown": 5, - "Class": 2, - "Attributes": { - "Sell": true, - "Buy": true, - "Consume": false, - "Drop": true + "Type": { + "Case": "Hack", + "Fields": [ + 150, + 2, + 5 + ] } }, { "Id": 6, "Name": "Firewall", - "Type": 1, "Price": 0, - "Power": 10, - "Class": 0, - "Cooldown": 120, - "Attributes": { - "Sell": false, - "Buy": false, - "Consume": false, - "Drop": false + "Type": { + "Case": "Shield", + "Fields": [ + 0, + 120 + ] } }, { "Id": 7, "Name": "Encryption", - "Type": 1, "Price": 500, - "Power": 50, - "Class": 1, - "Cooldown": 240, - "Attributes": { - "Sell": true, - "Buy": true, - "Consume": false, - "Drop": true + "Type": { + "Case": "Shield", + "Fields": [ + 1, + 240 + ] } }, { "Id": 8, "Name": "Cypher", - "Type": 1, "Price": 5000, - "Power": 80, - "Class": 2, - "Cooldown": 380, - "Attributes": { - "Sell": true, - "Buy": true, - "Consume": false, - "Drop": true + "Type": { + "Case": "Shield", + "Fields": [ + 2, + 380 + ] } } ] diff --git a/Bot/PlayerInteractions.fs b/Bot/PlayerInteractions.fs index bfe188e..eaa0623 100644 --- a/Bot/PlayerInteractions.fs +++ b/Bot/PlayerInteractions.fs @@ -3,7 +3,6 @@ module Degenz.PlayerInteractions open System.Threading.Tasks open DSharpPlus open DSharpPlus.Entities -open DSharpPlus.SlashCommands open Degenz.Messaging open Degenz.DbService @@ -57,52 +56,3 @@ let handleResultWithResponse ctx fn (player : Result) = match player with | Ok p -> fn p | Error e -> async { do! Messaging.sendFollowUpMessage ctx e } - -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 = Armory.battleItems |> Array.find (fun i -> i.Id = randHack) - let shield = Armory.battleItems |> Array.find (fun i -> i.Id = randShield) - - { DiscordId = membr - Name = nickname - Inventory = [| hack ; shield |] - Events = [||] -// XP = 0 -// Achievements = [||] - Traits = PlayerTraits.empty - Bank = 100 } - - let upsertPlayer discordId = - async { - let! player = DbService.tryFindPlayer GuildEnvironment.pgDb discordId - let! newPlayer = - match player with - | Some _ -> async.Return false - | None -> - async { -// do! newPlayer "" discordId |> DbService.insertNewPlayer - return true - } - return newPlayer - } - - [] - type LeaderboardEntry = { - Position : string - Amount : string - Name : string - } - -type PlayerInteractions() = - inherit ApplicationCommandModule () - - [] - member _.AddHackerRole (ctx : InteractionContext) = Commands.upsertPlayer ctx.Member.Id - -// [] -// member this.Leaderboard (ctx : InteractionContext) = Commands.leaderboard ctx - - diff --git a/Bot/XP.fs b/Bot/XP.fs index 0477d3a..b26c175 100644 --- a/Bot/XP.fs +++ b/Bot/XP.fs @@ -6,7 +6,7 @@ open DSharpPlus.Entities type RewardType = | Currency of int - | RandomItem of itemType : ItemType * amount : int +// | RandomItem of itemType : ItemType * amount : int | SpecialItem of id : int [] diff --git a/DbService/DbService.fsproj b/DbService/DbService.fsproj deleted file mode 100644 index e7786d7..0000000 --- a/DbService/DbService.fsproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - net6.0 - true - - - - - - \ No newline at end of file diff --git a/DbService/paket.references b/DbService/paket.references deleted file mode 100644 index 8199177..0000000 --- a/DbService/paket.references +++ /dev/null @@ -1,8 +0,0 @@ -FSharp.Core -DSharpPlus -// DSharpPlus.CommandsNext -// DSharpPlus.Interactivity -DSharpPlus.SlashCommands - -MongoDB.Driver -Npgsql.FSharp diff --git a/Shared/Shared.fs b/Shared/Shared.fs deleted file mode 100644 index 8148165..0000000 --- a/Shared/Shared.fs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Degenz - -open System -open System.Threading.Tasks -open DSharpPlus -open DSharpPlus.Entities -open DSharpPlus.EventArgs -open DSharpPlus.SlashCommands -open Newtonsoft.Json diff --git a/Shared/Shared.fsproj b/Shared/Shared.fsproj deleted file mode 100644 index e855264..0000000 --- a/Shared/Shared.fsproj +++ /dev/null @@ -1,12 +0,0 @@ - - - - net6.0 - true - - - - - - - \ No newline at end of file diff --git a/Shared/paket.references b/Shared/paket.references deleted file mode 100644 index 71731ab..0000000 --- a/Shared/paket.references +++ /dev/null @@ -1,3 +0,0 @@ -FSharp.Core -DSharpPlus -DSharpPlus.SlashCommands