Gift GBT when completing training, don't let new players be hacked
This commit is contained in:
		
							parent
							
								
									e0fea6dd64
								
							
						
					
					
						commit
						ed512bd394
					
				@ -89,10 +89,19 @@ type ItemType =
 | 
				
			|||||||
    | Food
 | 
					    | Food
 | 
				
			||||||
    | Accessory
 | 
					    | Accessory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ItemAttributes = {
 | 
				
			||||||
 | 
					    CanBuy : bool
 | 
				
			||||||
 | 
					    CanSell : bool
 | 
				
			||||||
 | 
					    CanConsume : bool
 | 
				
			||||||
 | 
					    CanTrade : bool
 | 
				
			||||||
 | 
					    CanDrop : bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Item = {
 | 
					type Item = {
 | 
				
			||||||
    Id : int
 | 
					    Id : int
 | 
				
			||||||
    Name : string
 | 
					    Name : string
 | 
				
			||||||
    Price : int<GBT>
 | 
					    Price : int<GBT>
 | 
				
			||||||
 | 
					    Attributes : ItemAttributes
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type HackItem = {
 | 
					type HackItem = {
 | 
				
			||||||
 | 
				
			|||||||
@ -41,12 +41,12 @@ let checkWeaponHasCooldown (weapon : Item) attacker =
 | 
				
			|||||||
    |> function
 | 
					    |> function
 | 
				
			||||||
       | Some event ->
 | 
					       | Some event ->
 | 
				
			||||||
          let cooldown = getTimeText true (TimeSpan.FromMinutes(int event.Cooldown)) event.Timestamp
 | 
					          let cooldown = getTimeText true (TimeSpan.FromMinutes(int event.Cooldown)) event.Timestamp
 | 
				
			||||||
          Error $"{weapon.Name} is still active, it will expire in {cooldown}."
 | 
					          Error $"{weapon.Name} was recently used, wait another {cooldown} to use it again."
 | 
				
			||||||
       | None -> Ok attacker
 | 
					       | None -> Ok attacker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let checkHasEmptyHacks attacker =
 | 
					let checkHasEmptyHacks (attacker : PlayerData) =
 | 
				
			||||||
    match Inventory.getHacks attacker.Inventory with
 | 
					    match Inventory.getHacks attacker.Inventory 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.channelTraining}> and complete the training."
 | 
				
			||||||
    | _ -> Ok attacker
 | 
					    | _ -> Ok attacker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let checkPlayerOwnsWeapon (item : Item) player =
 | 
					let checkPlayerOwnsWeapon (item : Item) player =
 | 
				
			||||||
@ -69,16 +69,21 @@ let checkTargetHasFunds target player =
 | 
				
			|||||||
    | true -> Error $"Looks like the poor bastard has no $GBT... pick a different victim."
 | 
					    | true -> Error $"Looks like the poor bastard has no $GBT... pick a different victim."
 | 
				
			||||||
    | false -> Ok player
 | 
					    | false -> Ok player
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let checkTargetCompletedTraining target (player : PlayerData) = async {
 | 
				
			||||||
 | 
					    let! targetCompletedTraining = DbService.checkHasAchievement target.DiscordId Trainer.TrainerAchievement
 | 
				
			||||||
 | 
					    if targetCompletedTraining || not target.Inventory.IsEmpty
 | 
				
			||||||
 | 
					        then return Ok player
 | 
				
			||||||
 | 
					        else return Error $"Looks like they haven't completed training with Sensei yet, you can't hack noobs..."
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let runHackerBattle defender (hack : HackItem) =
 | 
					let runHackerBattle defender (hack : HackItem) =
 | 
				
			||||||
    defender
 | 
					    defender
 | 
				
			||||||
    |> Player.removeExpiredActions
 | 
					    |> Player.removeExpiredActions
 | 
				
			||||||
    |> fun p -> p.Events
 | 
					    |> fun p -> p.Events
 | 
				
			||||||
    |> List.choose (fun event ->
 | 
					    |> List.exists (fun event ->
 | 
				
			||||||
        match event.Type with
 | 
					        match event.Type with
 | 
				
			||||||
        | Shielding id -> defender.Inventory |> Inventory.getShields |> List.tryFind (fun item -> item.Item.Id = id)
 | 
					        | Shielding id -> hack.Class = (Inventory.findShieldById id Armory.weapons).Class
 | 
				
			||||||
        | _ -> None)
 | 
					        | _ -> false)
 | 
				
			||||||
    |> List.map (fun shield -> if hack.Class = shield.Class then Weak else Strong)
 | 
					 | 
				
			||||||
    |> List.contains Weak
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerData) (hack : HackItem) prize =
 | 
					let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerData) (hack : HackItem) prize =
 | 
				
			||||||
    let updatePlayer amount attack p =
 | 
					    let updatePlayer amount attack p =
 | 
				
			||||||
@ -134,9 +139,11 @@ let failedHack (ctx : IDiscordContext) attacker defender (hack : HackItem) =
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
let hack (target : DiscordUser) (ctx : IDiscordContext) =
 | 
					let hack (target : DiscordUser) (ctx : IDiscordContext) =
 | 
				
			||||||
    executePlayerActionWithTarget target ctx (fun attacker defender -> async {
 | 
					    executePlayerActionWithTarget target ctx (fun attacker defender -> async {
 | 
				
			||||||
 | 
					      let! result = checkTargetCompletedTraining defender attacker
 | 
				
			||||||
      do! attacker
 | 
					      do! attacker
 | 
				
			||||||
          |> Player.removeExpiredActions
 | 
					          |> Player.removeExpiredActions
 | 
				
			||||||
          |> checkAlreadyHackedTarget defender
 | 
					          |> checkAlreadyHackedTarget defender
 | 
				
			||||||
 | 
					          >>= fun p -> match result with Ok _ -> Ok p | Error e -> Error e
 | 
				
			||||||
          >>= checkTargetHasFunds defender
 | 
					          >>= checkTargetHasFunds defender
 | 
				
			||||||
          >>= checkHasEmptyHacks
 | 
					          >>= checkHasEmptyHacks
 | 
				
			||||||
          >>= checkPlayerIsAttackingThemselves defender
 | 
					          >>= checkPlayerIsAttackingThemselves defender
 | 
				
			||||||
@ -180,7 +187,7 @@ let defend (ctx : IDiscordContext) =
 | 
				
			|||||||
            let embed = Embeds.pickDefense "Defend" p false
 | 
					            let embed = Embeds.pickDefense "Defend" p false
 | 
				
			||||||
            do! ctx.FollowUp embed |> Async.AwaitTask
 | 
					            do! ctx.FollowUp embed |> Async.AwaitTask
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            let msg = $"You currently do not have any Shields to protect yourself from hacks. Please go to the <#{GuildEnvironment.channelArmory}> and purchase one."
 | 
					            let msg = $"You currently do not have any Shields to protect yourself from hacks. Please go to the <#{GuildEnvironment.channelTraining}> and purchase one."
 | 
				
			||||||
            do! Messaging.sendFollowUpMessage ctx msg
 | 
					            do! Messaging.sendFollowUpMessage ctx msg
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -7,10 +7,12 @@ open DSharpPlus.Entities
 | 
				
			|||||||
open Degenz.Types
 | 
					open Degenz.Types
 | 
				
			||||||
open Degenz.Messaging
 | 
					open Degenz.Messaging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let trainerAchievement = "FINISHED_TRAINER"
 | 
					let TrainerAchievement = "FINISHED_TRAINER"
 | 
				
			||||||
let Sensei = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
 | 
					let Sensei = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
 | 
				
			||||||
let defaultHack = Armory.weapons |> Inventory.findHackById (int ItemId.Virus)
 | 
					let defaultHack = Armory.weapons |> Inventory.findHackById (int ItemId.Virus)
 | 
				
			||||||
let defaultShield = Armory.weapons |> Inventory.findShieldById (int ItemId.Firewall)
 | 
					let defaultShield = Armory.weapons |> Inventory.findShieldById (int ItemId.Firewall)
 | 
				
			||||||
 | 
					let CurrencyGift = 250<GBT>
 | 
				
			||||||
 | 
					let BeginnerProtectionHours = 24
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let HackEvent () = {
 | 
					let HackEvent () = {
 | 
				
			||||||
    Timestamp = System.DateTime.UtcNow
 | 
					    Timestamp = System.DateTime.UtcNow
 | 
				
			||||||
@ -22,11 +24,17 @@ let HackEvent () = {
 | 
				
			|||||||
        HackId = defaultHack.Item.Id
 | 
					        HackId = defaultHack.Item.Id
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
let ShieldEvent () = {
 | 
					let ShieldEvents () = [
 | 
				
			||||||
    Timestamp = System.DateTime.UtcNow
 | 
					    { Timestamp = System.DateTime.UtcNow
 | 
				
			||||||
    Cooldown =  defaultShield.Cooldown
 | 
					      Cooldown =  BeginnerProtectionHours * 60<mins>
 | 
				
			||||||
    Type = Shielding defaultShield.Item.Id
 | 
					      Type = Shielding (int ItemId.Firewall) }
 | 
				
			||||||
}
 | 
					    { Timestamp = System.DateTime.UtcNow
 | 
				
			||||||
 | 
					      Cooldown =  BeginnerProtectionHours * 60<mins>
 | 
				
			||||||
 | 
					      Type = Shielding (int ItemId.Encryption) }
 | 
				
			||||||
 | 
					    { Timestamp = System.DateTime.UtcNow
 | 
				
			||||||
 | 
					      Cooldown =  BeginnerProtectionHours * 60<mins>
 | 
				
			||||||
 | 
					      Type = Shielding (int ItemId.Cypher) }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let sendInitialEmbed (client : DiscordClient)  =
 | 
					let sendInitialEmbed (client : DiscordClient)  =
 | 
				
			||||||
    async {
 | 
					    async {
 | 
				
			||||||
@ -149,76 +157,69 @@ let handleHack (ctx : IDiscordContext) =
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let sb = StringBuilder("Here, ")
 | 
					        let sb = StringBuilder("Here, ")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let! completed = DbService.checkHasAchievement player.DiscordId trainerAchievement
 | 
					        let! completed = DbService.checkHasAchievement player.DiscordId TrainerAchievement
 | 
				
			||||||
        if not completed then
 | 
					        if not completed then
 | 
				
			||||||
            do! DbService.addAchievement player.DiscordId trainerAchievement
 | 
					            sb.Append($"I'm going to gift you a hack,`{defaultHack.Item.Name}`, a shield, `{defaultShield.Item.Name}`, and `{CurrencyGift} 💰$GBT`") |> ignore
 | 
				
			||||||
                |> Async.Ignore
 | 
					            sb.Append(", you'll need this to survive\n\n") |> ignore
 | 
				
			||||||
 | 
					            sb.Append($"I'm also going to give you some **TEMPORARY SHIELDS** to protect you for the next **{BeginnerProtectionHours} hours**\n\n") |> ignore
 | 
				
			||||||
            sb.Append($"I'm going to gift you a hack,`{defaultHack.Item.Name}` and a shield, `{defaultShield.Item.Name}`") |> ignore
 | 
					            sb.AppendLine("To finish your training and collect your prizes, type the `/arsenal` command **NOW**") |> 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
 | 
					            do! Async.Sleep 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            do! sendFollowUpMessage ctx (sb.ToString())
 | 
					            do! sendFollowUpMessage ctx (sb.ToString())
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            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!")
 | 
					            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
 | 
					 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let handleArsenal (ctx : IDiscordContext) =
 | 
					let handleArsenal (ctx : IDiscordContext) = PlayerInteractions.executePlayerAction ctx (fun player -> async {
 | 
				
			||||||
    PlayerInteractions.executePlayerAction ctx (fun player -> async {
 | 
					    let! completed = DbService.checkHasAchievement player.DiscordId TrainerAchievement
 | 
				
			||||||
        let hack =
 | 
					    if not completed then
 | 
				
			||||||
            if player.Inventory |> List.exists (fun i -> i.Id = defaultHack.Item.Id)
 | 
					        do! DbService.addAchievement player.DiscordId TrainerAchievement |> Async.Ignore
 | 
				
			||||||
                then []
 | 
					        let addIfDoesntExist (weapon : ItemDetails) (inventory : Inventory) =
 | 
				
			||||||
                else [ Hack defaultHack ]
 | 
					            if inventory |> List.exists (fun i -> i.Id = weapon.Id)
 | 
				
			||||||
        let shield =
 | 
					                then inventory
 | 
				
			||||||
            if player.Inventory |> List.exists (fun i -> i.Id = defaultShield.Item.Id)
 | 
					                else weapon::inventory
 | 
				
			||||||
                then []
 | 
					        let updatedPlayer = {
 | 
				
			||||||
                else [ Shield defaultShield ]
 | 
					            player with
 | 
				
			||||||
        let shieldEvent =
 | 
					                Events =
 | 
				
			||||||
            let hasShield =
 | 
					 | 
				
			||||||
                    player
 | 
					                    player
 | 
				
			||||||
                    |> Player.removeExpiredActions
 | 
					                    |> Player.removeExpiredActions
 | 
				
			||||||
                    |> fun p -> p.Events
 | 
					                    |> fun p -> p.Events
 | 
				
			||||||
                |> List.exists (fun e -> match e.Type with Shielding shieldId -> shieldId = defaultShield.Item.Id | _ -> false)
 | 
					                    |> List.filter (fun e -> match e.Type with Shielding _ -> false | _ -> true)
 | 
				
			||||||
            if hasShield
 | 
					                    |> List.append (ShieldEvents())
 | 
				
			||||||
                then []
 | 
					                    |> List.consTo (HackEvent())
 | 
				
			||||||
                else [ ShieldEvent() ]
 | 
					                Inventory =
 | 
				
			||||||
        let updatedPlayer = {
 | 
					                    player.Inventory
 | 
				
			||||||
            Player.removeExpiredActions player with
 | 
					                    |> addIfDoesntExist (Hack defaultHack)
 | 
				
			||||||
                Events = shieldEvent @ player.Events
 | 
					                    |> addIfDoesntExist (Shield defaultShield)
 | 
				
			||||||
                Inventory = hack @ shield @ player.Inventory
 | 
					                Bank = player.Bank + CurrencyGift
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if not (List.isEmpty hack) || not (List.isEmpty shield) then
 | 
					 | 
				
			||||||
        do! DbService.updatePlayer updatedPlayer |> Async.Ignore
 | 
					        do! DbService.updatePlayer updatedPlayer |> Async.Ignore
 | 
				
			||||||
        if not (List.isEmpty shieldEvent) then
 | 
					 | 
				
			||||||
        try
 | 
					        try
 | 
				
			||||||
            do! DbService.addPlayerEvent player.DiscordId (List.head shieldEvent) |> Async.Ignore
 | 
					            do! ShieldEvents ()
 | 
				
			||||||
 | 
					                |> List.map (DbService.addPlayerEvent player.DiscordId)
 | 
				
			||||||
 | 
					                |> Async.Parallel
 | 
				
			||||||
 | 
					                |> Async.Ignore
 | 
				
			||||||
        with ex ->
 | 
					        with ex ->
 | 
				
			||||||
            printfn "%s" ex.Message
 | 
					            printfn "%s" ex.Message
 | 
				
			||||||
            ()
 | 
					            ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let playerForEmbed = {
 | 
					        let embed = Embeds.getArsenalEmbed updatedPlayer
 | 
				
			||||||
            player with
 | 
					 | 
				
			||||||
                Events = [ HackEvent() ; ShieldEvent() ]
 | 
					 | 
				
			||||||
                Inventory = hack @ shield @ player.Inventory
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        let embed = Embeds.getArsenalEmbed playerForEmbed
 | 
					 | 
				
			||||||
        do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
					        do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let! completed = DbService.checkHasAchievement player.DiscordId trainerAchievement
 | 
					 | 
				
			||||||
        if not completed then
 | 
					 | 
				
			||||||
            do! Async.Sleep 3000
 | 
					 | 
				
			||||||
            let rewards = [ $"{defaultHack.Item.Name} Hack" ; $"{defaultShield.Item.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
 | 
					        do! Async.Sleep 2000
 | 
				
			||||||
 | 
					        let rewards = [ $"{defaultHack.Item.Name} Hack" ; $"{defaultShield.Item.Name} Shield" ; $"{CurrencyGift} 💰$GBT"]
 | 
				
			||||||
 | 
					        let embed = Embeds.getAchievementEmbed rewards "You completed the Training Dojo and collected some prizes." TrainerAchievement
 | 
				
			||||||
 | 
					        do! ctx.FollowUp(embed) |> Async.AwaitTask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
 | 
					        let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
 | 
				
			||||||
        do! ctx.GetDiscordMember().RevokeRoleAsync(role) |> Async.AwaitTask
 | 
					        do! ctx.GetDiscordMember().RevokeRoleAsync(role)
 | 
				
			||||||
 | 
					            |> Async.AwaitTask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        do! Async.Sleep 2000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        do! sendFollowUpMessage ctx $"Now get out of there and go hack other Degenz in the <#{GuildEnvironment.channelBattle}> channel!"
 | 
					        do! sendFollowUpMessage ctx $"Now get out of there and go hack other Degenz in the <#{GuildEnvironment.channelBattle}> channel!"
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        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 handleButtonEvent (ctx : IDiscordContext) =
 | 
					let handleButtonEvent (ctx : IDiscordContext) =
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										131
									
								
								Bot/Items.json
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								Bot/Items.json
									
									
									
									
									
								
							@ -9,7 +9,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 0,
 | 
					          "Id": 0,
 | 
				
			||||||
          "Name": "Virus",
 | 
					          "Name": "Virus",
 | 
				
			||||||
          "Price": 0
 | 
					          "Price": 0,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -20,11 +27,18 @@
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        "Power": 50,
 | 
					        "Power": 50,
 | 
				
			||||||
        "Class": 1,
 | 
					        "Class": 1,
 | 
				
			||||||
        "Cooldown": 3,
 | 
					        "Cooldown": 5,
 | 
				
			||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 1,
 | 
					          "Id": 1,
 | 
				
			||||||
          "Name": "Remote Access",
 | 
					          "Name": "Remote Access",
 | 
				
			||||||
          "Price": 500
 | 
					          "Price": 500,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -35,11 +49,18 @@
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        "Power": 100,
 | 
					        "Power": 100,
 | 
				
			||||||
        "Class": 2,
 | 
					        "Class": 2,
 | 
				
			||||||
        "Cooldown": 5,
 | 
					        "Cooldown": 10,
 | 
				
			||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 2,
 | 
					          "Id": 2,
 | 
				
			||||||
          "Name": "Worm",
 | 
					          "Name": "Worm",
 | 
				
			||||||
          "Price": 5000
 | 
					          "Price": 5000,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -53,7 +74,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 6,
 | 
					          "Id": 6,
 | 
				
			||||||
          "Name": "Firewall",
 | 
					          "Name": "Firewall",
 | 
				
			||||||
          "Price": 0
 | 
					          "Price": 0,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -67,7 +95,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 7,
 | 
					          "Id": 7,
 | 
				
			||||||
          "Name": "Encryption",
 | 
					          "Name": "Encryption",
 | 
				
			||||||
          "Price": 500
 | 
					          "Price": 500,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -81,7 +116,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 8,
 | 
					          "Id": 8,
 | 
				
			||||||
          "Name": "Cypher",
 | 
					          "Name": "Cypher",
 | 
				
			||||||
          "Price": 5000
 | 
					          "Price": 5000,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -95,7 +137,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 12,
 | 
					          "Id": 12,
 | 
				
			||||||
          "Name": "Protein Powder",
 | 
					          "Name": "Protein Powder",
 | 
				
			||||||
          "Price": 50
 | 
					          "Price": 50,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : false,
 | 
				
			||||||
 | 
					            "CanConsume" : true,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -109,7 +158,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 13,
 | 
					          "Id": 13,
 | 
				
			||||||
          "Name": "Toro Loco",
 | 
					          "Name": "Toro Loco",
 | 
				
			||||||
          "Price": 50
 | 
					          "Price": 50,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : false,
 | 
				
			||||||
 | 
					            "CanConsume" : true,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -123,7 +179,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 14,
 | 
					          "Id": 14,
 | 
				
			||||||
          "Name": "Oldports Cigs",
 | 
					          "Name": "Oldports Cigs",
 | 
				
			||||||
          "Price": 50
 | 
					          "Price": 50,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : false,
 | 
				
			||||||
 | 
					            "CanConsume" : true,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -137,7 +200,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 15,
 | 
					          "Id": 15,
 | 
				
			||||||
          "Name": "Moon Pie",
 | 
					          "Name": "Moon Pie",
 | 
				
			||||||
          "Price": 50
 | 
					          "Price": 50,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : false,
 | 
				
			||||||
 | 
					            "CanConsume" : true,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -152,7 +222,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 20,
 | 
					          "Id": 20,
 | 
				
			||||||
          "Name": "Kettlebell",
 | 
					          "Name": "Kettlebell",
 | 
				
			||||||
          "Price": 250
 | 
					          "Price": 250,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -167,7 +244,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 21,
 | 
					          "Id": 21,
 | 
				
			||||||
          "Name": "Headphones",
 | 
					          "Name": "Headphones",
 | 
				
			||||||
          "Price": 250
 | 
					          "Price": 250,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -182,7 +266,14 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 22,
 | 
					          "Id": 22,
 | 
				
			||||||
          "Name": "Rolox Watch",
 | 
					          "Name": "Rolox Watch",
 | 
				
			||||||
          "Price": 250
 | 
					          "Price": 250,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
@ -197,9 +288,17 @@
 | 
				
			|||||||
        "Item": {
 | 
					        "Item": {
 | 
				
			||||||
          "Id": 23,
 | 
					          "Id": 23,
 | 
				
			||||||
          "Name": "Buddha Keychain",
 | 
					          "Name": "Buddha Keychain",
 | 
				
			||||||
          "Price": 250
 | 
					          "Price": 250,
 | 
				
			||||||
 | 
					          "Attributes": {
 | 
				
			||||||
 | 
					            "CanBuy" : true,
 | 
				
			||||||
 | 
					            "CanSell" : true,
 | 
				
			||||||
 | 
					            "CanConsume" : false,
 | 
				
			||||||
 | 
					            "CanTrade" : false,
 | 
				
			||||||
 | 
					            "CanDrop" : false
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,8 +5,8 @@ module ResultHelpers =
 | 
				
			|||||||
    let (>>=) x f = Result.bind f x
 | 
					    let (>>=) x f = Result.bind f x
 | 
				
			||||||
    let (<!>) x f = Result.map f x
 | 
					    let (<!>) x f = Result.map f x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[<Microsoft.FSharp.Core.AutoOpen>]
 | 
					 | 
				
			||||||
[<RequireQualifiedAccess>]
 | 
					[<RequireQualifiedAccess>]
 | 
				
			||||||
 | 
					[<Microsoft.FSharp.Core.AutoOpen>]
 | 
				
			||||||
module List =
 | 
					module List =
 | 
				
			||||||
    let cons xs x = x :: xs
 | 
					    let cons xs x = x :: xs
 | 
				
			||||||
    let consTo x xs  = x :: xs
 | 
					    let consTo x xs  = x :: xs
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user