Changes and fixes to attributes
This commit is contained in:
		
							parent
							
								
									881fd12aa9
								
							
						
					
					
						commit
						e51223df88
					
				@ -121,7 +121,7 @@ let getBuyItemsEmbed (player : PlayerData) (itemType : ItemType) (store : Item a
 | 
			
		||||
                    .WithThumbnail(getShieldIcon (enum<ShieldId>(item.Id)))
 | 
			
		||||
                    |> ignore
 | 
			
		||||
            embed
 | 
			
		||||
              .AddField("Cost 💰", $"{item.Price} $GBT", true)
 | 
			
		||||
              .AddField("Price 💰", $"{item.Price} $GBT", true)
 | 
			
		||||
              .WithTitle($"{item.Name}")
 | 
			
		||||
              |> ignore
 | 
			
		||||
            let button =
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								Bot/Game.fs
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								Bot/Game.fs
									
									
									
									
									
								
							@ -68,10 +68,10 @@ module Player =
 | 
			
		||||
    let getShields (player : PlayerData) = getItems ItemType.Shield player
 | 
			
		||||
    let getHackEvents player =
 | 
			
		||||
        player.Events
 | 
			
		||||
        |> Array.filter (fun act -> match act.Type with PlayerEventType.Hacking -> true | _ -> false || act.ItemId < 12)
 | 
			
		||||
        |> Array.filter (fun act -> match act.Type with PlayerEventType.Hacking -> true | _ -> false && act.ItemId < 12)
 | 
			
		||||
    let getShieldEvents player =
 | 
			
		||||
        player.Events
 | 
			
		||||
        |> Array.filter (fun act -> match act.Type with PlayerEventType.Shielding -> true | _ -> false || act.ItemId < 12)
 | 
			
		||||
        |> Array.filter (fun act -> match act.Type with PlayerEventType.Shielding -> true | _ -> false && act.ItemId < 12)
 | 
			
		||||
 | 
			
		||||
    // TODO: This parameter is a result of putting the cooldown on the attack side. Put the cooldown on the defender
 | 
			
		||||
    // side and only check if it's the same target, we need to refactor Actions
 | 
			
		||||
@ -106,28 +106,22 @@ module Arsenal =
 | 
			
		||||
    let actionFormat (actions : PlayerEvent array) =
 | 
			
		||||
        match actions with
 | 
			
		||||
        | [||] -> "None"
 | 
			
		||||
        | _ ->
 | 
			
		||||
            let hacks , defenses =
 | 
			
		||||
                actions
 | 
			
		||||
                |> Array.filter (fun act -> act.ItemId < 12)
 | 
			
		||||
                |> Array.partition (fun act -> match act.Type with PlayerEventType.Hacking -> true | _ -> false)
 | 
			
		||||
            let hacks = hacks |> Array.take (min hacks.Length 10)
 | 
			
		||||
            hacks
 | 
			
		||||
            |> Array.append defenses
 | 
			
		||||
        | _ -> actions
 | 
			
		||||
            |> Array.map (fun act ->
 | 
			
		||||
                    let item = Armory.getItem act.ItemId
 | 
			
		||||
                    match act.Type with
 | 
			
		||||
                    | PlayerEventType.Hacking ->
 | 
			
		||||
                        let cooldown = Messaging.getTimeText false Game.SameTargetAttackCooldown act.Timestamp
 | 
			
		||||
                    $"Hacked {act.Adversary.Name} {cooldown} ago"
 | 
			
		||||
                        $"Hacked {act.Adversary.Name} with {item.Name} {cooldown} ago"
 | 
			
		||||
                    | _ ->
 | 
			
		||||
                        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 =
 | 
			
		||||
        let hacks = Player.getHackEvents p
 | 
			
		||||
        $"**Hacks:** {Player.getHacks p |> battleItemFormat}\n
 | 
			
		||||
    **Shields:** {Player.getShields p |> battleItemFormat}\n
 | 
			
		||||
    **Hack Attacks:**\n{Player.getHackEvents p |> actionFormat}\n
 | 
			
		||||
    **Hack Attacks:**\n{ hacks |> Array.take (min hacks.Length 10) |> actionFormat}\n
 | 
			
		||||
    **Active Shields:**\n{Player.getShieldEvents p |> actionFormat}"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -264,7 +264,7 @@ type HackerGame() =
 | 
			
		||||
 | 
			
		||||
    [<SlashCommand("hack", "Send a hack attack to another player")>]
 | 
			
		||||
    member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) =
 | 
			
		||||
        enforceChannels (DiscordInteractionContext ctx) (Trainer.attack target) (attack target)
 | 
			
		||||
        enforceChannels (DiscordInteractionContext ctx) (Trainer.hack target) (attack target)
 | 
			
		||||
 | 
			
		||||
    [<SlashCommand("shield", "Create a passive shield that will protect you for a certain time")>]
 | 
			
		||||
    member this.ShieldCommand (ctx : InteractionContext) =
 | 
			
		||||
 | 
			
		||||
@ -3,48 +3,84 @@
 | 
			
		||||
    "Id": 0,
 | 
			
		||||
    "Name": "Virus",
 | 
			
		||||
    "Type": 0,
 | 
			
		||||
    "Cost": 50,
 | 
			
		||||
    "Power": 50,
 | 
			
		||||
    "Cooldown": 2
 | 
			
		||||
    "Price": 0,
 | 
			
		||||
    "Power": 10,
 | 
			
		||||
    "Cooldown": 2,
 | 
			
		||||
    "Attributes": {
 | 
			
		||||
      "Sell": false,
 | 
			
		||||
      "Buy": false,
 | 
			
		||||
      "Consume": false,
 | 
			
		||||
      "Drop": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Id": 1,
 | 
			
		||||
    "Name": "RemoteAccess",
 | 
			
		||||
    "Type": 0,
 | 
			
		||||
    "Cost": 50,
 | 
			
		||||
    "Price": 500,
 | 
			
		||||
    "Power": 50,
 | 
			
		||||
    "Cooldown": 2
 | 
			
		||||
    "Cooldown": 2,
 | 
			
		||||
    "Attributes": {
 | 
			
		||||
      "Sell": true,
 | 
			
		||||
      "Buy": true,
 | 
			
		||||
      "Consume": false,
 | 
			
		||||
      "Drop": true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Id": 2,
 | 
			
		||||
    "Name": "Worm",
 | 
			
		||||
    "Type": 0,
 | 
			
		||||
    "Cost": 50,
 | 
			
		||||
    "Power": 50,
 | 
			
		||||
    "Cooldown": 2
 | 
			
		||||
    "Price": 5000,
 | 
			
		||||
    "Power": 80,
 | 
			
		||||
    "Cooldown": 2,
 | 
			
		||||
    "Attributes": {
 | 
			
		||||
      "Sell": true,
 | 
			
		||||
      "Buy": true,
 | 
			
		||||
      "Consume": false,
 | 
			
		||||
      "Drop": true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Id": 6,
 | 
			
		||||
    "Name": "Firewall",
 | 
			
		||||
    "Type": 1,
 | 
			
		||||
    "Cost": 50,
 | 
			
		||||
    "Power": 50,
 | 
			
		||||
    "Cooldown": 600
 | 
			
		||||
    "Price": 0,
 | 
			
		||||
    "Power": 10,
 | 
			
		||||
    "Cooldown": 600,
 | 
			
		||||
    "Attributes": {
 | 
			
		||||
      "Sell": false,
 | 
			
		||||
      "Buy": false,
 | 
			
		||||
      "Consume": false,
 | 
			
		||||
      "Drop": false
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Id": 8,
 | 
			
		||||
    "Name": "Cypher",
 | 
			
		||||
    "Type": 1,
 | 
			
		||||
    "Cost": 50,
 | 
			
		||||
    "Price": 500,
 | 
			
		||||
    "Power": 50,
 | 
			
		||||
    "Cooldown": 600
 | 
			
		||||
    "Cooldown": 600,
 | 
			
		||||
    "Attributes": {
 | 
			
		||||
      "Sell": true,
 | 
			
		||||
      "Buy": true,
 | 
			
		||||
      "Consume": false,
 | 
			
		||||
      "Drop": true
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    "Id": 7,
 | 
			
		||||
    "Name": "Encryption",
 | 
			
		||||
    "Type": 1,
 | 
			
		||||
    "Cost": 50,
 | 
			
		||||
    "Power": 50,
 | 
			
		||||
    "Cooldown": 600
 | 
			
		||||
    "Price": 5000,
 | 
			
		||||
    "Power": 80,
 | 
			
		||||
    "Cooldown": 600,
 | 
			
		||||
    "Attributes": {
 | 
			
		||||
      "Sell": true,
 | 
			
		||||
      "Buy": true,
 | 
			
		||||
      "Consume": false,
 | 
			
		||||
      "Drop": true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
@ -168,8 +168,6 @@ let handleSteal (ctx : IDiscordContext) =
 | 
			
		||||
            let stole = { ItemId = -1 ; Type = PlayerEventType.Steal ; Result = PlayerEventResult.Positive ; Adversary = dp ; Timestamp = DateTime.UtcNow }
 | 
			
		||||
            let actions = player |> Player.removeExpiredActions false |> fun p -> Array.append [| stole |] p.Events
 | 
			
		||||
            do! DbService.updatePlayer { player with Bank = player.Bank + prize ; XP = player.XP + xp ; Events = actions }
 | 
			
		||||
            let newLevel = XP.getLevel (player.XP + xp)
 | 
			
		||||
//            if XP.getLevel player.XP < newLevel then
 | 
			
		||||
            do! Async.Sleep 2000
 | 
			
		||||
            do! ctx.FollowUp (XP.getRewardsEmbed 1 player) |> Async.AwaitTask
 | 
			
		||||
        | false , false ->
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										163
									
								
								Bot/Trainer.fs
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								Bot/Trainer.fs
									
									
									
									
									
								
							@ -1,16 +1,29 @@
 | 
			
		||||
module Degenz.Trainer
 | 
			
		||||
 | 
			
		||||
open System.Text
 | 
			
		||||
open System.Threading.Tasks
 | 
			
		||||
open DSharpPlus
 | 
			
		||||
open DSharpPlus.Entities
 | 
			
		||||
open DSharpPlus.EventArgs
 | 
			
		||||
open Degenz.Types
 | 
			
		||||
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.Encryption)
 | 
			
		||||
let defaultShield = Armory.battleItems |> Array.find (fun i -> i.Id = int ShieldId.Firewall)
 | 
			
		||||
 | 
			
		||||
let TrainerEvents = [|
 | 
			
		||||
  { PlayerEvent.Timestamp = System.DateTime.UtcNow
 | 
			
		||||
    PlayerEvent.Adversary = Sensei
 | 
			
		||||
    PlayerEvent.Type = PlayerEventType.Hacking
 | 
			
		||||
    PlayerEvent.Result = PlayerEventResult.Positive
 | 
			
		||||
    PlayerEvent.ItemId = defaultHack.Id }
 | 
			
		||||
  { PlayerEvent.Timestamp = System.DateTime.UtcNow
 | 
			
		||||
    PlayerEvent.Adversary = DiscordPlayer.empty
 | 
			
		||||
    PlayerEvent.Type = PlayerEventType.Shielding
 | 
			
		||||
    PlayerEvent.Result = PlayerEventResult.Positive
 | 
			
		||||
    PlayerEvent.ItemId = defaultShield.Id }
 | 
			
		||||
|]
 | 
			
		||||
 | 
			
		||||
let sendInitialEmbed (client : DiscordClient)  =
 | 
			
		||||
    async {
 | 
			
		||||
@ -31,41 +44,30 @@ let sendInitialEmbed (client : DiscordClient)  =
 | 
			
		||||
 | 
			
		||||
let handleTrainerStep1 (ctx : IDiscordContext) =
 | 
			
		||||
    Game.executePlayerAction ctx (fun player -> async {
 | 
			
		||||
        let shieldMessage , weaponName =
 | 
			
		||||
            if Player.getShields player |> Array.isEmpty
 | 
			
		||||
                then $"You do not have any Shields in your arsenal, take the `{defaultShield.Name}` shield, you can use it for now.\n\n" , defaultShield.Name
 | 
			
		||||
                else
 | 
			
		||||
                    let name = Player.getShields player |> Array.tryHead |> Option.defaultValue defaultShield |> fun w -> w.Name
 | 
			
		||||
                    $"Looks like you have `{name}` in your arsenal… 👀\n\n" , name
 | 
			
		||||
 | 
			
		||||
        let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
 | 
			
		||||
        do! ctx.GetDiscordMember().GrantRoleAsync(role)
 | 
			
		||||
            |> Async.AwaitTask
 | 
			
		||||
 | 
			
		||||
        do! sendFollowUpMessage ctx
 | 
			
		||||
                ("Beautopia© is a dangerous place... quick, put up a SHIELD 🛡 before another Degen hacks you, and steals your 💰$GBT.\n\n"
 | 
			
		||||
               + shieldMessage
 | 
			
		||||
               + "To enable it, you need to run the `/shield` slash command.\n\n"
 | 
			
		||||
               + $"Type the `/shield` command now, then select - `{weaponName}`\n")
 | 
			
		||||
               + $"Type the `/shield` command now, then select - `{defaultShield.Name}`\n")
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
let defend (ctx : IDiscordContext) =
 | 
			
		||||
    Game.executePlayerAction ctx (fun player -> async {
 | 
			
		||||
        let playerWithShields =
 | 
			
		||||
            match Player.getShields player with
 | 
			
		||||
            | [||] -> { player with Inventory = [| defaultShield |] }
 | 
			
		||||
            | _ -> player
 | 
			
		||||
 | 
			
		||||
        let embed = Embeds.pickDefense "Trainer-2" playerWithShields true
 | 
			
		||||
 | 
			
		||||
    async {
 | 
			
		||||
        let builder = DiscordInteractionResponseBuilder()
 | 
			
		||||
        builder.IsEphemeral <- true
 | 
			
		||||
        builder.Content <- "Content"
 | 
			
		||||
        do! ctx.Respond InteractionResponseType.DeferredChannelMessageWithSource builder |> Async.AwaitTask
 | 
			
		||||
        let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [| defaultShield |] } true
 | 
			
		||||
        do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
			
		||||
    })
 | 
			
		||||
    } |> Async.StartAsTask :> Task
 | 
			
		||||
 | 
			
		||||
let handleDefenseMsg shieldId hackId = {
 | 
			
		||||
let handleDefenseMsg hackId = {
 | 
			
		||||
    ButtonId = "Trainer-3"
 | 
			
		||||
    ButtonText = "Got it"
 | 
			
		||||
    Message = "🎉 Congratulations you successfully defended my hack!\n\n"
 | 
			
		||||
            + $"The `{shieldId}` shield is strong against the `{hackId}` hack, so make sure to have multiple shields up to protect from multiple attacks..."
 | 
			
		||||
    Message = $"🎉 Congratulations you successfully defended my {hackId} hack!\n\n"
 | 
			
		||||
             + "Shields only protect you for a LIMITED TIME, so remember to keep them mounted at all times, or risk getting hacked!"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -78,41 +80,32 @@ let handleDefense (ctx : IDiscordContext) =
 | 
			
		||||
        let embed = Embeds.responseCreatedShield shield
 | 
			
		||||
        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 **VIRUS**"
 | 
			
		||||
        do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **{defaultHack.Name}**"
 | 
			
		||||
        do! Async.Sleep 5000
 | 
			
		||||
        do! sendMessage' $"❌ HACKING FAILED!\n\n{player.Name} defended hack from <@{GuildEnvironment.botIdHackerBattle}>!"
 | 
			
		||||
        do! sendMessage' $"❌ HACKING FAILED!\n\n{player.Name} defended hack from <@{Sensei.Id}>!"
 | 
			
		||||
        do! Async.Sleep 4000
 | 
			
		||||
        do! sendFollowUpMessageWithButton ctx (handleDefenseMsg shieldId "VIRUS")
 | 
			
		||||
 | 
			
		||||
        do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHack.Name)
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
let handleTrainerStep3 (ctx : IDiscordContext) =
 | 
			
		||||
    Game.executePlayerAction ctx (fun player -> async {
 | 
			
		||||
        let hackMessage , weaponName =
 | 
			
		||||
            if Player.getHacks player |> Array.isEmpty
 | 
			
		||||
                then $"You do not have any Hacks in your arsenal, take this `{defaultHack.Name}`, you can use it for now.\n\n" , defaultHack.Name
 | 
			
		||||
                else
 | 
			
		||||
                    let name = Player.getHacks player |> Array.tryHead |> Option.defaultValue defaultHack |> fun w -> w.Name
 | 
			
		||||
                    $"Looks like you have `{name}` in your arsenal...\n\n" , name
 | 
			
		||||
 | 
			
		||||
    async {
 | 
			
		||||
        let builder = DiscordInteractionResponseBuilder()
 | 
			
		||||
        builder.IsEphemeral <- true
 | 
			
		||||
        builder.Content <- "Content"
 | 
			
		||||
        do! ctx.Respond InteractionResponseType.DeferredChannelMessageWithSource builder |> Async.AwaitTask
 | 
			
		||||
        do! sendFollowUpMessage ctx
 | 
			
		||||
              ("Now let’s **HACK!** 💻\n\n"
 | 
			
		||||
             + "I want you to **HACK ME**...\n\n"
 | 
			
		||||
             + hackMessage
 | 
			
		||||
             + "To deploy it, you need to run the `/hack` slash command.\n"
 | 
			
		||||
             + $"Type the `/hack` command now, then choose me - <@{GuildEnvironment.botIdHackerBattle}> as your target, and select `{weaponName}`")
 | 
			
		||||
    })
 | 
			
		||||
               ( "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}`")
 | 
			
		||||
    } |> Async.StartAsTask :> Task
 | 
			
		||||
 | 
			
		||||
let attack (target : DiscordUser) (ctx : IDiscordContext) =
 | 
			
		||||
let hack (target : DiscordUser) (ctx : IDiscordContext) =
 | 
			
		||||
    Game.executePlayerAction ctx (fun player -> async {
 | 
			
		||||
        let isRightTarget = target.Id = GuildEnvironment.botIdHackerBattle
 | 
			
		||||
        let isRightTarget = target.Id = Sensei.Id
 | 
			
		||||
        match isRightTarget with
 | 
			
		||||
        | true ->
 | 
			
		||||
            let playerWithAttacks =
 | 
			
		||||
                match Player.getHacks player with
 | 
			
		||||
                | [||] -> { player with Inventory = [| defaultHack |] }
 | 
			
		||||
                | _ -> player
 | 
			
		||||
            let bot = { player with DiscordId = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
 | 
			
		||||
            let embed = Embeds.pickHack "Trainer-4" playerWithAttacks bot true
 | 
			
		||||
            let bot = { PlayerData.empty with DiscordId = Sensei.Id ; Name = Sensei.Name }
 | 
			
		||||
            let embed = Embeds.pickHack "Trainer-4" { player with Inventory = [| defaultHack |] } bot true
 | 
			
		||||
 | 
			
		||||
            do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
			
		||||
        | false ->
 | 
			
		||||
@ -124,12 +117,11 @@ let attack (target : DiscordUser) (ctx : IDiscordContext) =
 | 
			
		||||
            do! ctx.FollowUp(builder) |> Async.AwaitTask
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
let handleAttack (ctx : IDiscordContext) =
 | 
			
		||||
let handleHack (ctx : IDiscordContext) =
 | 
			
		||||
    Game.executePlayerAction ctx (fun player -> async {
 | 
			
		||||
        let sendMessage' = sendFollowUpMessage ctx
 | 
			
		||||
        do! Async.Sleep 1000
 | 
			
		||||
        let hack = Player.getHacks player |> Array.tryHead |> Option.defaultValue defaultHack
 | 
			
		||||
        let embed = Embeds.responseSuccessfulHack false GuildEnvironment.botIdHackerBattle hack
 | 
			
		||||
        let embed = Embeds.responseSuccessfulHack false Sensei.Id defaultHack
 | 
			
		||||
        do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
			
		||||
        do! Async.Sleep 5000
 | 
			
		||||
        do! sendMessage'
 | 
			
		||||
@ -146,53 +138,14 @@ let handleAttack (ctx : IDiscordContext) =
 | 
			
		||||
        if isFirstTrainer then
 | 
			
		||||
            do! DbService.addAchievement player.DiscordId trainerAchievement
 | 
			
		||||
 | 
			
		||||
            let hasHacks   = Player.getHacks player |> Array.isEmpty |> not
 | 
			
		||||
            let hasShields = Player.getShields player |> Array.isEmpty |> not
 | 
			
		||||
 | 
			
		||||
            let rand = System.Random(System.Guid.NewGuid().GetHashCode())
 | 
			
		||||
            let freeHack = Armory.hacks.[rand.Next(0, 3)]
 | 
			
		||||
            let freeShield = Armory.shields.[rand.Next(0, 3)]
 | 
			
		||||
            let hackMoney   = if hasHacks   then defaultHack.Price else 0<GBT>
 | 
			
		||||
            let shieldMoney = if hasShields then defaultShield.Price else 0<GBT>
 | 
			
		||||
 | 
			
		||||
            let giftMsg =
 | 
			
		||||
                match hasHacks , hasShields with
 | 
			
		||||
                | true  , true  -> $"I'm going to give you these {hackMoney + shieldMoney} 💰$GBT"
 | 
			
		||||
                | false , true  -> $"I'm going to gift you a hack, `{freeHack.Name}` and {defaultHack.Price} 💰$GBT"
 | 
			
		||||
                | true  , false -> $"I'm going to gift you a shield, `{freeShield.Name}` and {defaultHack.Price} 💰$GBT"
 | 
			
		||||
                | false , false -> $"I'm going to gift you a hack,`{freeHack.Name}` and a shield, `{freeShield.Name}`"
 | 
			
		||||
 | 
			
		||||
            sb.Append(giftMsg) |> ignore
 | 
			
		||||
            sb.Append($"I'm going to gift you a hack,`{defaultHack.Name}` and a shield, `{defaultShield.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
 | 
			
		||||
            let updatedPlayer = {
 | 
			
		||||
                player with
 | 
			
		||||
                    Bank = player.Bank + 100<GBT>
 | 
			
		||||
                    Events = [
 | 
			
		||||
                        { PlayerEvent.Timestamp = System.DateTime.UtcNow
 | 
			
		||||
                          PlayerEvent.Adversary = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
 | 
			
		||||
                          PlayerEvent.Type = PlayerEventType.Shielding
 | 
			
		||||
                          PlayerEvent.Result = PlayerEventResult.Positive
 | 
			
		||||
                          PlayerEvent.ItemId = defaultHack.Id }
 | 
			
		||||
                        if not hasShields && Array.exists (fun act -> act.ItemId = freeShield.Id) player.Events |> not then {
 | 
			
		||||
                          PlayerEvent.Timestamp = System.DateTime.UtcNow
 | 
			
		||||
                          PlayerEvent.Adversary = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
 | 
			
		||||
                          PlayerEvent.Type = PlayerEventType.Shielding
 | 
			
		||||
                          PlayerEvent.Result = PlayerEventResult.Positive
 | 
			
		||||
                          PlayerEvent.ItemId = defaultHack.Id }
 | 
			
		||||
                    ] |> Seq.toArray
 | 
			
		||||
                      |> Array.append player.Events
 | 
			
		||||
                    Inventory = [
 | 
			
		||||
                        if not hasHacks   then freeHack
 | 
			
		||||
                        if not hasShields then freeShield
 | 
			
		||||
                    ] |> Seq.toArray
 | 
			
		||||
                      |> Array.append player.Inventory
 | 
			
		||||
            }
 | 
			
		||||
            do! DbService.updatePlayer updatedPlayer
 | 
			
		||||
 | 
			
		||||
            do! sendFollowUpMessage ctx (sb.ToString())
 | 
			
		||||
        else
 | 
			
		||||
            do! sendFollowUpMessage ctx ($"Your training is now complete. If you want to buy more **HACKS & SHIELDS**, go to the <#{GuildEnvironment.channelArmory}> **NOW** and type the `/buy-hack` and `/buy-shield` commands! 😱")
 | 
			
		||||
            do! sendFollowUpMessage ctx ($"Your training is now complete. If you want to buy more **HACKS & SHIELDS**, go to the <#{GuildEnvironment.channelArmory}> and type the `/buy-hack` and `/buy-shield` commands!")
 | 
			
		||||
            let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
 | 
			
		||||
            do! ctx.GetDiscordMember().RevokeRoleAsync(role)
 | 
			
		||||
                |> Async.AwaitTask
 | 
			
		||||
@ -200,9 +153,25 @@ let handleAttack (ctx : IDiscordContext) =
 | 
			
		||||
 | 
			
		||||
let handleArsenal (ctx : IDiscordContext) =
 | 
			
		||||
    Game.executePlayerAction ctx (fun player -> async {
 | 
			
		||||
        let hasStockWeapons = Player.getHacks player |> Array.exists (fun item -> item.Id = defaultHack.Id)
 | 
			
		||||
        let updatedPlayer = Player.removeExpiredActions false player
 | 
			
		||||
        let embed = Embeds.getArsenalEmbed updatedPlayer
 | 
			
		||||
        let newPlayer =
 | 
			
		||||
            if not hasStockWeapons then {
 | 
			
		||||
                updatedPlayer with
 | 
			
		||||
                    Events = if not (player.Events |> Array.exists (fun act -> act.Adversary = Sensei))
 | 
			
		||||
                                then TrainerEvents
 | 
			
		||||
                                else [||]
 | 
			
		||||
                            |> Array.append player.Events
 | 
			
		||||
                    Inventory = if not hasStockWeapons then [| defaultHack ; defaultShield |] else Array.empty
 | 
			
		||||
                                |> Array.append player.Inventory
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                updatedPlayer
 | 
			
		||||
        if not hasStockWeapons then
 | 
			
		||||
            do! DbService.updatePlayer newPlayer
 | 
			
		||||
        let embed = Embeds.getArsenalEmbed newPlayer
 | 
			
		||||
        do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
			
		||||
        if not (player.Achievements |> Array.contains trainerAchievement) then
 | 
			
		||||
            do! Async.Sleep 3000
 | 
			
		||||
            let embed = Embeds.getAchievementEmbed "You completed the Training Dojo and collected loot." trainerAchievement
 | 
			
		||||
            do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
			
		||||
@ -220,7 +189,7 @@ let handleButtonEvent (ctx : IDiscordContext) =
 | 
			
		||||
        | 1 -> do! handleTrainerStep1 ctx |> Async.AwaitTask
 | 
			
		||||
        | 2 -> do! handleDefense ctx |> Async.AwaitTask
 | 
			
		||||
        | 3 -> do! handleTrainerStep3 ctx |> Async.AwaitTask
 | 
			
		||||
        | 4 -> do! handleAttack ctx |> Async.AwaitTask
 | 
			
		||||
        | 4 -> do! handleHack ctx |> Async.AwaitTask
 | 
			
		||||
        | _ -> do! sendFollowUpMessage ctx "No action found"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -69,6 +69,6 @@ let updatePlayer (player : PlayerData) =
 | 
			
		||||
let addAchievement (id : uint64) (achievement : string) =
 | 
			
		||||
    async {
 | 
			
		||||
        let filter = Builders<BsonDocument>.Filter.Eq("Player.DiscordId", id)
 | 
			
		||||
        let update = Builders<BsonDocument>.Update.Push("Achievements", achievement)
 | 
			
		||||
        let update = Builders<BsonDocument>.Update.Push("Player.Achievements", achievement)
 | 
			
		||||
        return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
 | 
			
		||||
    }
 | 
			
		||||
@ -49,9 +49,17 @@ module Types =
 | 
			
		||||
    type ItemType =
 | 
			
		||||
        | Hack = 0
 | 
			
		||||
        | Shield = 1
 | 
			
		||||
        | Consumable = 1
 | 
			
		||||
        | Food = 1
 | 
			
		||||
 | 
			
		||||
    type ItemAttributes = {
 | 
			
		||||
        Sell : bool
 | 
			
		||||
        Buy : bool
 | 
			
		||||
        Consume : bool
 | 
			
		||||
        Drop : bool
 | 
			
		||||
    }
 | 
			
		||||
    with static member empty = { Sell = false ; Buy = false ; Consume = false ; Drop = false }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    [<CLIMutable>]
 | 
			
		||||
    type Item = {
 | 
			
		||||
        Id : int
 | 
			
		||||
        Name : string
 | 
			
		||||
@ -59,6 +67,7 @@ module Types =
 | 
			
		||||
        Type : ItemType
 | 
			
		||||
        Power : int
 | 
			
		||||
        Cooldown : int<mins>
 | 
			
		||||
        Attributes : ItemAttributes
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    type HackResult =
 | 
			
		||||
@ -109,6 +118,15 @@ module Types =
 | 
			
		||||
        Bank : int<GBT>
 | 
			
		||||
    }
 | 
			
		||||
    with member this.basicPlayer = { Id = this.DiscordId ; Name = this.Name }
 | 
			
		||||
         static member empty =
 | 
			
		||||
             { DiscordId = 0uL
 | 
			
		||||
               Name = "None"
 | 
			
		||||
               Inventory = [||]
 | 
			
		||||
               Events = [||]
 | 
			
		||||
               Traits = PlayerTraits.empty
 | 
			
		||||
               Achievements = [||]
 | 
			
		||||
               XP = 0
 | 
			
		||||
               Bank = 0<GBT> }
 | 
			
		||||
 | 
			
		||||
module Armory =
 | 
			
		||||
    let battleItems =
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user