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,77 +157,70 @@ 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) =
|
||||||
async {
|
async {
|
||||||
|
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