Refactor for new inventory, events, and traits
This commit is contained in:
parent
c1c51dcd99
commit
7900bba3c3
@ -1,6 +1,7 @@
|
|||||||
module Degenz.Embeds
|
module Degenz.Embeds
|
||||||
|
|
||||||
open System
|
open System
|
||||||
|
open DSharpPlus
|
||||||
open Degenz.Messaging
|
open Degenz.Messaging
|
||||||
open Degenz.Types
|
open Degenz.Types
|
||||||
open DSharpPlus.Entities
|
open DSharpPlus.Entities
|
||||||
@ -37,15 +38,15 @@ let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerDat
|
|||||||
|> Player.getItems itemType
|
|> Player.getItems itemType
|
||||||
|> Array.map (fun item ->
|
|> Array.map (fun item ->
|
||||||
let action =
|
let action =
|
||||||
player.Actions
|
player.Events
|
||||||
|> Array.tryFind (fun i -> i.ActionId = item.Id)
|
|> Array.tryFind (fun i -> i.ItemId = item.Id)
|
||||||
match action , isTrainer with
|
match action , isTrainer with
|
||||||
| None , _ | Some _ , true ->
|
| None , _ | Some _ , true ->
|
||||||
DiscordButtonComponent(Game.getClassButtonColor item.Class, $"{actionId}-{item.Id}-{buttonInfo}", $"{item.Name}")
|
DiscordButtonComponent(ButtonStyle.Primary, $"{actionId}-{item.Id}-{buttonInfo}", $"{item.Name}")
|
||||||
| Some act , false ->
|
| Some act , false ->
|
||||||
let c = ((Armory.getItem act.ActionId).Cooldown)
|
let c = ((Armory.getItem act.ItemId).Cooldown)
|
||||||
let time = Messaging.getShortTimeText (TimeSpan.FromMinutes(int c)) act.Timestamp
|
let time = Messaging.getShortTimeText (TimeSpan.FromMinutes(int c)) act.Timestamp
|
||||||
DiscordButtonComponent(Game.getClassButtonColor item.Class, $"{actionId}-{item.Id}", $"{item.Name} ({time} left)", true))
|
DiscordButtonComponent(ButtonStyle.Primary, $"{actionId}-{item.Id}", $"{item.Name} ({time} left)", true))
|
||||||
|> Seq.cast<DiscordComponent>
|
|> Seq.cast<DiscordComponent>
|
||||||
|
|
||||||
let pickDefense actionId player isTrainer =
|
let pickDefense actionId player isTrainer =
|
||||||
@ -109,25 +110,24 @@ let getBuyItemsEmbed (player : PlayerData) (itemType : ItemType) (store : Battle
|
|||||||
match item.Type with
|
match item.Type with
|
||||||
| Hack ->
|
| Hack ->
|
||||||
embed
|
embed
|
||||||
.AddField($"Weak Against |", Game.getGoodAgainst item.Class |> fst |> string , true)
|
.AddField($"Hacking Power |", string item.Power, true)
|
||||||
.AddField("Cooldown |", $"{TimeSpan.FromMinutes(int item.Cooldown).Minutes} minutes", true)
|
.AddField("Cooldown |", $"{TimeSpan.FromMinutes(int item.Cooldown).Minutes} minutes", true)
|
||||||
.WithThumbnail(getHackIcon (enum<HackId>(item.Id)))
|
.WithThumbnail(getHackIcon (enum<HackId>(item.Id)))
|
||||||
|> ignore
|
|> ignore
|
||||||
| Shield ->
|
| Shield ->
|
||||||
embed
|
embed
|
||||||
.AddField($"Strong Against |", Game.getGoodAgainst item.Class |> snd |> string , true)
|
.AddField($"Defensive Strength |", string item.Power, true)
|
||||||
.AddField("Active For |", $"{TimeSpan.FromMinutes(int item.Cooldown).Hours} hours", true)
|
.AddField("Active For |", $"{TimeSpan.FromMinutes(int item.Cooldown).Hours} hours", true)
|
||||||
.WithThumbnail(getShieldIcon (enum<ShieldId>(item.Id)))
|
.WithThumbnail(getShieldIcon (enum<ShieldId>(item.Id)))
|
||||||
|> ignore
|
|> ignore
|
||||||
embed
|
embed
|
||||||
.AddField("Cost 💰", $"{item.Cost} $GBT", true)
|
.AddField("Cost 💰", $"{item.Price} $GBT", true)
|
||||||
.WithColor(Game.getClassEmbedColor item.Class)
|
|
||||||
.WithTitle($"{item.Name}")
|
.WithTitle($"{item.Name}")
|
||||||
|> ignore
|
|> ignore
|
||||||
let button =
|
let button =
|
||||||
if player.Arsenal |> Array.exists (fun i -> i.Id = item.Id)
|
if player.Inventory |> Array.exists (fun i -> i.Id = item.Id)
|
||||||
then DiscordButtonComponent(Game.getClassButtonColor item.Class, $"Buy-{item.Id}", $"Own {item.Name}", true)
|
then DiscordButtonComponent(ButtonStyle.Primary, $"Buy-{item.Id}", $"Own {item.Name}", true)
|
||||||
else DiscordButtonComponent(Game.getClassButtonColor item.Class, $"Buy-{item.Id}", $"Buy {item.Name}")
|
else DiscordButtonComponent(ButtonStyle.Primary, $"Buy-{item.Id}", $"Buy {item.Name}")
|
||||||
embed.Build() , button :> DiscordComponent)
|
embed.Build() , button :> DiscordComponent)
|
||||||
|> Array.unzip
|
|> Array.unzip
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ let getBuyItemsEmbed (player : PlayerData) (itemType : ItemType) (store : Battle
|
|||||||
|
|
||||||
let getSellItemsEmbed (itemType : ItemType) (player : PlayerData) =
|
let getSellItemsEmbed (itemType : ItemType) (player : PlayerData) =
|
||||||
let embeds , buttons =
|
let embeds , buttons =
|
||||||
player.Arsenal
|
player.Inventory
|
||||||
|> Array.filter (fun i -> i.Type = itemType)
|
|> Array.filter (fun i -> i.Type = itemType)
|
||||||
|> Array.map (fun item ->
|
|> Array.map (fun item ->
|
||||||
let embed = DiscordEmbedBuilder()
|
let embed = DiscordEmbedBuilder()
|
||||||
@ -146,11 +146,10 @@ let getSellItemsEmbed (itemType : ItemType) (player : PlayerData) =
|
|||||||
| Hack -> embed.WithThumbnail(getHackIcon (enum<HackId>(item.Id))) |> ignore
|
| Hack -> embed.WithThumbnail(getHackIcon (enum<HackId>(item.Id))) |> ignore
|
||||||
| Shield -> embed.WithThumbnail(getShieldIcon (enum<ShieldId>(item.Id))) |> ignore
|
| Shield -> embed.WithThumbnail(getShieldIcon (enum<ShieldId>(item.Id))) |> ignore
|
||||||
embed
|
embed
|
||||||
.AddField("Sell For 💰", $"{item.Cost} $GBT", true)
|
.AddField("Sell For 💰", $"{item.Price} $GBT", true)
|
||||||
.WithColor(Game.getClassEmbedColor item.Class)
|
|
||||||
.WithTitle($"{item.Name}")
|
.WithTitle($"{item.Name}")
|
||||||
|> ignore
|
|> ignore
|
||||||
let button = DiscordButtonComponent(Game.getClassButtonColor item.Class, $"Sell-{item.Id}", $"Sell {item.Name}")
|
let button = DiscordButtonComponent(ButtonStyle.Primary, $"Sell-{item.Id}", $"Sell {item.Name}")
|
||||||
embed.Build() , button :> DiscordComponent)
|
embed.Build() , button :> DiscordComponent)
|
||||||
|> Array.unzip
|
|> Array.unzip
|
||||||
|
|
||||||
|
70
Bot/Game.fs
70
Bot/Game.fs
@ -14,21 +14,6 @@ module Game =
|
|||||||
|
|
||||||
let SameTargetAttackCooldown = System.TimeSpan.FromHours(6)
|
let SameTargetAttackCooldown = System.TimeSpan.FromHours(6)
|
||||||
|
|
||||||
let getClassButtonColor = function
|
|
||||||
| Network -> ButtonStyle.Danger
|
|
||||||
| Exploit -> ButtonStyle.Success
|
|
||||||
| Penetration -> ButtonStyle.Primary
|
|
||||||
|
|
||||||
let getClassEmbedColor = function
|
|
||||||
| Network -> DiscordColor.Red
|
|
||||||
| Penetration -> DiscordColor.Blurple
|
|
||||||
| Exploit -> DiscordColor.Green
|
|
||||||
|
|
||||||
let getGoodAgainst = function
|
|
||||||
| BattleClass.Network -> ( ShieldId.Firewall , HackId.Virus )
|
|
||||||
| BattleClass.Penetration -> ( ShieldId.Cypher , HackId.RemoteAccess )
|
|
||||||
| BattleClass.Exploit -> ( ShieldId.Encryption , HackId.Worm )
|
|
||||||
|
|
||||||
let executePlayerAction (ctx : IDiscordContext) (dispatch : PlayerData -> Async<unit>) =
|
let executePlayerAction (ctx : IDiscordContext) (dispatch : PlayerData -> Async<unit>) =
|
||||||
async {
|
async {
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
@ -78,65 +63,64 @@ module Game =
|
|||||||
} |> Async.StartAsTask :> Task
|
} |> Async.StartAsTask :> Task
|
||||||
|
|
||||||
module Player =
|
module Player =
|
||||||
let getItems itemType (player : PlayerData) = player.Arsenal |> Array.filter (fun i -> i.Type = itemType)
|
let getItems itemType (player : PlayerData) = player.Inventory |> Array.filter (fun i -> i.Type = itemType)
|
||||||
let getHacks (player : PlayerData) = getItems ItemType.Hack player
|
let getHacks (player : PlayerData) = getItems ItemType.Hack player
|
||||||
let getShields (player : PlayerData) = getItems ItemType.Shield player
|
let getShields (player : PlayerData) = getItems ItemType.Shield player
|
||||||
let getAttacks player =
|
let getHackEvents player =
|
||||||
player.Actions
|
player.Events
|
||||||
|> Array.filter (fun act -> match act.Type with Attack _ -> true | _ -> false || act.ActionId < 12)
|
|> Array.filter (fun act -> match act.Type with PlayerEventType.Hack -> true | _ -> false || act.ItemId < 12)
|
||||||
let getDefenses player =
|
let getShieldEvents player =
|
||||||
player.Actions
|
player.Events
|
||||||
|> Array.filter (fun act -> match act.Type with Defense -> true | _ -> false || act.ActionId < 12)
|
|> Array.filter (fun act -> match act.Type with PlayerEventType.Shield -> true | _ -> false || act.ItemId < 12)
|
||||||
|
|
||||||
// TODO: This parameter is a result of putting the cooldown on the attack side. Put the cooldown on the defender
|
// TODO: This parameter is a result of putting the cooldown on the attack side. Put the cooldown on the defender
|
||||||
// side and only check if it's the same target, we need to refactor Actions
|
// side and only check if it's the same target, we need to refactor Actions
|
||||||
let removeExpiredActions filterByAttackCooldown player =
|
let removeExpiredActions filterByAttackCooldown player =
|
||||||
let actions =
|
let actions =
|
||||||
player.Actions
|
player.Events
|
||||||
|> Array.filter (fun (act : Action) ->
|
|> Array.filter (fun (act : PlayerEvent) ->
|
||||||
let itemCooldown =
|
let itemCooldown =
|
||||||
if act.ActionId < 12 then
|
if act.ItemId < 12 then
|
||||||
(Armory.getItem act.ActionId).Cooldown
|
(Armory.getItem act.ItemId).Cooldown
|
||||||
else
|
else
|
||||||
match act.Type with
|
match act.Type with
|
||||||
| Attack _ -> 1<mins>
|
| PlayerEventType.Steal -> 1<mins>
|
||||||
| Defense -> 720<mins>
|
| _ -> 720<mins>
|
||||||
|> int
|
|> int
|
||||||
|
|
||||||
match act.Type , filterByAttackCooldown with
|
match act.Type , filterByAttackCooldown with
|
||||||
| Attack _ , true -> System.DateTime.UtcNow - act.Timestamp < System.TimeSpan.FromMinutes(itemCooldown)
|
| PlayerEventType.Hack , true -> System.DateTime.UtcNow - act.Timestamp < System.TimeSpan.FromMinutes(itemCooldown)
|
||||||
| Attack _ , false -> System.DateTime.UtcNow - act.Timestamp < Game.SameTargetAttackCooldown
|
| PlayerEventType.Hack , false -> System.DateTime.UtcNow - act.Timestamp < Game.SameTargetAttackCooldown
|
||||||
| Defense , _ -> System.DateTime.UtcNow - act.Timestamp < System.TimeSpan.FromMinutes(itemCooldown))
|
| PlayerEventType.Shield , _ -> System.DateTime.UtcNow - act.Timestamp < System.TimeSpan.FromMinutes(itemCooldown)
|
||||||
{ player with Actions = actions }
|
| _ -> System.DateTime.UtcNow - act.Timestamp < System.TimeSpan.FromMinutes(itemCooldown))
|
||||||
|
{ player with Events = actions }
|
||||||
|
|
||||||
let modifyBank (player : PlayerData) amount = { player with Bank = max (player.Bank + amount) 0<GBT> }
|
let modifyBank (player : PlayerData) amount = { player with Bank = max (player.Bank + amount) 0<GBT> }
|
||||||
|
|
||||||
let getAttacksFlat actions = actions |> Array.choose (fun act -> match act.Type with Attack ar -> Some (act,ar.Target,ar.Result) | Defense -> None)
|
|
||||||
|
|
||||||
module Arsenal =
|
module Arsenal =
|
||||||
let battleItemFormat (items : BattleItem array) =
|
let battleItemFormat (items : BattleItem array) =
|
||||||
match items with
|
match items with
|
||||||
| [||] -> "None"
|
| [||] -> "None"
|
||||||
| _ -> items |> Array.toList |> List.map (fun i -> i.Name) |> String.concat ", "
|
| _ -> items |> Array.toList |> List.map (fun i -> i.Name) |> String.concat ", "
|
||||||
|
|
||||||
let actionFormat (actions : Action array) =
|
let actionFormat (actions : PlayerEvent array) =
|
||||||
match actions with
|
match actions with
|
||||||
| [||] -> "None"
|
| [||] -> "None"
|
||||||
| _ ->
|
| _ ->
|
||||||
let hacks , defenses =
|
let hacks , defenses =
|
||||||
actions
|
actions
|
||||||
|> Array.filter (fun act -> act.ActionId < 12)
|
|> Array.filter (fun act -> act.ItemId < 12)
|
||||||
|> Array.partition (fun act -> match act.Type with Attack _ -> true | Defense -> false)
|
|> Array.partition (fun act -> match act.Type with PlayerEventType.Hack -> true | _ -> false)
|
||||||
let hacks = hacks |> Array.take (min hacks.Length 10)
|
let hacks = hacks |> Array.take (min hacks.Length 10)
|
||||||
hacks
|
hacks
|
||||||
|> Array.append defenses
|
|> Array.append defenses
|
||||||
|> Array.map (fun act ->
|
|> Array.map (fun act ->
|
||||||
let item = Armory.getItem act.ActionId
|
let item = Armory.getItem act.ItemId
|
||||||
match act.Type with
|
match act.Type with
|
||||||
| Attack atk ->
|
| PlayerEventType.Hack ->
|
||||||
let cooldown = Messaging.getTimeText false Game.SameTargetAttackCooldown act.Timestamp
|
let cooldown = Messaging.getTimeText false Game.SameTargetAttackCooldown act.Timestamp
|
||||||
$"Hacked {atk.Target.Name} {cooldown} ago"
|
$"Hacked {act.Adversary.Name} {cooldown} ago"
|
||||||
| Defense ->
|
| _ ->
|
||||||
let cooldown = Messaging.getTimeText true (System.TimeSpan.FromMinutes(int item.Cooldown)) act.Timestamp
|
let cooldown = Messaging.getTimeText true (System.TimeSpan.FromMinutes(int item.Cooldown)) act.Timestamp
|
||||||
$"{item.Name} Shield active for {cooldown}")
|
$"{item.Name} Shield active for {cooldown}")
|
||||||
|> String.concat "\n"
|
|> String.concat "\n"
|
||||||
@ -144,6 +128,6 @@ module Arsenal =
|
|||||||
let statusFormat p =
|
let statusFormat p =
|
||||||
$"**Hacks:** {Player.getHacks p |> battleItemFormat}\n
|
$"**Hacks:** {Player.getHacks p |> battleItemFormat}\n
|
||||||
**Shields:** {Player.getShields p |> battleItemFormat}\n
|
**Shields:** {Player.getShields p |> battleItemFormat}\n
|
||||||
**Hack Attacks:**\n{Player.getAttacks p |> actionFormat}\n
|
**Hack Attacks:**\n{Player.getHackEvents p |> actionFormat}\n
|
||||||
**Active Shields:**\n{Player.getDefenses p |> actionFormat}"
|
**Active Shields:**\n{Player.getShieldEvents p |> actionFormat}"
|
||||||
|
|
||||||
|
@ -15,19 +15,18 @@ let checkPlayerIsAttackingThemselves defender attacker =
|
|||||||
| false -> Ok attacker
|
| false -> Ok attacker
|
||||||
|
|
||||||
let checkAlreadyHackedTarget defenderId attacker =
|
let checkAlreadyHackedTarget defenderId attacker =
|
||||||
attacker.Actions
|
attacker.Events
|
||||||
|> Player.getAttacksFlat
|
|> Array.tryFind (fun pe -> pe.Adversary.Id = defenderId)
|
||||||
|> Array.tryFind (fun (_,t,_) -> t.Id = defenderId)
|
|
||||||
|> function
|
|> function
|
||||||
| Some ( atk , target , _ ) ->
|
| Some event ->
|
||||||
let cooldown = getTimeText true Game.SameTargetAttackCooldown atk.Timestamp
|
let cooldown = getTimeText true Game.SameTargetAttackCooldown event.Timestamp
|
||||||
Error $"You can only hack the same target once every {Game.SameTargetAttackCooldown.Hours} hours, wait {cooldown} to attempt another hack on {target.Name}."
|
Error $"You can only hack the same target once every {Game.SameTargetAttackCooldown.Hours} hours, wait {cooldown} to attempt another hack on {event.Adversary.Name}."
|
||||||
| None -> Ok attacker
|
| None -> Ok attacker
|
||||||
|
|
||||||
let checkItemHasCooldown itemId attacker =
|
let checkItemHasCooldown itemId attacker =
|
||||||
let cooldown =
|
let cooldown =
|
||||||
attacker.Actions
|
attacker.Events
|
||||||
|> Array.tryFind (fun a -> a.ActionId = itemId)
|
|> Array.tryFind (fun a -> a.ItemId = itemId)
|
||||||
|> function
|
|> function
|
||||||
| Some a -> a.Timestamp
|
| Some a -> a.Timestamp
|
||||||
| None -> DateTime.MinValue
|
| None -> DateTime.MinValue
|
||||||
@ -45,7 +44,7 @@ let checkHasEmptyHacks attacker =
|
|||||||
| _ -> Ok attacker
|
| _ -> Ok attacker
|
||||||
|
|
||||||
let checkPlayerOwnsWeapon itemId player =
|
let checkPlayerOwnsWeapon itemId player =
|
||||||
match player.Arsenal |> Array.exists (fun i -> i.Id = itemId) with
|
match player.Inventory |> Array.exists (fun i -> i.Id = itemId) with
|
||||||
| true -> Ok player
|
| true -> Ok player
|
||||||
| false -> Error $"You sold your weapon already, you cheeky bastard..."
|
| false -> Error $"You sold your weapon already, you cheeky bastard..."
|
||||||
|
|
||||||
@ -56,7 +55,7 @@ let checkTargetHasMoney (target : PlayerData) attacker =
|
|||||||
|
|
||||||
let checkPlayerHasShieldSlotsAvailable shield player =
|
let checkPlayerHasShieldSlotsAvailable shield player =
|
||||||
let updatedPlayer = player |> Player.removeExpiredActions false
|
let updatedPlayer = player |> Player.removeExpiredActions false
|
||||||
let defenses = Player.getDefenses updatedPlayer
|
let defenses = Player.getShieldEvents updatedPlayer
|
||||||
match defenses |> Array.length >= 2 with
|
match defenses |> Array.length >= 2 with
|
||||||
| true ->
|
| true ->
|
||||||
let timestamp = defenses |> Array.rev |> Array.head |> fun a -> a.Timestamp // This should be the next expiring timestamp
|
let timestamp = defenses |> Array.rev |> Array.head |> fun a -> a.Timestamp // This should be the next expiring timestamp
|
||||||
@ -65,24 +64,33 @@ let checkPlayerHasShieldSlotsAvailable shield player =
|
|||||||
| false -> Ok updatedPlayer
|
| false -> Ok updatedPlayer
|
||||||
|
|
||||||
let calculateDamage (hack : BattleItem) (shield : BattleItem) =
|
let calculateDamage (hack : BattleItem) (shield : BattleItem) =
|
||||||
if hack.Class = shield.Class
|
if hack.Power < shield.Power
|
||||||
then Weak
|
then Weak
|
||||||
else Strong
|
else Strong
|
||||||
|
|
||||||
let runHackerBattle defender hack =
|
let runHackerBattle defender hack =
|
||||||
defender
|
defender
|
||||||
|> Player.removeExpiredActions false
|
|> Player.removeExpiredActions false
|
||||||
|> Player.getDefenses
|
|> Player.getShieldEvents
|
||||||
|> Array.map (fun dfn -> Armory.battleItems |> Array.find (fun w -> w.Id = dfn.ActionId))
|
|> Array.map (fun dfn -> Armory.battleItems |> Array.find (fun w -> w.Id = dfn.ItemId))
|
||||||
|> Array.map (calculateDamage (hack))
|
|> Array.map (calculateDamage (hack))
|
||||||
|> Array.contains Weak
|
|> Array.contains Weak
|
||||||
|
|
||||||
let updateCombatants attacker defender hack prize =
|
let updateCombatants attacker defender hack prize =
|
||||||
let updatePlayer amount attack p =
|
let updatePlayer amount attack p =
|
||||||
{ p with Actions = Array.append [| attack |] p.Actions ; Bank = max (p.Bank + amount) 0<GBT> }
|
{ p with Events = Array.append [| attack |] p.Events ; Bank = max (p.Bank + amount) 0<GBT> }
|
||||||
let target = { Id = defender.DiscordId ; Name = defender.Name }
|
let target = { Id = defender.DiscordId ; Name = defender.Name }
|
||||||
let attack = { ActionId = int hack ; Type = Attack { Target = target ; Result = prize > 0<GBT> } ; Timestamp = DateTime.UtcNow }
|
let attack = {
|
||||||
|
ItemId = int hack
|
||||||
|
Type = PlayerEventType.Hack
|
||||||
|
Adversary = target
|
||||||
|
Result = if prize > 0<GBT> then PlayerEventResult.Successful else PlayerEventResult.Failed
|
||||||
|
Timestamp = DateTime.UtcNow
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This is what I was talking about, this isn't a "Shield" event, this is a hack event but there's an adversary
|
||||||
|
// who loses, so the event itself is to just "hack", so there's no "mugged" event, there's just a failed steal defense
|
||||||
|
// or something like that.
|
||||||
[ DbService.updatePlayer <| updatePlayer prize attack attacker
|
[ DbService.updatePlayer <| updatePlayer prize attack attacker
|
||||||
DbService.updatePlayer <| Player.modifyBank defender -prize ]
|
DbService.updatePlayer <| Player.modifyBank defender -prize ]
|
||||||
|> Async.Parallel
|
|> Async.Parallel
|
||||||
@ -181,8 +189,14 @@ let handleDefense (ctx : IDiscordContext) =
|
|||||||
|> handleResultWithResponse ctx (fun _ -> async { // Don't use this player, it removes player cooldowns
|
|> handleResultWithResponse ctx (fun _ -> async { // Don't use this player, it removes player cooldowns
|
||||||
let embed = Embeds.responseCreatedShield (Armory.getItem shieldId)
|
let embed = Embeds.responseCreatedShield (Armory.getItem shieldId)
|
||||||
do! ctx.FollowUp embed |> Async.AwaitTask
|
do! ctx.FollowUp embed |> Async.AwaitTask
|
||||||
let defense = { ActionId = shieldId ; Type = Defense ; Timestamp = DateTime.UtcNow }
|
let defense = {
|
||||||
do! DbService.updatePlayer <| { player with Actions = Array.append [| defense |] player.Actions }
|
ItemId = shieldId
|
||||||
|
Type = PlayerEventType.Shield
|
||||||
|
Result = PlayerEventResult.Successful
|
||||||
|
Timestamp = DateTime.UtcNow
|
||||||
|
Adversary = DiscordPlayer.empty
|
||||||
|
}
|
||||||
|
do! DbService.updatePlayer <| { player with Events = Array.append [| defense |] player.Events }
|
||||||
let builder = DiscordMessageBuilder()
|
let builder = DiscordMessageBuilder()
|
||||||
builder.WithContent($"{ctx.GetDiscordMember().Username} has protected their system!") |> ignore
|
builder.WithContent($"{ctx.GetDiscordMember().Username} has protected their system!") |> ignore
|
||||||
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle)
|
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle)
|
||||||
|
@ -14,8 +14,8 @@ module Commands =
|
|||||||
|
|
||||||
{ DiscordId = membr
|
{ DiscordId = membr
|
||||||
Name = nickname
|
Name = nickname
|
||||||
Arsenal = [| hack ; shield |]
|
Inventory = [| hack ; shield |]
|
||||||
Actions = [||]
|
Events = [||]
|
||||||
XP = 0
|
XP = 0
|
||||||
Achievements = [||]
|
Achievements = [||]
|
||||||
Traits = PlayerTraits.empty
|
Traits = PlayerTraits.empty
|
||||||
|
24
Bot/Store.fs
24
Bot/Store.fs
@ -9,22 +9,22 @@ open Degenz
|
|||||||
open Degenz.Messaging
|
open Degenz.Messaging
|
||||||
|
|
||||||
let checkHasSufficientFunds (item : BattleItem) player =
|
let checkHasSufficientFunds (item : BattleItem) player =
|
||||||
if player.Bank - item.Cost >= 0<GBT>
|
if player.Bank - item.Price >= 0<GBT>
|
||||||
then Ok player
|
then Ok player
|
||||||
else Error $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
|
else Error $"You do not have sufficient funds to buy this item! Current balance: {player.Bank} GBT"
|
||||||
|
|
||||||
let checkAlreadyOwnsItem (item : BattleItem) player =
|
let checkAlreadyOwnsItem (item : BattleItem) player =
|
||||||
if player.Arsenal |> Array.exists (fun w -> item.Id = w.Id)
|
if player.Inventory |> Array.exists (fun w -> item.Id = w.Id)
|
||||||
then Error $"You already own {item.Name}!"
|
then Error $"You already own {item.Name}!"
|
||||||
else Ok player
|
else Ok player
|
||||||
|
|
||||||
let checkSoldItemAlready (item : BattleItem) player =
|
let checkSoldItemAlready (item : BattleItem) player =
|
||||||
if player.Arsenal |> Array.exists (fun w -> item.Id = w.Id)
|
if player.Inventory |> Array.exists (fun w -> item.Id = w.Id)
|
||||||
then Ok player
|
then Ok player
|
||||||
else Error $"{item.Name} not found in your arsenal! Looks like you sold it already."
|
else Error $"{item.Name} not found in your arsenal! Looks like you sold it already."
|
||||||
|
|
||||||
let checkHasItemsInArsenal itemType player =
|
let checkHasItemsInArsenal itemType player =
|
||||||
if player.Arsenal |> Array.filter (fun i -> i.Type = itemType ) |> Array.length > 0
|
if player.Inventory |> Array.filter (fun i -> i.Type = itemType ) |> Array.length > 0
|
||||||
then Ok player
|
then Ok player
|
||||||
else Error $"You currently have no {itemType}s in your arsenal to sell!"
|
else Error $"You currently have no {itemType}s in your arsenal to sell!"
|
||||||
|
|
||||||
@ -50,8 +50,8 @@ let handleBuyItem (ctx : IDiscordContext) itemId =
|
|||||||
|> checkHasSufficientFunds item
|
|> checkHasSufficientFunds item
|
||||||
>>= checkAlreadyOwnsItem item
|
>>= checkAlreadyOwnsItem item
|
||||||
|> handleResultWithResponse ctx (fun player -> async {
|
|> handleResultWithResponse ctx (fun player -> async {
|
||||||
let newBalance = player.Bank - item.Cost
|
let newBalance = player.Bank - item.Price
|
||||||
let p = { player with Bank = newBalance ; Arsenal = Array.append [| item |] player.Arsenal }
|
let p = { player with Bank = newBalance ; Inventory = Array.append [| item |] player.Inventory }
|
||||||
do! DbService.updatePlayer p
|
do! DbService.updatePlayer p
|
||||||
do! sendFollowUpMessage ctx $"Successfully purchased {item.Name}! You now have {newBalance} 💰$GBT remaining"
|
do! sendFollowUpMessage ctx $"Successfully purchased {item.Name}! You now have {newBalance} 💰$GBT remaining"
|
||||||
})
|
})
|
||||||
@ -65,15 +65,15 @@ let handleSell (ctx : IDiscordContext) itemId =
|
|||||||
|> handleResultWithResponse ctx (fun player -> async {
|
|> handleResultWithResponse ctx (fun player -> async {
|
||||||
let updatedPlayer = {
|
let updatedPlayer = {
|
||||||
player with
|
player with
|
||||||
Bank = player.Bank + item.Cost
|
Bank = player.Bank + item.Price
|
||||||
Arsenal = player.Arsenal |> Array.filter (fun i -> i.Id <> itemId)
|
Inventory = player.Inventory |> Array.filter (fun i -> i.Id <> itemId)
|
||||||
Actions =
|
Events =
|
||||||
if item.Type = ItemType.Shield
|
if item.Type = ItemType.Shield
|
||||||
then player.Actions |> Array.filter (fun a -> a.ActionId <> itemId)
|
then player.Events |> Array.filter (fun a -> a.ItemId <> itemId)
|
||||||
else player.Actions
|
else player.Events
|
||||||
}
|
}
|
||||||
do! DbService.updatePlayer updatedPlayer
|
do! DbService.updatePlayer updatedPlayer
|
||||||
do! sendFollowUpMessage ctx $"Sold {item.Type} {item.Name} for {item.Cost}! Current Balance: {updatedPlayer.Bank}"
|
do! sendFollowUpMessage ctx $"Sold {item.Type} {item.Name} for {item.Price}! Current Balance: {updatedPlayer.Bank}"
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
33
Bot/Thief.fs
33
Bot/Thief.fs
@ -7,11 +7,6 @@ open DSharpPlus.Entities
|
|||||||
open DSharpPlus.SlashCommands
|
open DSharpPlus.SlashCommands
|
||||||
open Degenz.Messaging
|
open Degenz.Messaging
|
||||||
|
|
||||||
[<Literal>]
|
|
||||||
let StealActionId = 12
|
|
||||||
[<Literal>]
|
|
||||||
let VictimDefenseActionId = 12
|
|
||||||
|
|
||||||
let ThiefCooldown = TimeSpan.FromMinutes(1)
|
let ThiefCooldown = TimeSpan.FromMinutes(1)
|
||||||
let VictimRecovery = TimeSpan.FromHours(6)
|
let VictimRecovery = TimeSpan.FromHours(6)
|
||||||
|
|
||||||
@ -89,8 +84,8 @@ let getResultEmbed targetName result =
|
|||||||
let checkVictimStealingCooldown defender attacker =
|
let checkVictimStealingCooldown defender attacker =
|
||||||
defender
|
defender
|
||||||
|> Player.removeExpiredActions false
|
|> Player.removeExpiredActions false
|
||||||
|> Player.getDefenses
|
|> Player.getShieldEvents
|
||||||
|> Array.tryFind (fun act -> act.ActionId = VictimDefenseActionId)
|
|> Array.tryFind (fun pe -> pe.Type = PlayerEventType.Mugged)
|
||||||
|> function
|
|> function
|
||||||
| Some act ->
|
| Some act ->
|
||||||
let cooldown = VictimRecovery - (DateTime.UtcNow - act.Timestamp)
|
let cooldown = VictimRecovery - (DateTime.UtcNow - act.Timestamp)
|
||||||
@ -101,8 +96,8 @@ let checkVictimStealingCooldown defender attacker =
|
|||||||
// TODO: Look for ways to generalize checking for action cooldowns
|
// TODO: Look for ways to generalize checking for action cooldowns
|
||||||
let checkThiefCooldown attacker =
|
let checkThiefCooldown attacker =
|
||||||
attacker
|
attacker
|
||||||
|> Player.getAttacks
|
|> Player.getHackEvents
|
||||||
|> Array.tryFind (fun act -> act.ActionId = StealActionId)
|
|> Array.tryFind (fun pe -> pe.Type = PlayerEventType.Steal)
|
||||||
|> function
|
|> function
|
||||||
| Some act ->
|
| Some act ->
|
||||||
if ThiefCooldown > (DateTime.UtcNow - act.Timestamp) then
|
if ThiefCooldown > (DateTime.UtcNow - act.Timestamp) then
|
||||||
@ -144,7 +139,7 @@ let handleSteal (ctx : IDiscordContext) =
|
|||||||
let split = ctx.GetInteractionId().Split("-")
|
let split = ctx.GetInteractionId().Split("-")
|
||||||
let answer = split.[1]
|
let answer = split.[1]
|
||||||
|
|
||||||
let handleYes player = async {
|
let handleYes (player : PlayerData) = async {
|
||||||
let targetId = uint64 split.[2]
|
let targetId = uint64 split.[2]
|
||||||
let targetName = split.[3]
|
let targetName = split.[3]
|
||||||
let chance = double split.[4]
|
let chance = double split.[4]
|
||||||
@ -154,7 +149,7 @@ let handleSteal (ctx : IDiscordContext) =
|
|||||||
|
|
||||||
let result = chance >= rand.NextDouble() , rand.Next(0,3) = 0
|
let result = chance >= rand.NextDouble() , rand.Next(0,3) = 0
|
||||||
let dp = { DiscordPlayer.Id = targetId ; DiscordPlayer.Name = targetName }
|
let dp = { DiscordPlayer.Id = targetId ; DiscordPlayer.Name = targetName }
|
||||||
let stealAction = { ActionId = StealActionId ; Type = Attack { AttackResult.Result = false ; AttackResult.Target = dp } ; Timestamp = DateTime.UtcNow }
|
let stealAction result = { ItemId = -1 ; Type = PlayerEventType.Steal ; Result = result ; Adversary = dp ; Timestamp = DateTime.UtcNow }
|
||||||
// TODO: Send event to the hall of privacy
|
// TODO: Send event to the hall of privacy
|
||||||
// TODO: We need to check if the player is on cooldown
|
// TODO: We need to check if the player is on cooldown
|
||||||
match result with
|
match result with
|
||||||
@ -166,24 +161,24 @@ let handleSteal (ctx : IDiscordContext) =
|
|||||||
do! Messaging.sendFollowUpEmbed ctx (embed.Build())
|
do! Messaging.sendFollowUpEmbed ctx (embed.Build())
|
||||||
match! DbService.tryFindPlayer targetId with
|
match! DbService.tryFindPlayer targetId with
|
||||||
| Some t ->
|
| Some t ->
|
||||||
let action = { ActionId = VictimDefenseActionId ; Type = Defense ; Timestamp = DateTime.UtcNow }
|
let mugged = { ItemId = -1 ; Type = PlayerEventType.Mugged ; Result = PlayerEventResult.Failed ; Adversary = player.basicPlayer ; Timestamp = DateTime.UtcNow }
|
||||||
let actions = t |> Player.removeExpiredActions false |> fun p -> Array.append [| action |] p.Actions
|
let actions = t |> Player.removeExpiredActions false |> fun p -> Array.append [| mugged |] p.Events
|
||||||
do! DbService.updatePlayer { t with Bank = max (t.Bank - prize) 0<GBT> ; Actions = actions }
|
do! DbService.updatePlayer { t with Bank = max (t.Bank - prize) 0<GBT> ; Events = actions }
|
||||||
| None -> ()
|
| None -> ()
|
||||||
let action = { ActionId = StealActionId ; Type = Attack { AttackResult.Result = true ; AttackResult.Target = dp } ; Timestamp = DateTime.UtcNow }
|
let stole = { ItemId = -1 ; Type = PlayerEventType.Steal ; Result = PlayerEventResult.Successful ; Adversary = dp ; Timestamp = DateTime.UtcNow }
|
||||||
let actions = player |> Player.removeExpiredActions false |> fun p -> Array.append [| action |] p.Actions
|
let actions = player |> Player.removeExpiredActions false |> fun p -> Array.append [| stole |] p.Events
|
||||||
do! DbService.updatePlayer { player with Bank = player.Bank + prize ; XP = player.XP + xp ; Actions = actions }
|
do! DbService.updatePlayer { player with Bank = player.Bank + prize ; XP = player.XP + xp ; Events = actions }
|
||||||
let newLevel = XP.getLevel (player.XP + xp)
|
let newLevel = XP.getLevel (player.XP + xp)
|
||||||
// if XP.getLevel player.XP < newLevel then
|
// if XP.getLevel player.XP < newLevel then
|
||||||
do! Async.Sleep 2000
|
do! Async.Sleep 2000
|
||||||
do! ctx.FollowUp (XP.getRewardsEmbed 1 player) |> Async.AwaitTask
|
do! ctx.FollowUp (XP.getRewardsEmbed 1 player) |> Async.AwaitTask
|
||||||
| false , false ->
|
| false , false ->
|
||||||
let embed = getResultEmbed targetName VictimRanAway
|
let embed = getResultEmbed targetName VictimRanAway
|
||||||
do! DbService.updatePlayer { player with Actions = Array.append [| stealAction |] player.Actions }
|
do! DbService.updatePlayer { player with Events = Array.append [| stealAction PlayerEventResult.Neutral |] player.Events }
|
||||||
do! Messaging.sendFollowUpEmbed ctx (embed.Build())
|
do! Messaging.sendFollowUpEmbed ctx (embed.Build())
|
||||||
| false , true ->
|
| false , true ->
|
||||||
let embed = getResultEmbed targetName WentToPrison
|
let embed = getResultEmbed targetName WentToPrison
|
||||||
do! DbService.updatePlayer { player with Actions = Array.append [| stealAction |] player.Actions }
|
do! DbService.updatePlayer { player with Events = Array.append [| stealAction PlayerEventResult.Neutral |] player.Events }
|
||||||
do! Messaging.sendFollowUpEmbed ctx (embed.Build())
|
do! Messaging.sendFollowUpEmbed ctx (embed.Build())
|
||||||
do! Async.Sleep 2000
|
do! Async.Sleep 2000
|
||||||
let role = ctx.GetGuild().GetRole(GuildEnvironment.rolePrisoner)
|
let role = ctx.GetGuild().GetRole(GuildEnvironment.rolePrisoner)
|
||||||
|
@ -53,7 +53,7 @@ let defend (ctx : IDiscordContext) =
|
|||||||
Game.executePlayerAction ctx (fun player -> async {
|
Game.executePlayerAction ctx (fun player -> async {
|
||||||
let playerWithShields =
|
let playerWithShields =
|
||||||
match Player.getShields player with
|
match Player.getShields player with
|
||||||
| [||] -> { player with Arsenal = [| defaultShield |] }
|
| [||] -> { player with Inventory = [| defaultShield |] }
|
||||||
| _ -> player
|
| _ -> player
|
||||||
|
|
||||||
let embed = Embeds.pickDefense "Trainer-2" playerWithShields true
|
let embed = Embeds.pickDefense "Trainer-2" playerWithShields true
|
||||||
@ -78,12 +78,11 @@ let handleDefense (ctx : IDiscordContext) =
|
|||||||
let embed = Embeds.responseCreatedShield shield
|
let embed = Embeds.responseCreatedShield shield
|
||||||
do! ctx.FollowUp embed |> Async.AwaitTask
|
do! ctx.FollowUp embed |> Async.AwaitTask
|
||||||
do! Async.Sleep 4000
|
do! Async.Sleep 4000
|
||||||
let weakHack = Game.getGoodAgainst shield.Class
|
do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **VIRUS**"
|
||||||
do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **{snd weakHack}**"
|
|
||||||
do! Async.Sleep 5000
|
do! Async.Sleep 5000
|
||||||
do! sendMessage' $"❌ HACKING FAILED!\n\n{player.Name} defended hack from <@{GuildEnvironment.botIdHackerBattle}>!"
|
do! sendMessage' $"❌ HACKING FAILED!\n\n{player.Name} defended hack from <@{GuildEnvironment.botIdHackerBattle}>!"
|
||||||
do! Async.Sleep 4000
|
do! Async.Sleep 4000
|
||||||
do! sendFollowUpMessageWithButton ctx (handleDefenseMsg shieldId (snd weakHack))
|
do! sendFollowUpMessageWithButton ctx (handleDefenseMsg shieldId "VIRUS")
|
||||||
|
|
||||||
})
|
})
|
||||||
let handleTrainerStep3 (ctx : IDiscordContext) =
|
let handleTrainerStep3 (ctx : IDiscordContext) =
|
||||||
@ -110,7 +109,7 @@ let attack (target : DiscordUser) (ctx : IDiscordContext) =
|
|||||||
| true ->
|
| true ->
|
||||||
let playerWithAttacks =
|
let playerWithAttacks =
|
||||||
match Player.getHacks player with
|
match Player.getHacks player with
|
||||||
| [||] -> { player with Arsenal = [| defaultHack |] }
|
| [||] -> { player with Inventory = [| defaultHack |] }
|
||||||
| _ -> player
|
| _ -> player
|
||||||
let bot = { player with DiscordId = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
|
let bot = { player with DiscordId = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
|
||||||
let embed = Embeds.pickHack "Trainer-4" playerWithAttacks bot true
|
let embed = Embeds.pickHack "Trainer-4" playerWithAttacks bot true
|
||||||
@ -154,14 +153,14 @@ let handleAttack (ctx : IDiscordContext) =
|
|||||||
let rand = System.Random(System.Guid.NewGuid().GetHashCode())
|
let rand = System.Random(System.Guid.NewGuid().GetHashCode())
|
||||||
let freeHack = Armory.hacks.[rand.Next(0, 3)]
|
let freeHack = Armory.hacks.[rand.Next(0, 3)]
|
||||||
let freeShield = Armory.shields.[rand.Next(0, 3)]
|
let freeShield = Armory.shields.[rand.Next(0, 3)]
|
||||||
let hackMoney = if hasHacks then defaultHack.Cost else 0<GBT>
|
let hackMoney = if hasHacks then defaultHack.Price else 0<GBT>
|
||||||
let shieldMoney = if hasShields then defaultShield.Cost else 0<GBT>
|
let shieldMoney = if hasShields then defaultShield.Price else 0<GBT>
|
||||||
|
|
||||||
let giftMsg =
|
let giftMsg =
|
||||||
match hasHacks , hasShields with
|
match hasHacks , hasShields with
|
||||||
| true , true -> $"I'm going to give you these {hackMoney + shieldMoney} 💰$GBT"
|
| true , true -> $"I'm going to give you these {hackMoney + shieldMoney} 💰$GBT"
|
||||||
| false , true -> $"I'm going to gift you a hack, `{freeHack.Name}` and {defaultHack.Cost} 💰$GBT"
|
| false , true -> $"I'm going to gift you a hack, `{freeHack.Name}` and {defaultHack.Price} 💰$GBT"
|
||||||
| true , false -> $"I'm going to gift you a shield, `{freeShield.Name}` and {defaultHack.Cost} 💰$GBT"
|
| true , false -> $"I'm going to gift you a shield, `{freeShield.Name}` and {defaultHack.Price} 💰$GBT"
|
||||||
| false , false -> $"I'm going to gift you a hack,`{freeHack.Name}` and a shield, `{freeShield.Name}`"
|
| false , false -> $"I'm going to gift you a hack,`{freeHack.Name}` and a shield, `{freeShield.Name}`"
|
||||||
|
|
||||||
sb.Append(giftMsg) |> ignore
|
sb.Append(giftMsg) |> ignore
|
||||||
@ -171,27 +170,25 @@ let handleAttack (ctx : IDiscordContext) =
|
|||||||
let updatedPlayer = {
|
let updatedPlayer = {
|
||||||
player with
|
player with
|
||||||
Bank = player.Bank + hackMoney + shieldMoney
|
Bank = player.Bank + hackMoney + shieldMoney
|
||||||
Actions = [
|
Events = [
|
||||||
{ Action.Timestamp = System.DateTime.UtcNow
|
{ PlayerEvent.Timestamp = System.DateTime.UtcNow
|
||||||
Action.Type =
|
PlayerEvent.Adversary = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
|
||||||
Attack {
|
PlayerEvent.Type = PlayerEventType.Shield
|
||||||
Result = true
|
PlayerEvent.Result = PlayerEventResult.Successful
|
||||||
Target = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
|
PlayerEvent.ItemId = defaultHack.Id }
|
||||||
}
|
if not hasShields && Array.exists (fun act -> act.ItemId = freeShield.Id) player.Events |> not then {
|
||||||
ActionId = defaultHack.Id
|
PlayerEvent.Timestamp = System.DateTime.UtcNow
|
||||||
}
|
PlayerEvent.Adversary = { Id = GuildEnvironment.botIdHackerBattle ; Name = "Sensei" }
|
||||||
if not hasShields && Array.exists (fun act -> act.ActionId = freeShield.Id) player.Actions |> not then {
|
PlayerEvent.Type = PlayerEventType.Shield
|
||||||
Action.Timestamp = System.DateTime.UtcNow
|
PlayerEvent.Result = PlayerEventResult.Successful
|
||||||
Action.Type = Defense
|
PlayerEvent.ItemId = defaultHack.Id }
|
||||||
Action.ActionId = freeShield.Id
|
|
||||||
}
|
|
||||||
] |> Seq.toArray
|
] |> Seq.toArray
|
||||||
|> Array.append player.Actions
|
|> Array.append player.Events
|
||||||
Arsenal = [
|
Inventory = [
|
||||||
if not hasHacks then freeHack
|
if not hasHacks then freeHack
|
||||||
if not hasShields then freeShield
|
if not hasShields then freeShield
|
||||||
] |> Seq.toArray
|
] |> Seq.toArray
|
||||||
|> Array.append player.Arsenal
|
|> Array.append player.Inventory
|
||||||
}
|
}
|
||||||
do! DbService.updatePlayer updatedPlayer
|
do! DbService.updatePlayer updatedPlayer
|
||||||
do! sendFollowUpMessage ctx (sb.ToString())
|
do! sendFollowUpMessage ctx (sb.ToString())
|
||||||
|
@ -26,26 +26,6 @@ type PlayerEntry =
|
|||||||
XP : int
|
XP : int
|
||||||
Bank : int }
|
Bank : int }
|
||||||
|
|
||||||
let private actionToAttack (action : Action) (hack : AttackResult) =
|
|
||||||
{ ActionId = action.ActionId
|
|
||||||
Result = hack.Result
|
|
||||||
Target = hack.Target
|
|
||||||
Timestamp = action.Timestamp }
|
|
||||||
|
|
||||||
let private actionToDefense (action : Action) =
|
|
||||||
{ ActionId = action.ActionId
|
|
||||||
Timestamp = action.Timestamp }
|
|
||||||
|
|
||||||
let private attackToAction (attack : AttackAction) =
|
|
||||||
{ ActionId = attack.ActionId
|
|
||||||
Type = Attack { Target = attack.Target ; Result = attack.Result }
|
|
||||||
Timestamp = attack.Timestamp }
|
|
||||||
|
|
||||||
let private defenseToAction (action : DefenseAction) =
|
|
||||||
{ ActionId = action.ActionId
|
|
||||||
Type = Defense
|
|
||||||
Timestamp = action.Timestamp }
|
|
||||||
|
|
||||||
let private playerMap (player : PlayerData) = {
|
let private playerMap (player : PlayerData) = {
|
||||||
DiscordId = player.DiscordId
|
DiscordId = player.DiscordId
|
||||||
Name = player.Name
|
Name = player.Name
|
||||||
@ -60,13 +40,13 @@ let tryWithDefault (bson : BsonDocument) field (defaultValue : 'a) (map : BsonVa
|
|||||||
let private mapBack (bson : BsonDocument) : PlayerData =
|
let private mapBack (bson : BsonDocument) : PlayerData =
|
||||||
{ DiscordId = tryWithDefault bson "Player.DiscordId" 0uL (fun v -> v.AsInt64 |> uint64)
|
{ DiscordId = tryWithDefault bson "Player.DiscordId" 0uL (fun v -> v.AsInt64 |> uint64)
|
||||||
Name = tryWithDefault bson "Player.Name" "Empty" (fun v -> v.AsString)
|
Name = tryWithDefault bson "Player.Name" "Empty" (fun v -> v.AsString)
|
||||||
Arsenal =
|
Inventory =
|
||||||
tryWithDefault bson "Inventory" [||] (fun v ->
|
tryWithDefault bson "Inventory" [||] (fun v ->
|
||||||
v.AsBsonArray
|
v.AsBsonArray
|
||||||
|> Seq.map (fun (bv : BsonValue) -> bv.AsInt32)
|
|> Seq.map (fun (bv : BsonValue) -> bv.AsInt32)
|
||||||
|> Seq.map (fun w -> Armory.battleItems |> Array.find (fun w' -> w = w'.Id))
|
|> Seq.map (fun w -> Armory.battleItems |> Array.find (fun w' -> w = w'.Id))
|
||||||
|> Seq.toArray)
|
|> Seq.toArray)
|
||||||
Actions = tryWithDefault bson "Events" [||] (fun _ -> [||])
|
Events = tryWithDefault bson "Events" [||] (fun _ -> [||])
|
||||||
Traits = tryWithDefault bson "Traits" PlayerTraits.empty (fun _ -> PlayerTraits.empty)
|
Traits = tryWithDefault bson "Traits" PlayerTraits.empty (fun _ -> PlayerTraits.empty)
|
||||||
Achievements = tryWithDefault bson "Achievements" [||] (fun _ -> [||])
|
Achievements = tryWithDefault bson "Achievements" [||] (fun _ -> [||])
|
||||||
XP = tryWithDefault bson "XP" 0 (fun _ -> 0)
|
XP = tryWithDefault bson "XP" 0 (fun _ -> 0)
|
||||||
@ -96,9 +76,9 @@ let updatePlayer (player : PlayerData) =
|
|||||||
let update = Builders<BsonDocument>.Update
|
let update = Builders<BsonDocument>.Update
|
||||||
.Set("Player", playerMap player)
|
.Set("Player", playerMap player)
|
||||||
.AddToSet("Traits", player.Traits)
|
.AddToSet("Traits", player.Traits)
|
||||||
.AddToSet("Events", player.Actions)
|
.AddToSet("Events", player.Events)
|
||||||
.AddToSet("Achievements", player.Achievements)
|
.AddToSet("Achievements", player.Achievements)
|
||||||
.AddToSet("Inventory", player.Arsenal)
|
.AddToSet("Inventory", player.Inventory)
|
||||||
return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
|
return! players.UpdateOneAsync(filter, update) |> Async.AwaitTask |> Async.Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,11 +36,6 @@ module Types =
|
|||||||
[<Measure>]
|
[<Measure>]
|
||||||
type GBT
|
type GBT
|
||||||
|
|
||||||
type BattleClass =
|
|
||||||
| Network
|
|
||||||
| Exploit
|
|
||||||
| Penetration
|
|
||||||
|
|
||||||
type HackId =
|
type HackId =
|
||||||
| Virus = 0
|
| Virus = 0
|
||||||
| RemoteAccess = 1
|
| RemoteAccess = 1
|
||||||
@ -58,9 +53,8 @@ module Types =
|
|||||||
type BattleItem = {
|
type BattleItem = {
|
||||||
Id : int
|
Id : int
|
||||||
Name : string
|
Name : string
|
||||||
Cost : int<GBT>
|
Price : int<GBT>
|
||||||
Type : ItemType
|
Type : ItemType
|
||||||
Class : BattleClass
|
|
||||||
Power : int
|
Power : int
|
||||||
Cooldown : int<mins>
|
Cooldown : int<mins>
|
||||||
}
|
}
|
||||||
@ -71,51 +65,49 @@ module Types =
|
|||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type DiscordPlayer = { Id: uint64; Name: string }
|
type DiscordPlayer = { Id: uint64; Name: string }
|
||||||
|
with static member empty = { Id = 0uL ; Name = "None" }
|
||||||
|
|
||||||
|
type PlayerEventResult =
|
||||||
|
| Successful = 0
|
||||||
|
| Neutral = 1
|
||||||
|
| Failed = 2
|
||||||
|
|
||||||
|
type PlayerEventType =
|
||||||
|
| Hack = 0
|
||||||
|
| Shield = 1
|
||||||
|
| Steal = 2
|
||||||
|
| Mugged = 3
|
||||||
|
| Imprison = 3
|
||||||
|
| Imprisoned = 3
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type AttackResult = {
|
type PlayerEvent =
|
||||||
Result : bool
|
{ Type : PlayerEventType
|
||||||
Target : DiscordPlayer
|
Result : PlayerEventResult
|
||||||
}
|
Adversary : DiscordPlayer
|
||||||
|
ItemId : int
|
||||||
type ActionType =
|
|
||||||
| Attack of AttackResult
|
|
||||||
| Defense
|
|
||||||
|
|
||||||
[<CLIMutable>]
|
|
||||||
type Action =
|
|
||||||
{ ActionId : int
|
|
||||||
Type : ActionType
|
|
||||||
Timestamp : DateTime }
|
Timestamp : DateTime }
|
||||||
|
|
||||||
type StatAmount = int
|
|
||||||
type XPAmount = int
|
|
||||||
|
|
||||||
type AttributeId =
|
|
||||||
| Strength = 0
|
|
||||||
| Cunning = 1
|
|
||||||
|
|
||||||
type PlayerTraits = {
|
type PlayerTraits = {
|
||||||
Strength : int
|
Strength : int
|
||||||
Focus : int
|
Focus : int
|
||||||
|
Luck : int
|
||||||
|
Charisma : int
|
||||||
}
|
}
|
||||||
with static member empty = { Strength = 0 ; Focus = 0 }
|
with static member empty = { Strength = 0 ; Focus = 0 ; Luck = 0 ; Charisma = 0 }
|
||||||
|
|
||||||
type PlayerXP = {
|
|
||||||
Amount : XPAmount
|
|
||||||
}
|
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type PlayerData = {
|
type PlayerData = {
|
||||||
DiscordId : uint64
|
DiscordId : uint64
|
||||||
Name : string
|
Name : string
|
||||||
Arsenal : BattleItem array
|
Inventory : BattleItem array
|
||||||
Actions : Action array
|
Events : PlayerEvent array
|
||||||
Traits : PlayerTraits
|
Traits : PlayerTraits
|
||||||
Achievements : string array
|
Achievements : string array
|
||||||
XP : int
|
XP : int
|
||||||
Bank : int<GBT>
|
Bank : int<GBT>
|
||||||
}
|
}
|
||||||
|
with member this.basicPlayer = { Id = this.DiscordId ; Name = this.Name }
|
||||||
|
|
||||||
module Armory =
|
module Armory =
|
||||||
let battleItems =
|
let battleItems =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user