Introduce denormalized records + mapping functions
This commit is contained in:
parent
a0267b4cbb
commit
9867d06512
@ -48,7 +48,7 @@ let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerDat
|
|||||||
|> Seq.cast<DiscordComponent>
|
|> Seq.cast<DiscordComponent>
|
||||||
|
|
||||||
let pickDefense actionId player isTrainer =
|
let pickDefense actionId player isTrainer =
|
||||||
let shieldItems = player |> Player.getShieldItems
|
let shieldItems = player.Inventory |> Inventory.filterByShields
|
||||||
let buttons = constructButtons actionId (string player.DiscordId) player shieldItems isTrainer
|
let buttons = constructButtons actionId (string player.DiscordId) player shieldItems isTrainer
|
||||||
|
|
||||||
let embed =
|
let embed =
|
||||||
@ -56,10 +56,10 @@ let pickDefense actionId player isTrainer =
|
|||||||
.WithTitle("Shield Defense")
|
.WithTitle("Shield Defense")
|
||||||
.WithDescription("Pick a shield to protect yourself from hacks")
|
.WithDescription("Pick a shield to protect yourself from hacks")
|
||||||
|
|
||||||
for (item,sClass,cooldown) in Player.getShields player do
|
for shield in Inventory.getShieldItems player.Inventory do
|
||||||
let hours = TimeSpan.FromMinutes(int cooldown).TotalHours
|
let hours = TimeSpan.FromMinutes(int shield.Cooldown).TotalHours
|
||||||
let against = WeaponClass.getGoodAgainst(sClass) |> snd
|
let against = WeaponClass.getGoodAgainst(shield.Class) |> snd
|
||||||
embed.AddField(item.Name, $"Active {hours} hours\nDefeats {against}", true) |> ignore
|
embed.AddField(shield.Name, $"Active {hours} hours\nDefeats {against}", true) |> ignore
|
||||||
|
|
||||||
DiscordFollowupMessageBuilder()
|
DiscordFollowupMessageBuilder()
|
||||||
.AddComponents(buttons)
|
.AddComponents(buttons)
|
||||||
@ -67,7 +67,7 @@ let pickDefense actionId player isTrainer =
|
|||||||
.AsEphemeral(true)
|
.AsEphemeral(true)
|
||||||
|
|
||||||
let pickHack actionId attacker defender isTrainer =
|
let pickHack actionId attacker defender isTrainer =
|
||||||
let hackItems = attacker |> Player.getHackItems
|
let hackItems = attacker.Inventory |> Inventory.filterByHacks
|
||||||
let buttons = constructButtons actionId $"{defender.DiscordId}-{defender.Name}" attacker hackItems isTrainer
|
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 stealMsg = if not isTrainer then $"{defender.Name} has **{defender.Bank} $GBT** we can take from them. " else ""
|
||||||
@ -77,16 +77,16 @@ let pickHack actionId attacker defender isTrainer =
|
|||||||
.WithDescription($"{stealMsg}Pick the hack you want to use.")
|
.WithDescription($"{stealMsg}Pick the hack you want to use.")
|
||||||
|
|
||||||
if not isTrainer then
|
if not isTrainer then
|
||||||
for (item,power,hClass,cooldown) in Player.getHacks attacker do
|
for hack in Inventory.getHackItems attacker.Inventory do
|
||||||
let amount = if power > int defender.Bank then int defender.Bank else power
|
let amount = if hack.Power > int defender.Bank then int defender.Bank else hack.Power
|
||||||
embed.AddField(item.Name, $"Cooldown {cooldown} mins\nExtract {amount} $GBT", true) |> ignore
|
embed.AddField(hack.Name, $"Cooldown {hack.Cooldown} mins\nExtract {amount} $GBT", true) |> ignore
|
||||||
|
|
||||||
DiscordFollowupMessageBuilder()
|
DiscordFollowupMessageBuilder()
|
||||||
.AddComponents(buttons)
|
.AddComponents(buttons)
|
||||||
.AddEmbeds([ DiscordEmbedBuilder().WithImageUrl(hackGif).Build() ; embed.Build() ])
|
.AddEmbeds([ DiscordEmbedBuilder().WithImageUrl(hackGif).Build() ; embed.Build() ])
|
||||||
.AsEphemeral true
|
.AsEphemeral true
|
||||||
|
|
||||||
let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : Item) =
|
let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : HackItem) =
|
||||||
let embed =
|
let embed =
|
||||||
DiscordEmbedBuilder()
|
DiscordEmbedBuilder()
|
||||||
.WithImageUrl(getItemGif hack.Id)
|
.WithImageUrl(getItemGif hack.Id)
|
||||||
@ -98,10 +98,10 @@ let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : I
|
|||||||
.AddEmbed(embed.Build())
|
.AddEmbed(embed.Build())
|
||||||
.AsEphemeral(true)
|
.AsEphemeral(true)
|
||||||
|
|
||||||
let responseCreatedShield ((item,_,cooldown) : ShieldItem) =
|
let responseCreatedShield (shield : ShieldItem) =
|
||||||
let embed = DiscordEmbedBuilder().WithImageUrl(getItemGif item.Id)
|
let embed = DiscordEmbedBuilder().WithImageUrl(getItemGif shield.Id)
|
||||||
embed.Title <- "Mounted Shield"
|
embed.Title <- "Mounted Shield"
|
||||||
embed.Description <- $"Mounted {item.Name} shield for {TimeSpan.FromMinutes(int cooldown).Hours} hours"
|
embed.Description <- $"Mounted {shield.Name} shield for {TimeSpan.FromMinutes(int shield.Cooldown).Hours} hours"
|
||||||
|
|
||||||
DiscordFollowupMessageBuilder()
|
DiscordFollowupMessageBuilder()
|
||||||
.AddEmbed(embed)
|
.AddEmbed(embed)
|
||||||
@ -111,58 +111,6 @@ let eventSuccessfulHack (ctx : IDiscordContext) target prize =
|
|||||||
DiscordMessageBuilder()
|
DiscordMessageBuilder()
|
||||||
.WithContent($"{ctx.GetDiscordMember().Username} successfully hacked <@{target.DiscordId}> and took {prize} GoodBoyTokenz")
|
.WithContent($"{ctx.GetDiscordMember().Username} successfully hacked <@{target.DiscordId}> and took {prize} GoodBoyTokenz")
|
||||||
|
|
||||||
let getBuyItemsEmbed (playerInventory : Inventory) (storeInventory : Inventory) =
|
|
||||||
let embeds , buttons =
|
|
||||||
storeInventory
|
|
||||||
|> List.map (fun item ->
|
|
||||||
let embed = DiscordEmbedBuilder()
|
|
||||||
match item.Type with
|
|
||||||
| 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("Active For |", $"{TimeSpan.FromMinutes(int cooldown).Hours} hours", true)
|
|
||||||
.WithThumbnail(getItemIcon item.Id)
|
|
||||||
|> ignore
|
|
||||||
| _ -> ()
|
|
||||||
embed
|
|
||||||
.AddField("Price 💰", (if item.Price = 0<GBT> then "Free" else $"{item.Price} $GBT"), true)
|
|
||||||
.WithColor(WeaponClass.getClassEmbedColor item)
|
|
||||||
.WithTitle($"{item.Name}")
|
|
||||||
|> ignore
|
|
||||||
let button =
|
|
||||||
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 (items : Item list) =
|
|
||||||
let embeds , buttons =
|
|
||||||
items
|
|
||||||
|> List.map (fun item ->
|
|
||||||
DiscordEmbedBuilder()
|
|
||||||
.AddField("Sell For 💰", $"{item.Price} $GBT", true)
|
|
||||||
.WithTitle($"{item.Name}")
|
|
||||||
.WithColor(WeaponClass.getClassEmbedColor item)
|
|
||||||
.Build()
|
|
||||||
, DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Sell-{id}", $"Sell {item.Name}") :> DiscordComponent)
|
|
||||||
|> List.unzip
|
|
||||||
|
|
||||||
DiscordFollowupMessageBuilder()
|
|
||||||
.AddEmbeds(embeds)
|
|
||||||
.AddComponents(buttons)
|
|
||||||
.AsEphemeral(true)
|
|
||||||
|
|
||||||
let getArsenalEmbed (player : PlayerData) =
|
let getArsenalEmbed (player : PlayerData) =
|
||||||
DiscordFollowupMessageBuilder()
|
DiscordFollowupMessageBuilder()
|
||||||
.AsEphemeral(true)
|
.AsEphemeral(true)
|
||||||
|
@ -24,20 +24,60 @@ module Armory =
|
|||||||
inventory
|
inventory
|
||||||
|> List.filter (fun item -> match item.Type with Shield _ -> true | _ -> false)
|
|> List.filter (fun item -> match item.Type with Shield _ -> true | _ -> false)
|
||||||
|> List.sortBy (fun item -> item.Id)
|
|> List.sortBy (fun item -> item.Id)
|
||||||
let getHacks : HackItem list =
|
let getHackById id inventory = inventory |> getHackItems |> List.find (fun item -> item.Id = id)
|
||||||
battleItems
|
let getShieldById id inventory = inventory |> getShieldItems |> List.find (fun item -> item.Id = id)
|
||||||
|> List.choose (fun item ->
|
|
||||||
match item.Type with
|
module Inventory =
|
||||||
| Hack(power, hackClass, cooldown) -> Some (item , power, hackClass, cooldown) | _ -> None)
|
let itemToHack item power hackClass cooldown = {
|
||||||
|> List.sortBy (fun (item,_,_,_) -> item.Id)
|
Id = item.Id
|
||||||
let getShields : ShieldItem list =
|
Name = item.Name
|
||||||
battleItems
|
Price = item.Price
|
||||||
|> List.choose (fun item ->
|
Power = power
|
||||||
match item.Type with
|
Class = hackClass
|
||||||
| Shield(hackClass, cooldown) -> Some (item,hackClass,cooldown) | _ -> None)
|
Cooldown = cooldown
|
||||||
|> 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)
|
let itemToShield item hackClass cooldown = {
|
||||||
|
Id = item.Id
|
||||||
|
Name = item.Name
|
||||||
|
Price = item.Price
|
||||||
|
Class = hackClass
|
||||||
|
Cooldown = cooldown
|
||||||
|
}
|
||||||
|
let hackToItem (hack : HackItem) = {
|
||||||
|
Id = hack.Id
|
||||||
|
Name = hack.Name
|
||||||
|
Price = hack.Price
|
||||||
|
Type = Hack (hack.Power, hack.Class, hack.Cooldown)
|
||||||
|
}
|
||||||
|
let shieldToItem (shield : ShieldItem) = {
|
||||||
|
Id = shield.Id
|
||||||
|
Name = shield.Name
|
||||||
|
Price = shield.Price
|
||||||
|
Type = Shield (shield.Class, shield.Cooldown)
|
||||||
|
}
|
||||||
|
|
||||||
|
let filterByHacks inventory =
|
||||||
|
inventory |> List.filter (fun item -> match item.Type with Hack _ -> true | _ -> false)
|
||||||
|
let filterByShields inventory =
|
||||||
|
inventory |> List.filter (fun item -> match item.Type with Shield _ -> true | _ -> false)
|
||||||
|
|
||||||
|
let getHackItems inventory =
|
||||||
|
inventory
|
||||||
|
|> List.choose (fun item -> match item.Type with Hack (p,cl,co) -> Some (itemToHack item p cl co) | _ -> None)
|
||||||
|
|> List.sortBy (fun item -> item.Id)
|
||||||
|
let getShieldItems inventory =
|
||||||
|
inventory
|
||||||
|
|> List.choose (fun item -> match item.Type with Shield (cl,co) -> Some (itemToShield item cl co) | _ -> None)
|
||||||
|
|> List.sortBy (fun item -> item.Id)
|
||||||
|
let findHackById id inventory =
|
||||||
|
inventory |> getHackItems |> List.pick (fun item -> if item.Id = id then Some item else None)
|
||||||
|
let findShieldById id inventory =
|
||||||
|
inventory |> getShieldItems |> List.pick (fun item -> if item.Id = id then Some item else None)
|
||||||
|
let tryFindHackById id inventory =
|
||||||
|
inventory |> getHackItems |> List.tryFind (fun item -> item.Id = id)
|
||||||
|
let tryFindShieldById id inventory =
|
||||||
|
inventory |> getShieldItems |> List.tryFind (fun item -> item.Id = id)
|
||||||
|
|
||||||
module WeaponClass =
|
module WeaponClass =
|
||||||
// TODO: Find a different place to put this
|
// TODO: Find a different place to put this
|
||||||
@ -63,26 +103,6 @@ module WeaponClass =
|
|||||||
| _ -> ( ItemId.Cypher , ItemId.Worm )
|
| _ -> ( ItemId.Cypher , ItemId.Worm )
|
||||||
|
|
||||||
module Player =
|
module 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 =
|
let getHackEvents player =
|
||||||
player.Events
|
player.Events
|
||||||
|> Array.filter (fun act -> match act.Type with PlayerEventType.Hacking h -> h.IsInstigator | _ -> false)
|
|> Array.filter (fun act -> match act.Type with PlayerEventType.Hacking h -> h.IsInstigator | _ -> false)
|
||||||
@ -133,8 +153,27 @@ module Arsenal =
|
|||||||
|
|
||||||
let statusFormat p =
|
let statusFormat p =
|
||||||
let hacks = Player.getHackEvents p
|
let hacks = Player.getHackEvents p
|
||||||
$"**Hacks:** {Player.getHackItems p |> battleItemFormat}\n
|
$"**Hacks:** {Inventory.filterByHacks p.Inventory |> battleItemFormat}\n
|
||||||
**Shields:** {Player.getShieldItems p |> battleItemFormat}\n
|
**Shields:** {Inventory.filterByShields p.Inventory |> battleItemFormat}\n
|
||||||
**Hack Attacks:**\n{ hacks |> Array.take (min hacks.Length 10) |> actionFormat}\n
|
**Hack Attacks:**\n{ hacks |> Array.take (min hacks.Length 10) |> actionFormat}\n
|
||||||
**Active Shields:**\n{Player.getShieldEvents p |> actionFormat}"
|
**Active Shields:**\n{Player.getShieldEvents p |> actionFormat}"
|
||||||
|
|
||||||
|
module Items =
|
||||||
|
let mapHack fn inventory =
|
||||||
|
inventory
|
||||||
|
|> List.choose (fun item ->
|
||||||
|
match item.Type with
|
||||||
|
| Hack(power, hackClass, cooldown) -> Some <| fn item power hackClass cooldown
|
||||||
|
| _ -> None)
|
||||||
|
let mapShield fn inventory =
|
||||||
|
inventory
|
||||||
|
|> List.choose (fun item ->
|
||||||
|
match item.Type with
|
||||||
|
| Shield(hackClass, cooldown) -> Some <| fn item hackClass cooldown
|
||||||
|
| _ -> None)
|
||||||
|
let doShields fn inventory =
|
||||||
|
inventory
|
||||||
|
|> List.iter (fun item ->
|
||||||
|
match item.Type with
|
||||||
|
| Shield(hackClass, cooldown) -> fn item hackClass cooldown
|
||||||
|
| _ -> ())
|
||||||
|
@ -73,11 +73,24 @@ type PlayerEvent =
|
|||||||
Cooldown : int<mins>
|
Cooldown : int<mins>
|
||||||
Timestamp : DateTime }
|
Timestamp : DateTime }
|
||||||
|
|
||||||
type HackItem = Item * int * int * int<mins>
|
type HackItem = {
|
||||||
and ShieldItem = Item * int * int<mins>
|
Id : int
|
||||||
and FoodItem = Item * (Item -> PlayerData -> PlayerData)
|
Name : string
|
||||||
and AccessoryItem = Item * (Item -> PlayerData -> PlayerData)
|
Price : int<GBT>
|
||||||
and ItemType =
|
Power : int
|
||||||
|
Class : int
|
||||||
|
Cooldown : int<mins>
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShieldItem = {
|
||||||
|
Id : int
|
||||||
|
Name : string
|
||||||
|
Price : int<GBT>
|
||||||
|
Class : int
|
||||||
|
Cooldown : int<mins>
|
||||||
|
}
|
||||||
|
|
||||||
|
type ItemType =
|
||||||
| Hack of power : int * hackClass : int * cooldown : int<mins>
|
| Hack of power : int * hackClass : int * cooldown : int<mins>
|
||||||
| Shield of shieldClass : int * cooldown : int<mins>
|
| Shield of shieldClass : int * cooldown : int<mins>
|
||||||
| Food of effect : (Item -> PlayerData -> PlayerData)
|
| Food of effect : (Item -> PlayerData -> PlayerData)
|
||||||
|
@ -44,7 +44,7 @@ let checkWeaponHasCooldown (weapon : Item) attacker =
|
|||||||
| None -> Ok attacker
|
| None -> Ok attacker
|
||||||
|
|
||||||
let checkHasEmptyHacks attacker =
|
let checkHasEmptyHacks attacker =
|
||||||
match Player.getHacks attacker with
|
match Inventory.getHackItems 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.channelArmory}> and purchase one."
|
||||||
| _ -> Ok attacker
|
| _ -> Ok attacker
|
||||||
|
|
||||||
@ -68,36 +68,30 @@ 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 calculateDamage ((_,_,hackClass,_) : HackItem) ((_,shieldClass,_) : ShieldItem) =
|
|
||||||
if hackClass = shieldClass
|
|
||||||
then Weak
|
|
||||||
else Strong
|
|
||||||
|
|
||||||
let runHackerBattle defender (hack : HackItem) =
|
let runHackerBattle defender (hack : HackItem) =
|
||||||
defender
|
defender
|
||||||
|> Player.removeExpiredActions
|
|> Player.removeExpiredActions
|
||||||
|> fun p -> p.Events
|
|> fun p -> p.Events
|
||||||
|> Array.choose (fun event ->
|
|> Array.choose (fun event ->
|
||||||
match event.Type with
|
match event.Type with
|
||||||
| Shielding id -> Armory.getShields |> List.find (fun (item,_,_) -> item.Id = id) |> Some
|
| Shielding id -> defender.Inventory |> Inventory.getShieldItems |> List.find (fun item -> item.Id = id) |> Some
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
|> Array.map (calculateDamage hack)
|
|> Array.map (fun shield -> if hack.Class = shield.Class then Weak else Strong)
|
||||||
|> Array.contains Weak
|
|> Array.contains Weak
|
||||||
|
|
||||||
let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerData) (hack : HackItem) prize =
|
let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerData) (hack : HackItem) prize =
|
||||||
let (item, power, hackClass, cooldown) = hack
|
|
||||||
let updatePlayer amount attack p =
|
let updatePlayer amount attack p =
|
||||||
{ p with Events = Array.append [| attack |] p.Events ; Bank = max (p.Bank + amount) 0<GBT> }
|
{ p with Events = Array.append [| attack |] p.Events ; Bank = max (p.Bank + amount) 0<GBT> }
|
||||||
let event isDefenderEvent =
|
let event isDefenderEvent =
|
||||||
let hackEvent = {
|
let hackEvent = {
|
||||||
HackId = item.Id
|
HackId = hack.Id
|
||||||
Adversary = if isDefenderEvent then attacker.basicPlayer else defender.basicPlayer
|
Adversary = if isDefenderEvent then attacker.basicPlayer else defender.basicPlayer
|
||||||
IsInstigator = not isDefenderEvent
|
IsInstigator = not isDefenderEvent
|
||||||
Success = successfulHack
|
Success = successfulHack
|
||||||
}
|
}
|
||||||
{ Type = Hacking hackEvent
|
{ Type = Hacking hackEvent
|
||||||
Timestamp = DateTime.UtcNow
|
Timestamp = DateTime.UtcNow
|
||||||
Cooldown = if isDefenderEvent then int WeaponClass.SameTargetAttackCooldown.TotalMinutes * 1<mins> else cooldown }
|
Cooldown = if isDefenderEvent then int WeaponClass.SameTargetAttackCooldown.TotalMinutes * 1<mins> else hack.Cooldown }
|
||||||
|
|
||||||
[ DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer prize (event false) attacker
|
[ DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer prize (event false) attacker
|
||||||
DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer -prize (event true) defender
|
DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer -prize (event true) defender
|
||||||
@ -108,11 +102,10 @@ let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerDa
|
|||||||
|
|
||||||
let successfulHack (ctx : IDiscordContext) attacker defender (hack : HackItem) =
|
let successfulHack (ctx : IDiscordContext) attacker defender (hack : HackItem) =
|
||||||
async {
|
async {
|
||||||
let (item,power,hackClass,cooldown) = hack
|
let prizeAmount = if hack.Power < int defender.Bank then hack.Power else int defender.Bank
|
||||||
let prizeAmount = if power < int defender.Bank then power else int defender.Bank
|
|
||||||
do! updateCombatants true attacker defender hack (prizeAmount * 1<GBT>)
|
do! updateCombatants true attacker defender hack (prizeAmount * 1<GBT>)
|
||||||
|
|
||||||
let embed = Embeds.responseSuccessfulHack true defender.DiscordId prizeAmount item
|
let embed = Embeds.responseSuccessfulHack true defender.DiscordId prizeAmount hack
|
||||||
do! ctx.FollowUp embed |> Async.AwaitTask
|
do! ctx.FollowUp embed |> Async.AwaitTask
|
||||||
|
|
||||||
let builder = Embeds.eventSuccessfulHack ctx defender prizeAmount
|
let builder = Embeds.eventSuccessfulHack ctx defender prizeAmount
|
||||||
@ -123,9 +116,8 @@ let successfulHack (ctx : IDiscordContext) attacker defender (hack : HackItem) =
|
|||||||
}
|
}
|
||||||
|
|
||||||
let failedHack (ctx : IDiscordContext) attacker defender (hack : HackItem) =
|
let failedHack (ctx : IDiscordContext) attacker defender (hack : HackItem) =
|
||||||
let (item, power, hackClass, cooldown) = hack
|
|
||||||
async {
|
async {
|
||||||
let lostAmount = if power < int attacker.Bank then power else int attacker.Bank
|
let lostAmount = if hack.Power < int attacker.Bank then hack.Power else int attacker.Bank
|
||||||
let msg = $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {lostAmount} $GBT!"
|
let msg = $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {lostAmount} $GBT!"
|
||||||
do! sendFollowUpMessage ctx msg
|
do! sendFollowUpMessage ctx msg
|
||||||
|
|
||||||
@ -158,7 +150,8 @@ let handleAttack (ctx : IDiscordContext) =
|
|||||||
executePlayerAction ctx (fun attacker -> async {
|
executePlayerAction ctx (fun attacker -> async {
|
||||||
let tokens = ctx.GetInteractionId().Split("-")
|
let tokens = ctx.GetInteractionId().Split("-")
|
||||||
let hackId = int tokens.[1]
|
let hackId = int tokens.[1]
|
||||||
let item,_,_,_ as hackItem = Armory.getHackById hackId
|
let hack = Armory.battleItems |> Inventory.findHackById hackId
|
||||||
|
let hackAsItem = Inventory.hackToItem hack
|
||||||
let resultId , targetId = UInt64.TryParse tokens.[2]
|
let resultId , targetId = UInt64.TryParse tokens.[2]
|
||||||
let! resultTarget = DbService.tryFindPlayer GuildEnvironment.pgDb targetId
|
let! resultTarget = DbService.tryFindPlayer GuildEnvironment.pgDb targetId
|
||||||
|
|
||||||
@ -167,21 +160,21 @@ let handleAttack (ctx : IDiscordContext) =
|
|||||||
do! attacker
|
do! attacker
|
||||||
|> Player.removeExpiredActions
|
|> Player.removeExpiredActions
|
||||||
|> checkAlreadyHackedTarget defender
|
|> checkAlreadyHackedTarget defender
|
||||||
>>= checkPlayerOwnsWeapon item
|
>>= checkPlayerOwnsWeapon hackAsItem
|
||||||
>>= checkWeaponHasCooldown item
|
>>= checkWeaponHasCooldown hackAsItem
|
||||||
|> function
|
|> function
|
||||||
| Ok atkr ->
|
| Ok atkr ->
|
||||||
runHackerBattle defender hackItem
|
runHackerBattle defender hack
|
||||||
|> function
|
|> function
|
||||||
| false -> successfulHack ctx atkr defender hackItem
|
| false -> successfulHack ctx atkr defender hack
|
||||||
| true -> failedHack ctx attacker defender hackItem
|
| true -> failedHack ctx attacker defender hack
|
||||||
| Error msg -> Messaging.sendFollowUpMessage ctx msg
|
| Error msg -> Messaging.sendFollowUpMessage ctx msg
|
||||||
| _ -> do! Messaging.sendFollowUpMessage ctx "Error occurred processing attack"
|
| _ -> do! Messaging.sendFollowUpMessage ctx "Error occurred processing attack"
|
||||||
})
|
})
|
||||||
|
|
||||||
let defend (ctx : IDiscordContext) =
|
let defend (ctx : IDiscordContext) =
|
||||||
executePlayerAction ctx (fun player -> async {
|
executePlayerAction ctx (fun player -> async {
|
||||||
if Player.getShields player |> List.length > 0 then
|
if player.Inventory |> Inventory.filterByShields |> List.length > 0 then
|
||||||
let p = Player.removeExpiredActions player
|
let p = Player.removeExpiredActions player
|
||||||
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
|
||||||
@ -194,18 +187,19 @@ let handleDefense (ctx : IDiscordContext) =
|
|||||||
executePlayerAction ctx (fun player -> async {
|
executePlayerAction ctx (fun player -> async {
|
||||||
let tokens = ctx.GetInteractionId().Split("-")
|
let tokens = ctx.GetInteractionId().Split("-")
|
||||||
let shieldId = int tokens.[1]
|
let shieldId = int tokens.[1]
|
||||||
let item, shieldClass, cooldown as shield = Armory.getShields |> List.find (fun (item,_,_) -> item.Id = shieldId)
|
let shield = Armory.battleItems |> Inventory.findShieldById shieldId
|
||||||
|
let shieldAsItem = Inventory.shieldToItem shield
|
||||||
|
|
||||||
do! player
|
do! player
|
||||||
|> checkPlayerOwnsWeapon item
|
|> checkPlayerOwnsWeapon shieldAsItem
|
||||||
>>= checkPlayerHasShieldSlotsAvailable
|
>>= checkPlayerHasShieldSlotsAvailable
|
||||||
>>= checkWeaponHasCooldown item
|
>>= checkWeaponHasCooldown shieldAsItem
|
||||||
|> handleResultWithResponse ctx (fun p -> async {
|
|> handleResultWithResponse ctx (fun p -> async {
|
||||||
let embed = Embeds.responseCreatedShield shield
|
let embed = Embeds.responseCreatedShield shield
|
||||||
do! ctx.FollowUp embed |> Async.AwaitTask
|
do! ctx.FollowUp embed |> Async.AwaitTask
|
||||||
let defense = {
|
let defense = {
|
||||||
Type = Shielding shieldId
|
Type = Shielding shieldId
|
||||||
Cooldown = cooldown
|
Cooldown = shield.Cooldown
|
||||||
Timestamp = DateTime.UtcNow
|
Timestamp = DateTime.UtcNow
|
||||||
}
|
}
|
||||||
do! DbService.updatePlayer GuildEnvironment.pgDb p
|
do! DbService.updatePlayer GuildEnvironment.pgDb p
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
module Degenz.Store
|
module Degenz.Store
|
||||||
|
|
||||||
|
open System
|
||||||
open System.Threading.Tasks
|
open System.Threading.Tasks
|
||||||
open DSharpPlus.Entities
|
open DSharpPlus.Entities
|
||||||
open DSharpPlus
|
open DSharpPlus
|
||||||
@ -9,6 +10,58 @@ open Degenz
|
|||||||
open Degenz.Messaging
|
open Degenz.Messaging
|
||||||
open Degenz.PlayerInteractions
|
open Degenz.PlayerInteractions
|
||||||
|
|
||||||
|
let getBuyItemsEmbed (playerInventory : Inventory) (storeInventory : Inventory) =
|
||||||
|
let embeds , buttons =
|
||||||
|
storeInventory
|
||||||
|
|> List.map (fun item ->
|
||||||
|
let embed = DiscordEmbedBuilder()
|
||||||
|
match item.Type with
|
||||||
|
| Hack(power,_,cooldown) ->
|
||||||
|
embed.AddField($"$GBT Reward |", string power, true)
|
||||||
|
.AddField("Cooldown |", $"{TimeSpan.FromMinutes(int cooldown).Minutes} minutes", true)
|
||||||
|
.WithThumbnail(Embeds.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("Active For |", $"{TimeSpan.FromMinutes(int cooldown).Hours} hours", true)
|
||||||
|
.WithThumbnail(Embeds.getItemIcon item.Id)
|
||||||
|
|> ignore
|
||||||
|
| _ -> ()
|
||||||
|
embed
|
||||||
|
.AddField("Price 💰", (if item.Price = 0<GBT> then "Free" else $"{item.Price} $GBT"), true)
|
||||||
|
.WithColor(WeaponClass.getClassEmbedColor item)
|
||||||
|
.WithTitle($"{item.Name}")
|
||||||
|
|> ignore
|
||||||
|
let button =
|
||||||
|
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 (items : Item list) =
|
||||||
|
let embeds , buttons =
|
||||||
|
items
|
||||||
|
|> List.map (fun item ->
|
||||||
|
DiscordEmbedBuilder()
|
||||||
|
.AddField("Sell For 💰", $"{item.Price} $GBT", true)
|
||||||
|
.WithTitle($"{item.Name}")
|
||||||
|
.WithColor(WeaponClass.getClassEmbedColor item)
|
||||||
|
.Build()
|
||||||
|
, DiscordButtonComponent(WeaponClass.getClassButtonColor item, $"Sell-{id}", $"Sell {item.Name}") :> DiscordComponent)
|
||||||
|
|> List.unzip
|
||||||
|
|
||||||
|
DiscordFollowupMessageBuilder()
|
||||||
|
.AddEmbeds(embeds)
|
||||||
|
.AddComponents(buttons)
|
||||||
|
.AsEphemeral(true)
|
||||||
|
|
||||||
let checkHasSufficientFunds (item : Item) player =
|
let checkHasSufficientFunds (item : Item) player =
|
||||||
if player.Bank - item.Price >= 0<GBT>
|
if player.Bank - item.Price >= 0<GBT>
|
||||||
then Ok player
|
then Ok player
|
||||||
@ -31,15 +84,15 @@ let checkHasItemsInArsenal itemType items player =
|
|||||||
|
|
||||||
let buy getItems (ctx : IDiscordContext) =
|
let buy getItems (ctx : IDiscordContext) =
|
||||||
executePlayerAction ctx (fun player -> async {
|
executePlayerAction ctx (fun player -> async {
|
||||||
let itemStore = Embeds.getBuyItemsEmbed (getItems player.Inventory) (getItems Armory.battleItems)
|
let itemStore = getBuyItemsEmbed (getItems player.Inventory) (getItems Armory.battleItems)
|
||||||
do! ctx.FollowUp itemStore |> Async.AwaitTask
|
do! ctx.FollowUp itemStore |> Async.AwaitTask
|
||||||
})
|
})
|
||||||
|
|
||||||
let sell itemType getItems (ctx : IDiscordContext) =
|
let sell itemType getItems (ctx : IDiscordContext) =
|
||||||
executePlayerAction ctx (fun player -> async {
|
executePlayerAction ctx (fun player -> async {
|
||||||
let items = getItems player
|
let items = getItems player.Inventory
|
||||||
match checkHasItemsInArsenal itemType items player with
|
match checkHasItemsInArsenal itemType items player with
|
||||||
| Ok _ -> let itemStore = Embeds.getSellEmbed items
|
| Ok _ -> let itemStore = getSellEmbed items
|
||||||
do! ctx.FollowUp(itemStore) |> Async.AwaitTask
|
do! ctx.FollowUp(itemStore) |> Async.AwaitTask
|
||||||
| Error e -> do! sendFollowUpMessage ctx e
|
| Error e -> do! sendFollowUpMessage ctx e
|
||||||
})
|
})
|
||||||
@ -114,8 +167,8 @@ type Store() =
|
|||||||
member this.BuyShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy Armory.getShieldItems)
|
member this.BuyShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy Armory.getShieldItems)
|
||||||
|
|
||||||
[<SlashCommand("sell-hack", "Sell a hack for GoodBoyTokenz")>]
|
[<SlashCommand("sell-hack", "Sell a hack for GoodBoyTokenz")>]
|
||||||
member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Hacks" Player.getHackItems)
|
member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Hacks" Inventory.filterByHacks)
|
||||||
|
|
||||||
[<SlashCommand("sell-shield", "Sell a shield for GoodBoyTokenz")>]
|
[<SlashCommand("sell-shield", "Sell a shield for GoodBoyTokenz")>]
|
||||||
member this.SellShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" Player.getShieldItems)
|
member this.SellShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" Inventory.filterByShields)
|
||||||
|
|
||||||
|
@ -9,20 +9,20 @@ 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 defaultHackItem, hackPower, hackClass, hackCooldown as defaultHack = Armory.getHackById (int ItemId.Virus)
|
let defaultHack = Armory.battleItems |> Inventory.findHackById (int ItemId.Virus)
|
||||||
let defaultShieldItem, shieldClass, shieldCooldown as defaultShield = Armory.getShieldById (int ItemId.Firewall)
|
let defaultShield = Armory.battleItems |> Inventory.findShieldById (int ItemId.Firewall)
|
||||||
|
|
||||||
let TrainerEvents = [|
|
let TrainerEvents = [|
|
||||||
{ Timestamp = System.DateTime.UtcNow
|
{ Timestamp = System.DateTime.UtcNow
|
||||||
Cooldown = 2<mins>
|
Cooldown = defaultHack.Cooldown
|
||||||
Type = Hacking {
|
Type = Hacking {
|
||||||
Adversary = Sensei
|
Adversary = Sensei
|
||||||
Success = true
|
Success = true
|
||||||
IsInstigator = true
|
IsInstigator = true
|
||||||
HackId = defaultHackItem.Id } }
|
HackId = defaultHack.Id } }
|
||||||
{ Timestamp = System.DateTime.UtcNow
|
{ Timestamp = System.DateTime.UtcNow
|
||||||
Cooldown = shieldCooldown
|
Cooldown = defaultShield.Cooldown
|
||||||
Type = Shielding defaultShieldItem.Id }
|
Type = Shielding defaultShield.Id }
|
||||||
|]
|
|]
|
||||||
|
|
||||||
let sendInitialEmbed (client : DiscordClient) =
|
let sendInitialEmbed (client : DiscordClient) =
|
||||||
@ -52,7 +52,7 @@ let handleTrainerStep1 (ctx : IDiscordContext) =
|
|||||||
|> Async.AwaitTask
|
|> 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"
|
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"
|
+ "To enable it, you need to run the `/shield` slash command.\n\n"
|
||||||
+ $"Type the `/shield` command now, then select - `{defaultShieldItem.Name}`\n"
|
+ $"Type the `/shield` command now, then select - `{defaultShield.Name}`\n"
|
||||||
let builder =
|
let builder =
|
||||||
DiscordInteractionResponseBuilder()
|
DiscordInteractionResponseBuilder()
|
||||||
.WithContent(msg)
|
.WithContent(msg)
|
||||||
@ -66,7 +66,7 @@ let defend (ctx : IDiscordContext) =
|
|||||||
do! Messaging.defer ctx
|
do! Messaging.defer ctx
|
||||||
let m = ctx.GetDiscordMember()
|
let m = ctx.GetDiscordMember()
|
||||||
let name = if System.String.IsNullOrEmpty m.Nickname then m.DisplayName else m.Nickname
|
let name = if System.String.IsNullOrEmpty m.Nickname then m.DisplayName else m.Nickname
|
||||||
let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [ defaultShieldItem ] ; Name = name } true
|
let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [ Inventory.shieldToItem defaultShield ] ; Name = name } true
|
||||||
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
||||||
} |> Async.StartAsTask :> Task
|
} |> Async.StartAsTask :> Task
|
||||||
|
|
||||||
@ -88,11 +88,11 @@ let handleDefense (ctx : IDiscordContext) =
|
|||||||
let embed = Embeds.responseCreatedShield defaultShield
|
let embed = Embeds.responseCreatedShield defaultShield
|
||||||
do! ctx.FollowUp embed |> Async.AwaitTask
|
do! ctx.FollowUp embed |> Async.AwaitTask
|
||||||
do! Async.Sleep 4000
|
do! Async.Sleep 4000
|
||||||
do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **{defaultHackItem.Name}**"
|
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! Async.Sleep 5000
|
||||||
do! sendMessage' $"❌ HACKING FAILED!\n\n{playerName} defended hack from <@{Sensei.Id}>!"
|
do! sendMessage' $"❌ HACKING FAILED!\n\n{playerName} defended hack from <@{Sensei.Id}>!"
|
||||||
do! Async.Sleep 4000
|
do! Async.Sleep 4000
|
||||||
do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHackItem.Name)
|
do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHack.Name)
|
||||||
} |> Async.StartAsTask :> Task
|
} |> Async.StartAsTask :> Task
|
||||||
|
|
||||||
let handleTrainerStep3 (ctx : IDiscordContext) =
|
let handleTrainerStep3 (ctx : IDiscordContext) =
|
||||||
@ -103,7 +103,7 @@ let handleTrainerStep3 (ctx : IDiscordContext) =
|
|||||||
.WithContent
|
.WithContent
|
||||||
( "Now let’s **HACK** 💻... I want you to **HACK ME**!\n\n"
|
( "Now let’s **HACK** 💻... I want you to **HACK ME**!\n\n"
|
||||||
+ "To **hack**, you need to run the `/hack` slash command.\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 `{defaultHackItem.Name}`")
|
+ $"Type the `/hack` command now, then choose me - <@{Sensei.Id}> as your target, and select `{defaultHack.Name}`")
|
||||||
|
|
||||||
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
|
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
|
||||||
} |> Async.StartAsTask :> Task
|
} |> Async.StartAsTask :> Task
|
||||||
@ -115,8 +115,9 @@ let hack (target : DiscordUser) (ctx : IDiscordContext) =
|
|||||||
let isRightTarget = target.Id = Sensei.Id
|
let isRightTarget = target.Id = Sensei.Id
|
||||||
match isRightTarget with
|
match isRightTarget with
|
||||||
| true ->
|
| true ->
|
||||||
|
let player = { PlayerData.empty with Inventory = [ Inventory.hackToItem defaultHack ] }
|
||||||
let bot = { PlayerData.empty with DiscordId = Sensei.Id ; Name = Sensei.Name }
|
let bot = { PlayerData.empty with DiscordId = Sensei.Id ; Name = Sensei.Name }
|
||||||
let embed = Embeds.pickHack "Trainer-4" { PlayerData.empty with Inventory = [ defaultHackItem ] } bot true
|
let embed = Embeds.pickHack "Trainer-4" player bot true
|
||||||
|
|
||||||
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
||||||
| false ->
|
| false ->
|
||||||
@ -132,7 +133,7 @@ let handleHack (ctx : IDiscordContext) =
|
|||||||
PlayerInteractions.executePlayerAction ctx (fun player -> async {
|
PlayerInteractions.executePlayerAction ctx (fun player -> async {
|
||||||
let sendMessage' = sendFollowUpMessage ctx
|
let sendMessage' = sendFollowUpMessage ctx
|
||||||
do! Async.Sleep 1000
|
do! Async.Sleep 1000
|
||||||
let embed = Embeds.responseSuccessfulHack false Sensei.Id hackPower defaultHackItem
|
let embed = Embeds.responseSuccessfulHack false Sensei.Id defaultHack.Power defaultHack
|
||||||
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
||||||
do! Async.Sleep 4000
|
do! Async.Sleep 4000
|
||||||
do! sendMessage'
|
do! sendMessage'
|
||||||
@ -150,7 +151,7 @@ let handleHack (ctx : IDiscordContext) =
|
|||||||
do! DbService.addAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement
|
do! DbService.addAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement
|
||||||
|> Async.Ignore
|
|> Async.Ignore
|
||||||
|
|
||||||
sb.Append($"I'm going to gift you a hack,`{defaultHackItem.Name}` and a shield, `{defaultShieldItem.Name}`") |> 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.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
|
sb.AppendLine("To finish your training and collect the loot, type the `/arsenal` command **NOW**") |> ignore
|
||||||
do! Async.Sleep 1000
|
do! Async.Sleep 1000
|
||||||
@ -165,12 +166,15 @@ let handleHack (ctx : IDiscordContext) =
|
|||||||
|
|
||||||
let handleArsenal (ctx : IDiscordContext) =
|
let handleArsenal (ctx : IDiscordContext) =
|
||||||
PlayerInteractions.executePlayerAction ctx (fun player -> async {
|
PlayerInteractions.executePlayerAction ctx (fun player -> async {
|
||||||
let hasStockWeapons = Player.getHackItems player |> List.exists (fun item -> item.Id = defaultHackItem.Id)
|
let hasStockWeapons =
|
||||||
|
player.Inventory
|
||||||
|
|> List.choose (fun item -> if item.Id = defaultHack.Id || item.Id = defaultShield.Id then Some item else None)
|
||||||
|
|> List.length > 0
|
||||||
let updatedPlayer =
|
let updatedPlayer =
|
||||||
if not hasStockWeapons then {
|
if not hasStockWeapons then {
|
||||||
Player.removeExpiredActions player with
|
Player.removeExpiredActions player with
|
||||||
Events = TrainerEvents |> Array.append player.Events
|
Events = TrainerEvents |> Array.append player.Events
|
||||||
Inventory = defaultHackItem::defaultShieldItem::player.Inventory
|
Inventory = Inventory.hackToItem defaultHack::Inventory.shieldToItem defaultShield::player.Inventory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Player.removeExpiredActions player
|
Player.removeExpiredActions player
|
||||||
@ -187,7 +191,7 @@ let handleArsenal (ctx : IDiscordContext) =
|
|||||||
let! completed = DbService.checkHasAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement
|
let! completed = DbService.checkHasAchievement GuildEnvironment.pgDb player.DiscordId trainerAchievement
|
||||||
if not completed then
|
if not completed then
|
||||||
do! Async.Sleep 3000
|
do! Async.Sleep 3000
|
||||||
let rewards = [ $"{defaultHackItem.Name} Hack" ; $"{defaultShieldItem.Name} Shield" ]
|
let rewards = [ $"{defaultHack.Name} Hack" ; $"{defaultShield.Name} Shield" ]
|
||||||
let embed = Embeds.getAchievementEmbed rewards "You completed the Training Dojo and collected loot." trainerAchievement
|
let embed = Embeds.getAchievementEmbed rewards "You completed the Training Dojo and collected loot." trainerAchievement
|
||||||
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
||||||
do! Async.Sleep 2000
|
do! Async.Sleep 2000
|
||||||
|
Loading…
x
Reference in New Issue
Block a user