Another pass on item modeling
This commit is contained in:
parent
8a57d3305e
commit
f01fc28a0c
@ -28,13 +28,13 @@ let getItemGif id =
|
|||||||
| ItemId.Cypher -> "https://s10.gifyu.com/images/Cypher-Smaller.gif"
|
| ItemId.Cypher -> "https://s10.gifyu.com/images/Cypher-Smaller.gif"
|
||||||
| _ -> hackGif
|
| _ -> hackGif
|
||||||
|
|
||||||
let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerData) items ignoreCooldown =
|
let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerData) (items : Inventory) ignoreCooldown =
|
||||||
items
|
items
|
||||||
|> List.map (fun item ->
|
|> List.map (fun item ->
|
||||||
let action =
|
let action =
|
||||||
player.Events
|
player.Events
|
||||||
|> List.tryFind (fun i ->
|
|> List.tryFind (fun event ->
|
||||||
match i.Type with
|
match event.Type with
|
||||||
| Hacking h -> h.HackId = item.Id && h.IsInstigator
|
| Hacking h -> h.HackId = item.Id && h.IsInstigator
|
||||||
| Shielding id -> id = item.Id
|
| Shielding id -> id = item.Id
|
||||||
| _ -> false)
|
| _ -> false)
|
||||||
@ -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.Inventory |> Inventory.filterByShields
|
let shieldItems = player.Inventory |> Inventory.getItemsByType ItemType.Shield
|
||||||
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 shield in Inventory.getShieldItems player.Inventory do
|
for shield in Inventory.getShields player.Inventory do
|
||||||
let hours = TimeSpan.FromMinutes(int shield.Cooldown).TotalHours
|
let hours = TimeSpan.FromMinutes(int shield.Cooldown).TotalHours
|
||||||
let against = WeaponClass.getGoodAgainst(shield.Class) |> snd
|
let against = WeaponClass.getGoodAgainst(shield.Class) |> snd
|
||||||
embed.AddField(shield.Name, $"Active {hours} hours\nDefeats {against}", true) |> ignore
|
embed.AddField(shield.Item.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.Inventory |> Inventory.filterByHacks
|
let hackItems = attacker.Inventory |> Inventory.getItemsByType ItemType.Hack
|
||||||
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,9 +77,9 @@ 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 hack in Inventory.getHackItems attacker.Inventory do
|
for hack in Inventory.getHacks attacker.Inventory do
|
||||||
let amount = if hack.Power > int defender.Bank then int defender.Bank else hack.Power
|
let amount = if hack.Power > int defender.Bank then int defender.Bank else hack.Power
|
||||||
embed.AddField(hack.Name, $"Cooldown {hack.Cooldown} mins\nExtract {amount} $GBT", true) |> ignore
|
embed.AddField(hack.Item.Name, $"Cooldown {hack.Cooldown} mins\nExtract {amount} $GBT", true) |> ignore
|
||||||
|
|
||||||
DiscordFollowupMessageBuilder()
|
DiscordFollowupMessageBuilder()
|
||||||
.AddComponents(buttons)
|
.AddComponents(buttons)
|
||||||
@ -89,9 +89,9 @@ let pickHack actionId attacker defender isTrainer =
|
|||||||
let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : HackItem) =
|
let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : HackItem) =
|
||||||
let embed =
|
let embed =
|
||||||
DiscordEmbedBuilder()
|
DiscordEmbedBuilder()
|
||||||
.WithImageUrl(getItemGif hack.Id)
|
.WithImageUrl(getItemGif hack.Item.Id)
|
||||||
.WithTitle("Hack Attack")
|
.WithTitle("Hack Attack")
|
||||||
.WithDescription($"You successfully hacked <@{targetId}> using {hack.Name}"
|
.WithDescription($"You successfully hacked <@{targetId}> using {hack.Item.Name}"
|
||||||
+ (if earnedMoney then $", and took {amountTaken} 💰$GBT from them!" else "!"))
|
+ (if earnedMoney then $", and took {amountTaken} 💰$GBT from them!" else "!"))
|
||||||
|
|
||||||
DiscordFollowupMessageBuilder()
|
DiscordFollowupMessageBuilder()
|
||||||
@ -99,9 +99,9 @@ let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : H
|
|||||||
.AsEphemeral(true)
|
.AsEphemeral(true)
|
||||||
|
|
||||||
let responseCreatedShield (shield : ShieldItem) =
|
let responseCreatedShield (shield : ShieldItem) =
|
||||||
let embed = DiscordEmbedBuilder().WithImageUrl(getItemGif shield.Id)
|
let embed = DiscordEmbedBuilder().WithImageUrl(getItemGif shield.Item.Id)
|
||||||
embed.Title <- "Mounted Shield"
|
embed.Title <- "Mounted Shield"
|
||||||
embed.Description <- $"Mounted {shield.Name} shield for {TimeSpan.FromMinutes(int shield.Cooldown).TotalHours} hours"
|
embed.Description <- $"Mounted {shield.Item.Name} shield for {TimeSpan.FromMinutes(int shield.Cooldown).TotalHours} hours"
|
||||||
|
|
||||||
DiscordFollowupMessageBuilder()
|
DiscordFollowupMessageBuilder()
|
||||||
.AddEmbed(embed)
|
.AddEmbed(embed)
|
||||||
|
@ -3,102 +3,60 @@ namespace Degenz
|
|||||||
open System
|
open System
|
||||||
open DSharpPlus
|
open DSharpPlus
|
||||||
open DSharpPlus.Entities
|
open DSharpPlus.Entities
|
||||||
|
open Degenz
|
||||||
open Newtonsoft.Json
|
open Newtonsoft.Json
|
||||||
|
|
||||||
module Armory =
|
module Armory =
|
||||||
let weapons =
|
// let weapons : ItemDetails list= []
|
||||||
|
let weapons : ItemDetails list =
|
||||||
let file = System.IO.File.ReadAllText("Items.json")
|
let file = System.IO.File.ReadAllText("Items.json")
|
||||||
// let file = System.IO.File.ReadAllText("Bot/Items.json")
|
// let file = System.IO.File.ReadAllText("Bot/Items.json")
|
||||||
JsonConvert.DeserializeObject<Item array>(file)
|
JsonConvert.DeserializeObject<ItemDetails array>(file)
|
||||||
|> Array.toList
|
|> Array.toList
|
||||||
|
|
||||||
module Inventory =
|
module Inventory =
|
||||||
let itemToHack item power hackClass cooldown = {
|
let getItemsByType itemType inventory =
|
||||||
Id = item.Id
|
match itemType with
|
||||||
Name = item.Name
|
| ItemType.Hack -> inventory |> List.filter (fun item -> match item with Hack _ -> true | _ -> false)
|
||||||
Price = item.Price
|
| ItemType.Shield -> inventory |> List.filter (fun item -> match item with Shield _ -> true | _ -> false)
|
||||||
Power = power
|
| ItemType.Food -> inventory |> List.filter (fun item -> match item with Food _ -> true | _ -> false)
|
||||||
Class = hackClass
|
| ItemType.Accessory -> inventory |> List.filter (fun item -> match item with Accessory _ -> true | _ -> false)
|
||||||
Cooldown = cooldown
|
|
||||||
}
|
|
||||||
let itemToShield item hackClass cooldown = {
|
|
||||||
Id = item.Id
|
|
||||||
Name = item.Name
|
|
||||||
Price = item.Price
|
|
||||||
Class = hackClass
|
|
||||||
Cooldown = cooldown
|
|
||||||
}
|
|
||||||
let itemToFood item targetStat boostAmount = {
|
|
||||||
Id = item.Id
|
|
||||||
Name = item.Name
|
|
||||||
Price = item.Price
|
|
||||||
TargetStat = targetStat
|
|
||||||
BoostAmount = boostAmount
|
|
||||||
}
|
|
||||||
let hackToItem (hack : HackItem) = {
|
|
||||||
Id = hack.Id
|
|
||||||
Name = hack.Name
|
|
||||||
Price = hack.Price
|
|
||||||
Details = Hack (hack.Power, hack.Class, hack.Cooldown)
|
|
||||||
}
|
|
||||||
let shieldToItem (shield : ShieldItem) = {
|
|
||||||
Id = shield.Id
|
|
||||||
Name = shield.Name
|
|
||||||
Price = shield.Price
|
|
||||||
Details = Shield (shield.Class, shield.Cooldown)
|
|
||||||
}
|
|
||||||
|
|
||||||
let filterByHacks inventory =
|
let findItemById id (inventory : Inventory) = inventory |> List.find (fun item -> item.Id = id)
|
||||||
inventory |> List.filter (fun item -> match item.Details with Hack _ -> true | _ -> false)
|
|
||||||
let filterByShields inventory =
|
|
||||||
inventory |> List.filter (fun item -> match item.Details with Shield _ -> true | _ -> false)
|
|
||||||
let filterByWeapons inventory =
|
|
||||||
inventory |> List.filter (fun item -> match item.Details with Hack _ | Shield _ -> true | _ -> false)
|
|
||||||
let filterByFood inventory =
|
|
||||||
inventory |> List.filter (fun item -> match item.Details with Food _ -> true | _ -> false)
|
|
||||||
let filterByAccessories inventory =
|
|
||||||
inventory |> List.filter (fun item -> match item.Details with Accessory _ -> true | _ -> false)
|
|
||||||
|
|
||||||
let getHackItems inventory =
|
|
||||||
inventory
|
|
||||||
|> List.choose (fun item -> match item.Details 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.Details with Shield (cl,co) -> Some (itemToShield item cl co) | _ -> None)
|
|
||||||
|> List.sortBy (fun item -> item.Id)
|
|
||||||
let getFoodItems inventory =
|
|
||||||
inventory
|
|
||||||
|> List.choose (fun item -> match item.Details with Food(t,b) -> Some (itemToFood item t b) | _ -> None)
|
|
||||||
|> List.sortBy (fun item -> item.Id)
|
|
||||||
let findItemById id inventory = inventory |> List.find (fun item -> item.Id = id)
|
|
||||||
let tryFindItemById id inventory = inventory |> List.tryFind (fun item -> item.Id = id)
|
|
||||||
let findHackById id inventory =
|
let findHackById id inventory =
|
||||||
inventory |> getHackItems |> List.pick (fun item -> if item.Id = id then Some item else None)
|
inventory |> List.pick (fun item -> match item with | Hack h -> (if h.Item.Id = id then Some h else None) | _ -> None)
|
||||||
let findShieldById id inventory =
|
let findShieldById id inventory =
|
||||||
inventory |> getShieldItems |> List.pick (fun item -> if item.Id = id then Some item else None)
|
inventory |> List.pick (fun item -> match item with | Shield s -> (if s.Item.Id = id then Some s else None) | _ -> None)
|
||||||
let findFoodById id inventory =
|
let findFoodById id inventory =
|
||||||
inventory |> getFoodItems |> List.pick (fun item -> if item.Id = id then Some item else None)
|
inventory |> List.pick (fun item -> match item with | Food f -> (if f.Item.Id = id then Some f else None) | _ -> None)
|
||||||
let tryFindHackById id inventory =
|
let findAccessoryById id inventory =
|
||||||
inventory |> getHackItems |> List.tryFind (fun item -> item.Id = id)
|
inventory |> List.pick (fun item -> match item with | Accessory a -> (if a.Item.Id = id then Some a else None) | _ -> None)
|
||||||
let tryFindShieldById id inventory =
|
|
||||||
inventory |> getShieldItems |> List.tryFind (fun item -> item.Id = id)
|
let getHacks inventory =
|
||||||
|
inventory |> List.choose (fun item -> match item with | Hack h -> Some h | _ -> None)
|
||||||
|
let getShields inventory =
|
||||||
|
inventory |> List.choose (fun item -> match item with | Shield s -> Some s | _ -> None)
|
||||||
|
let getFoods inventory =
|
||||||
|
inventory |> List.choose (fun item -> match item with | Food f -> Some f | _ -> None)
|
||||||
|
let getAccessories inventory =
|
||||||
|
inventory |> List.choose (fun item -> match item with | Accessory a -> Some a | _ -> None)
|
||||||
|
|
||||||
module WeaponClass =
|
module WeaponClass =
|
||||||
let SameTargetAttackCooldown = System.TimeSpan.FromHours(1)
|
let SameTargetAttackCooldown = TimeSpan.FromHours(1)
|
||||||
|
|
||||||
let getClassButtonColor item =
|
let getClassButtonColor item =
|
||||||
match item.Details with
|
match ItemDetails.getClass item with
|
||||||
| Hack (_,0,_) | Shield (0,_) -> ButtonStyle.Danger
|
| 0 -> ButtonStyle.Danger
|
||||||
| Hack (_,1,_) | Shield (1,_) -> ButtonStyle.Primary
|
| 1 -> ButtonStyle.Primary
|
||||||
| Hack (_,2,_) | Shield (2,_) -> ButtonStyle.Success
|
| 2 -> ButtonStyle.Success
|
||||||
| _ -> ButtonStyle.Primary
|
| _ -> ButtonStyle.Primary
|
||||||
|
|
||||||
let getClassEmbedColor item =
|
let getClassEmbedColor item =
|
||||||
match item.Details with
|
match ItemDetails.getClass item with
|
||||||
| Hack (_,0,_) | Shield (0,_) -> DiscordColor.Red
|
| 0 -> DiscordColor.Red
|
||||||
| Hack (_,1,_) | Shield (1,_) -> DiscordColor.Blurple
|
| 1 -> DiscordColor.Blurple
|
||||||
| Hack (_,2,_) | Shield (2,_) -> DiscordColor.Green
|
| 2 -> DiscordColor.Green
|
||||||
| _ -> DiscordColor.Blurple
|
| _ -> DiscordColor.Blurple
|
||||||
|
|
||||||
let getGoodAgainst = function
|
let getGoodAgainst = function
|
||||||
@ -118,8 +76,8 @@ module Player =
|
|||||||
let actions =
|
let actions =
|
||||||
player.Events
|
player.Events
|
||||||
|> List.filter (fun (act : PlayerEvent) ->
|
|> List.filter (fun (act : PlayerEvent) ->
|
||||||
let cooldown = System.TimeSpan.FromMinutes(int act.Cooldown)
|
let cooldown = TimeSpan.FromMinutes(int act.Cooldown)
|
||||||
System.DateTime.UtcNow - act.Timestamp < cooldown)
|
DateTime.UtcNow - act.Timestamp < cooldown)
|
||||||
{ player with Events = actions }
|
{ 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> }
|
||||||
@ -138,14 +96,14 @@ module PlayerStats =
|
|||||||
// let hoursElapsed = (DateTime.UtcNow - lastRead).Hours
|
// let hoursElapsed = (DateTime.UtcNow - lastRead).Hours
|
||||||
// let totalDecay = float hoursElapsed * statConfig.BaseDecayRate
|
// let totalDecay = float hoursElapsed * statConfig.BaseDecayRate
|
||||||
let modMinMax =
|
let modMinMax =
|
||||||
let min = items |> List.sumBy (fun item -> match item.Details with | Accessory(_,floorBoost,_) -> floorBoost | _ -> 0)
|
let min = items |> List.sumBy (fun item -> match item with | Accessory a -> a.FloorBoost | _ -> 0)
|
||||||
let max = items |> List.sumBy (fun item -> match item.Details with | Accessory(_,_,ceilBoost) -> ceilBoost | _ -> 0)
|
let max = items |> List.sumBy (fun item -> match item with | Accessory a -> a.CeilBoost | _ -> 0)
|
||||||
Range.create (statConfig.BaseRange.Min + min) (statConfig.BaseRange.Max + max)
|
Range.create (statConfig.BaseRange.Min + min) (statConfig.BaseRange.Max + max)
|
||||||
let amountAfterDecay = modMinMax |> Range.constrain amount
|
let amountAfterDecay = modMinMax |> Range.constrain amount
|
||||||
{ Id = statId ; Amount = amountAfterDecay ; ModRange = modMinMax ; LastRead = DateTime.UtcNow }
|
{ Id = statId ; Amount = amountAfterDecay ; ModRange = modMinMax ; LastRead = DateTime.UtcNow }
|
||||||
|
|
||||||
module Arsenal =
|
module Arsenal =
|
||||||
let battleItemFormat (items : Item list) =
|
let battleItemFormat (items : ItemDetails list) =
|
||||||
match items with
|
match items with
|
||||||
| [] -> "None"
|
| [] -> "None"
|
||||||
| _ -> items |> List.map (fun item -> item.Name) |> String.concat ", "
|
| _ -> items |> List.map (fun item -> item.Name) |> String.concat ", "
|
||||||
@ -155,23 +113,23 @@ module Arsenal =
|
|||||||
| [] -> "None"
|
| [] -> "None"
|
||||||
| acts ->
|
| acts ->
|
||||||
acts
|
acts
|
||||||
|> List.map (fun act ->
|
|> List.map (fun event ->
|
||||||
match act.Type with
|
match event.Type with
|
||||||
| Hacking h ->
|
| Hacking h ->
|
||||||
let item = Armory.weapons |> Inventory.findHackById h.HackId
|
let item = Armory.weapons |> Inventory.findHackById h.HackId
|
||||||
let cooldown = Messaging.getTimeText false WeaponClass.SameTargetAttackCooldown act.Timestamp
|
let cooldown = Messaging.getTimeText false WeaponClass.SameTargetAttackCooldown event.Timestamp
|
||||||
$"Hacked {h.Adversary.Name} with {item.Name} {cooldown} ago"
|
$"Hacked {h.Adversary.Name} with {item.Item.Name} {cooldown} ago"
|
||||||
| Shielding id ->
|
| Shielding id ->
|
||||||
let item = Armory.weapons |> Inventory.findHackById id
|
let item = Armory.weapons |> Inventory.findShieldById id
|
||||||
let cooldown = Messaging.getTimeText true (System.TimeSpan.FromMinutes(int act.Cooldown)) act.Timestamp
|
let cooldown = Messaging.getTimeText true (TimeSpan.FromMinutes(int event.Cooldown)) event.Timestamp
|
||||||
$"{item.Name} Shield active for {cooldown}"
|
$"{item.Item.Name} Shield active for {cooldown}"
|
||||||
| _ -> "")
|
| _ -> "")
|
||||||
|> List.filter (System.String.IsNullOrWhiteSpace >> not)
|
|> List.filter (String.IsNullOrWhiteSpace >> not)
|
||||||
|> String.concat "\n"
|
|> String.concat "\n"
|
||||||
|
|
||||||
let statusFormat p =
|
let statusFormat p =
|
||||||
let hacks = Player.getHackEvents p
|
let hacks = Player.getHackEvents p
|
||||||
$"**Hacks:** {Inventory.filterByHacks p.Inventory |> battleItemFormat}\n
|
$"**Hacks:** {Inventory.getItemsByType ItemType.Hack p.Inventory |> battleItemFormat}\n
|
||||||
**Shields:** {Inventory.filterByShields p.Inventory |> battleItemFormat}\n
|
**Shields:** {Inventory.getItemsByType ItemType.Hack p.Inventory |> battleItemFormat}\n
|
||||||
**Hack Attacks:**\n{ hacks |> List.take (min hacks.Length 10) |> actionFormat}\n
|
**Hack Attacks:**\n{hacks |> List.take (min hacks.Length 10) |> actionFormat}\n
|
||||||
**Active Shields:**\n{Player.getShieldEvents p |> actionFormat}"
|
**Active Shields:**\n{Player.getShieldEvents p |> actionFormat}"
|
||||||
|
110
Bot/GameTypes.fs
110
Bot/GameTypes.fs
@ -82,40 +82,6 @@ type PlayerEvent =
|
|||||||
Cooldown : int<mins>
|
Cooldown : int<mins>
|
||||||
Timestamp : DateTime }
|
Timestamp : DateTime }
|
||||||
|
|
||||||
type HackItem = {
|
|
||||||
Id : int
|
|
||||||
Name : string
|
|
||||||
Price : int<GBT>
|
|
||||||
Power : int
|
|
||||||
Class : int
|
|
||||||
Cooldown : int<mins>
|
|
||||||
}
|
|
||||||
|
|
||||||
type ShieldItem = {
|
|
||||||
Id : int
|
|
||||||
Name : string
|
|
||||||
Price : int<GBT>
|
|
||||||
Class : int
|
|
||||||
Cooldown : int<mins>
|
|
||||||
}
|
|
||||||
|
|
||||||
type FoodItem = {
|
|
||||||
Id : int
|
|
||||||
Name : string
|
|
||||||
Price : int<GBT>
|
|
||||||
TargetStat : StatId
|
|
||||||
BoostAmount : int
|
|
||||||
}
|
|
||||||
|
|
||||||
type AccessoryItem = {
|
|
||||||
Id : int
|
|
||||||
Name : string
|
|
||||||
Price : int<GBT>
|
|
||||||
TargetStat : StatId
|
|
||||||
FloorBoost : int
|
|
||||||
CeilBoost : int
|
|
||||||
}
|
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
type ItemType =
|
type ItemType =
|
||||||
| Hack
|
| Hack
|
||||||
@ -123,20 +89,76 @@ type ItemType =
|
|||||||
| Food
|
| Food
|
||||||
| Accessory
|
| Accessory
|
||||||
|
|
||||||
type ItemDetails =
|
type Item = {
|
||||||
| Hack of power : int * hackClass : int * cooldown : int<mins>
|
|
||||||
| Shield of shieldClass : int * cooldown : int<mins>
|
|
||||||
| Food of targetStat : StatId * boostAmount : int
|
|
||||||
| Accessory of targetStat : StatId * floorBoost : int * ceilBoost : int
|
|
||||||
and Item = {
|
|
||||||
Id : int
|
Id : int
|
||||||
Name : string
|
Name : string
|
||||||
Price : int<GBT>
|
Price : int<GBT>
|
||||||
// Type : ItemType
|
|
||||||
Details : ItemDetails
|
|
||||||
}
|
}
|
||||||
and Inventory = Item list
|
|
||||||
and PlayerData = {
|
type HackItem = {
|
||||||
|
Power : int
|
||||||
|
Class : int
|
||||||
|
Cooldown : int<mins>
|
||||||
|
Item : Item
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShieldItem = {
|
||||||
|
Class : int
|
||||||
|
Cooldown : int<mins>
|
||||||
|
Item : Item
|
||||||
|
}
|
||||||
|
|
||||||
|
type FoodItem = {
|
||||||
|
TargetStat : StatId
|
||||||
|
BoostAmount : int
|
||||||
|
Item : Item
|
||||||
|
}
|
||||||
|
|
||||||
|
type AccessoryItem = {
|
||||||
|
TargetStat : StatId
|
||||||
|
FloorBoost : int
|
||||||
|
CeilBoost : int
|
||||||
|
Item : Item
|
||||||
|
}
|
||||||
|
|
||||||
|
type ItemDetails =
|
||||||
|
| Hack of HackItem
|
||||||
|
| Shield of ShieldItem
|
||||||
|
| Food of FoodItem
|
||||||
|
| Accessory of AccessoryItem
|
||||||
|
member this.Id =
|
||||||
|
match this with
|
||||||
|
| Hack i -> i.Item.Id
|
||||||
|
| Shield i -> i.Item.Id
|
||||||
|
| Food i -> i.Item.Id
|
||||||
|
| Accessory i -> i.Item.Id
|
||||||
|
member this.Name =
|
||||||
|
match this with
|
||||||
|
| Hack i -> i.Item.Name
|
||||||
|
| Shield i -> i.Item.Name
|
||||||
|
| Food i -> i.Item.Name
|
||||||
|
| Accessory i -> i.Item.Name
|
||||||
|
member this.Price =
|
||||||
|
match this with
|
||||||
|
| Hack i -> i.Item.Price
|
||||||
|
| Shield i -> i.Item.Price
|
||||||
|
| Food i -> i.Item.Price
|
||||||
|
| Accessory i -> i.Item.Price
|
||||||
|
member this.getItem =
|
||||||
|
match this with
|
||||||
|
| Hack i -> i.Item
|
||||||
|
| Shield i -> i.Item
|
||||||
|
| Food i -> i.Item
|
||||||
|
| Accessory i -> i.Item
|
||||||
|
static member getClass = function
|
||||||
|
| Hack i -> i.Class
|
||||||
|
| Shield i -> i.Class
|
||||||
|
| Food _ -> -1
|
||||||
|
| Accessory _ -> -1
|
||||||
|
|
||||||
|
type Inventory = ItemDetails list
|
||||||
|
|
||||||
|
type PlayerData = {
|
||||||
DiscordId : uint64
|
DiscordId : uint64
|
||||||
Name : string
|
Name : string
|
||||||
Inventory : Inventory
|
Inventory : Inventory
|
||||||
|
@ -44,7 +44,7 @@ let checkWeaponHasCooldown (weapon : Item) attacker =
|
|||||||
| None -> Ok attacker
|
| None -> Ok attacker
|
||||||
|
|
||||||
let checkHasEmptyHacks attacker =
|
let checkHasEmptyHacks attacker =
|
||||||
match Inventory.getHackItems 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.channelArmory}> and purchase one."
|
||||||
| _ -> Ok attacker
|
| _ -> Ok attacker
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ let runHackerBattle defender (hack : HackItem) =
|
|||||||
|> fun p -> p.Events
|
|> fun p -> p.Events
|
||||||
|> List.choose (fun event ->
|
|> List.choose (fun event ->
|
||||||
match event.Type with
|
match event.Type with
|
||||||
| Shielding id -> defender.Inventory |> Inventory.getShieldItems |> List.find (fun item -> item.Id = id) |> Some
|
| Shielding id -> defender.Inventory |> Inventory.getShields |> List.find (fun item -> item.Item.Id = id) |> Some
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
|> List.map (fun shield -> if hack.Class = shield.Class then Weak else Strong)
|
|> List.map (fun shield -> if hack.Class = shield.Class then Weak else Strong)
|
||||||
|> List.contains Weak
|
|> List.contains Weak
|
||||||
@ -84,7 +84,7 @@ let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerDa
|
|||||||
{ p with Events = attack::p.Events ; Bank = max (p.Bank + amount) 0<GBT> }
|
{ p with Events = attack::p.Events ; Bank = max (p.Bank + amount) 0<GBT> }
|
||||||
let event isDefenderEvent =
|
let event isDefenderEvent =
|
||||||
let hackEvent = {
|
let hackEvent = {
|
||||||
HackId = hack.Id
|
HackId = hack.Item.Id
|
||||||
Adversary = if isDefenderEvent then attacker.toDiscordPlayer else defender.toDiscordPlayer
|
Adversary = if isDefenderEvent then attacker.toDiscordPlayer else defender.toDiscordPlayer
|
||||||
IsInstigator = not isDefenderEvent
|
IsInstigator = not isDefenderEvent
|
||||||
Success = successfulHack
|
Success = successfulHack
|
||||||
@ -151,7 +151,6 @@ let handleAttack (ctx : IDiscordContext) =
|
|||||||
let tokens = ctx.GetInteractionId().Split("-")
|
let tokens = ctx.GetInteractionId().Split("-")
|
||||||
let hackId = int tokens.[1]
|
let hackId = int tokens.[1]
|
||||||
let hack = Armory.weapons |> Inventory.findHackById hackId
|
let hack = Armory.weapons |> 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 targetId
|
let! resultTarget = DbService.tryFindPlayer targetId
|
||||||
|
|
||||||
@ -160,8 +159,8 @@ let handleAttack (ctx : IDiscordContext) =
|
|||||||
do! attacker
|
do! attacker
|
||||||
|> Player.removeExpiredActions
|
|> Player.removeExpiredActions
|
||||||
|> checkAlreadyHackedTarget defender
|
|> checkAlreadyHackedTarget defender
|
||||||
>>= checkPlayerOwnsWeapon hackAsItem
|
>>= checkPlayerOwnsWeapon hack.Item
|
||||||
>>= checkWeaponHasCooldown hackAsItem
|
>>= checkWeaponHasCooldown hack.Item
|
||||||
|> function
|
|> function
|
||||||
| Ok atkr ->
|
| Ok atkr ->
|
||||||
runHackerBattle defender hack
|
runHackerBattle defender hack
|
||||||
@ -174,7 +173,7 @@ let handleAttack (ctx : IDiscordContext) =
|
|||||||
|
|
||||||
let defend (ctx : IDiscordContext) =
|
let defend (ctx : IDiscordContext) =
|
||||||
executePlayerAction ctx (fun player -> async {
|
executePlayerAction ctx (fun player -> async {
|
||||||
if player.Inventory |> Inventory.filterByShields |> List.length > 0 then
|
if player.Inventory |> Inventory.getShields |> 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
|
||||||
@ -188,12 +187,11 @@ let handleDefense (ctx : IDiscordContext) =
|
|||||||
let tokens = ctx.GetInteractionId().Split("-")
|
let tokens = ctx.GetInteractionId().Split("-")
|
||||||
let shieldId = int tokens.[1]
|
let shieldId = int tokens.[1]
|
||||||
let shield = Armory.weapons |> Inventory.findShieldById shieldId
|
let shield = Armory.weapons |> Inventory.findShieldById shieldId
|
||||||
let shieldAsItem = Inventory.shieldToItem shield
|
|
||||||
|
|
||||||
do! player
|
do! player
|
||||||
|> checkPlayerOwnsWeapon shieldAsItem
|
|> checkPlayerOwnsWeapon shield.Item
|
||||||
>>= checkPlayerHasShieldSlotsAvailable
|
>>= checkPlayerHasShieldSlotsAvailable
|
||||||
>>= checkWeaponHasCooldown shieldAsItem
|
>>= checkWeaponHasCooldown shield.Item
|
||||||
|> 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
|
||||||
@ -244,6 +242,37 @@ let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEve
|
|||||||
do! eventCtx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
|
do! eventCtx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let invite (ctx : IDiscordContext) =
|
||||||
|
task {
|
||||||
|
let channel = ctx.GetGuild().GetChannel(927449884204867664uL)
|
||||||
|
let invite = channel.CreateInviteAsync(reason = "I MEAN WHY NOT") |> Async.AwaitTask |> Async.RunSynchronously
|
||||||
|
|
||||||
|
printfn "The invite code is %s" invite.Code
|
||||||
|
|
||||||
|
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, DiscordInteractionResponseBuilder().AsEphemeral(true).WithContent($"https://discord.gg/{invite.Code}")) |> Async.AwaitTask
|
||||||
|
}
|
||||||
|
|
||||||
|
//let invite (ctx : IDiscordContext) =
|
||||||
|
// task {
|
||||||
|
// let code = Guid.NewGuid().ToString().Substring(0, 7)
|
||||||
|
//
|
||||||
|
//// let embed1 =
|
||||||
|
//// DiscordEmbedBuilder()
|
||||||
|
//// .WithImageUrl("https://pbs.twimg.com/profile_banners/1449270642340089856/1640071520/1500x500")
|
||||||
|
// let embed2 =
|
||||||
|
// DiscordEmbedBuilder()
|
||||||
|
// .WithDescription($"Send this invite to your friend, when they join, type the `/enter-code` slash command\n\n```{code}```")
|
||||||
|
// .WithImageUrl("https://pbs.twimg.com/profile_banners/1449270642340089856/1640071520/1500x500")
|
||||||
|
// .WithTitle("Invite Code")
|
||||||
|
//
|
||||||
|
// let msg =
|
||||||
|
// DiscordInteractionResponseBuilder()
|
||||||
|
// .AsEphemeral(true)
|
||||||
|
//// .AddEmbed(embed1)
|
||||||
|
// .AddEmbed(embed2)
|
||||||
|
//
|
||||||
|
// do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, msg)
|
||||||
|
// }
|
||||||
type HackerGame() =
|
type HackerGame() =
|
||||||
inherit ApplicationCommandModule ()
|
inherit ApplicationCommandModule ()
|
||||||
|
|
||||||
@ -267,6 +296,10 @@ type HackerGame() =
|
|||||||
do! Messaging.sendSimpleResponse ctx msg
|
do! Messaging.sendSimpleResponse ctx msg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[<SlashCommand("invite", "Invite user to this discord and earn rewards")>]
|
||||||
|
member this.CreateInvite (ctx : InteractionContext) =
|
||||||
|
invite (DiscordInteractionContext ctx)
|
||||||
|
|
||||||
[<SlashCommand("arsenal", "Get the Hacks and Shields you own, and which ones are active")>]
|
[<SlashCommand("arsenal", "Get the Hacks and Shields you own, and which ones are active")>]
|
||||||
member this.Arsenal (ctx : InteractionContext) =
|
member this.Arsenal (ctx : InteractionContext) =
|
||||||
enforceChannels (DiscordInteractionContext ctx) (Trainer.handleArsenal) arsenal
|
enforceChannels (DiscordInteractionContext ctx) (Trainer.handleArsenal) arsenal
|
||||||
|
@ -15,27 +15,27 @@ let getBuyItemsEmbed (playerInventory : Inventory) (storeInventory : Inventory)
|
|||||||
storeInventory
|
storeInventory
|
||||||
|> List.map (fun item ->
|
|> List.map (fun item ->
|
||||||
let embed = DiscordEmbedBuilder()
|
let embed = DiscordEmbedBuilder()
|
||||||
match item.Details with
|
match item with
|
||||||
| Hack(power,_,cooldown) ->
|
| Hack hack ->
|
||||||
embed.AddField($"$GBT Reward |", string power, true)
|
embed.AddField($"$GBT Reward |", string hack.Power, true)
|
||||||
.AddField("Cooldown |", $"{TimeSpan.FromMinutes(int cooldown).Minutes} minutes", true)
|
.AddField("Cooldown |", $"{TimeSpan.FromMinutes(int hack.Cooldown).Minutes} minutes", true)
|
||||||
.WithThumbnail(Embeds.getItemIcon item.Id)
|
.WithThumbnail(Embeds.getItemIcon item.Id)
|
||||||
|> ignore
|
|> ignore
|
||||||
| Shield(shieldClass,cooldown) ->
|
| Shield shield ->
|
||||||
embed.AddField($"Strong against |", WeaponClass.getGoodAgainst shieldClass |> snd |> string, true)
|
embed.AddField($"Strong against |", WeaponClass.getGoodAgainst shield.Class |> snd |> string, true)
|
||||||
// .AddField($"Defensive Strength |", string item.Power, true)
|
// .AddField($"Defensive Strength |", string item.Power, true)
|
||||||
.AddField("Active For |", $"{TimeSpan.FromMinutes(int cooldown).Hours} hours", true)
|
.AddField("Active For |", $"{TimeSpan.FromMinutes(int shield.Cooldown).Hours} hours", true)
|
||||||
.WithThumbnail(Embeds.getItemIcon item.Id)
|
.WithThumbnail(Embeds.getItemIcon item.Id)
|
||||||
|> ignore
|
|> ignore
|
||||||
| Food(targetStat, boostAmount) ->
|
| Food food ->
|
||||||
embed.AddField($"Stat |", $"{targetStat}", true)
|
embed.AddField($"Stat |", $"{food.TargetStat}", true)
|
||||||
.AddField($"Amount |", $"+{boostAmount}", true) |> ignore
|
.AddField($"Amount |", $"+{food.BoostAmount}", true) |> ignore
|
||||||
| Accessory(targetStat, floorBoost, ceilBoost) ->
|
| Accessory accessory ->
|
||||||
embed.AddField($"Stat |", $"{targetStat}", true) |> ignore
|
embed.AddField($"Stat |", $"{accessory.TargetStat}", true) |> ignore
|
||||||
if floorBoost > 0 then
|
if accessory.FloorBoost > 0 then
|
||||||
embed.AddField($"Min Boost |", $"+{floorBoost}", true) |> ignore
|
embed.AddField($"Min Boost |", $"+{accessory.FloorBoost}", true) |> ignore
|
||||||
if ceilBoost > 0 then
|
if accessory.CeilBoost > 0 then
|
||||||
embed.AddField($"Max Boost |", $"+{ceilBoost}", true) |> ignore
|
embed.AddField($"Max Boost |", $"+{accessory.CeilBoost}", true) |> ignore
|
||||||
embed
|
embed
|
||||||
.AddField("Price 💰", (if item.Price = 0<GBT> then "Free" else $"{item.Price} $GBT"), true)
|
.AddField("Price 💰", (if item.Price = 0<GBT> then "Free" else $"{item.Price} $GBT"), true)
|
||||||
.WithColor(WeaponClass.getClassEmbedColor item)
|
.WithColor(WeaponClass.getClassEmbedColor item)
|
||||||
@ -53,7 +53,7 @@ let getBuyItemsEmbed (playerInventory : Inventory) (storeInventory : Inventory)
|
|||||||
.AddComponents(buttons)
|
.AddComponents(buttons)
|
||||||
.AsEphemeral(true)
|
.AsEphemeral(true)
|
||||||
|
|
||||||
let getSellEmbed (items : Item list) =
|
let getSellEmbed (items : ItemDetails list) =
|
||||||
let embeds , buttons =
|
let embeds , buttons =
|
||||||
items
|
items
|
||||||
|> List.map (fun item ->
|
|> List.map (fun item ->
|
||||||
@ -70,7 +70,7 @@ let getSellEmbed (items : Item list) =
|
|||||||
.AddComponents(buttons)
|
.AddComponents(buttons)
|
||||||
.AsEphemeral(true)
|
.AsEphemeral(true)
|
||||||
|
|
||||||
let getConsumeEmbed (items : Item list) =
|
let getConsumeEmbed (items : ItemDetails list) =
|
||||||
let embeds , buttons =
|
let embeds , buttons =
|
||||||
items
|
items
|
||||||
|> List.groupBy (fun item -> item.Id)
|
|> List.groupBy (fun item -> item.Id)
|
||||||
@ -78,7 +78,7 @@ let getConsumeEmbed (items : Item list) =
|
|||||||
let item = List.head items
|
let item = List.head items
|
||||||
let foodItem = Inventory.findFoodById itemId items
|
let foodItem = Inventory.findFoodById itemId items
|
||||||
DiscordEmbedBuilder()
|
DiscordEmbedBuilder()
|
||||||
.AddField($"{foodItem.Name}", $"Total {items.Length}\nBoosts {foodItem.TargetStat} +{foodItem.BoostAmount}", true)
|
.AddField($"{foodItem.Item.Name}", $"Total {items.Length}\nBoosts {foodItem.TargetStat} +{foodItem.BoostAmount}", true)
|
||||||
.WithTitle($"Food Items")
|
.WithTitle($"Food Items")
|
||||||
.WithColor(WeaponClass.getClassEmbedColor item)
|
.WithColor(WeaponClass.getClassEmbedColor item)
|
||||||
.Build()
|
.Build()
|
||||||
@ -130,8 +130,8 @@ let handleBuyItem (ctx : IDiscordContext) itemId =
|
|||||||
executePlayerAction ctx (fun player -> async {
|
executePlayerAction ctx (fun player -> async {
|
||||||
let item = Armory.weapons |> Inventory.findItemById itemId
|
let item = Armory.weapons |> Inventory.findItemById itemId
|
||||||
do! player
|
do! player
|
||||||
|> checkHasSufficientFunds item
|
|> checkHasSufficientFunds item.getItem
|
||||||
>>= checkAlreadyOwnsItem item
|
>>= checkAlreadyOwnsItem item.getItem
|
||||||
|> handleResultWithResponse ctx (fun player -> async {
|
|> handleResultWithResponse ctx (fun player -> async {
|
||||||
let newBalance = player.Bank - item.Price
|
let newBalance = player.Bank - item.Price
|
||||||
let p = { player with Bank = newBalance ; Inventory = item::player.Inventory }
|
let p = { player with Bank = newBalance ; Inventory = item::player.Inventory }
|
||||||
@ -145,7 +145,7 @@ let handleSell (ctx : IDiscordContext) itemId =
|
|||||||
let item = Armory.weapons |> Inventory.findItemById itemId
|
let item = Armory.weapons |> Inventory.findItemById itemId
|
||||||
do!
|
do!
|
||||||
player
|
player
|
||||||
|> checkSoldItemAlready item
|
|> checkSoldItemAlready item.getItem
|
||||||
|> handleResultWithResponse ctx (fun player -> async {
|
|> handleResultWithResponse ctx (fun player -> async {
|
||||||
let updatedPlayer = {
|
let updatedPlayer = {
|
||||||
player with
|
player with
|
||||||
@ -155,7 +155,7 @@ let handleSell (ctx : IDiscordContext) itemId =
|
|||||||
do!
|
do!
|
||||||
[ DbService.updatePlayer updatedPlayer |> Async.Ignore
|
[ DbService.updatePlayer updatedPlayer |> Async.Ignore
|
||||||
DbService.removeShieldEvent updatedPlayer.DiscordId itemId |> Async.Ignore
|
DbService.removeShieldEvent updatedPlayer.DiscordId itemId |> Async.Ignore
|
||||||
sendFollowUpMessage ctx $"Sold {item.Details} {item.Name} for {item.Price}! Current Balance: {updatedPlayer.Bank}" ]
|
sendFollowUpMessage ctx $"Sold {item.Name} for {item.Price}! Current Balance: {updatedPlayer.Bank}" ]
|
||||||
|> Async.Parallel
|
|> Async.Parallel
|
||||||
|> Async.Ignore
|
|> Async.Ignore
|
||||||
})
|
})
|
||||||
@ -202,10 +202,10 @@ type Store() =
|
|||||||
|
|
||||||
let checkChannel (ctx : IDiscordContext) =
|
let checkChannel (ctx : IDiscordContext) =
|
||||||
match ctx.GetChannel().Id with
|
match ctx.GetChannel().Id with
|
||||||
| id when id = GuildEnvironment.channelBackAlley -> buy Inventory.filterByHacks ctx
|
| id when id = GuildEnvironment.channelBackAlley -> buy (Inventory.getItemsByType ItemType.Hack) ctx
|
||||||
| id when id = GuildEnvironment.channelArmory -> buy Inventory.filterByShields ctx
|
| id when id = GuildEnvironment.channelArmory -> buy (Inventory.getItemsByType ItemType.Shield) ctx
|
||||||
| id when id = GuildEnvironment.channelMarket -> buy Inventory.filterByFood ctx
|
| id when id = GuildEnvironment.channelMarket -> buy (Inventory.getItemsByType ItemType.Food) ctx
|
||||||
| id when id = GuildEnvironment.channelAccessoryShop -> buy Inventory.filterByAccessories ctx
|
| id when id = GuildEnvironment.channelAccessoryShop -> buy (Inventory.getItemsByType ItemType.Accessory) ctx
|
||||||
| _ ->
|
| _ ->
|
||||||
task {
|
task {
|
||||||
let msg = $"This channel doesn't have any items to sell"
|
let msg = $"This channel doesn't have any items to sell"
|
||||||
@ -216,22 +216,22 @@ type Store() =
|
|||||||
member _.BuyItem (ctx : InteractionContext) = checkChannel (DiscordInteractionContext(ctx))
|
member _.BuyItem (ctx : InteractionContext) = checkChannel (DiscordInteractionContext(ctx))
|
||||||
|
|
||||||
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GoodBoyTokenz")>]
|
[<SlashCommand("buy-shield", "Purchase a hack shield so you can protect your GoodBoyTokenz")>]
|
||||||
member this.BuyShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy Inventory.filterByShields)
|
member this.BuyShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy (Inventory.getItemsByType ItemType.Shield))
|
||||||
|
|
||||||
[<SlashCommand("buy-food", "Purchase a food item to help boost your stats")>]
|
[<SlashCommand("buy-food", "Purchase a food item to help boost your stats")>]
|
||||||
member this.BuyFood (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy Inventory.filterByFood)
|
member this.BuyFood (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (buy (Inventory.getItemsByType ItemType.Food))
|
||||||
|
|
||||||
[<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" Inventory.filterByHacks)
|
member this.SellHack (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Hacks" (Inventory.getItemsByType ItemType.Hack))
|
||||||
|
|
||||||
[<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" Inventory.filterByShields)
|
member this.SellShield (ctx : InteractionContext) = enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" (Inventory.getItemsByType ItemType.Shield))
|
||||||
|
|
||||||
[<SlashCommand("consume", "Consume a food item")>]
|
[<SlashCommand("consume", "Consume a food item")>]
|
||||||
member this.Consume (ctx : InteractionContext) =
|
member this.Consume (ctx : InteractionContext) =
|
||||||
enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" Inventory.filterByShields)
|
enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" (Inventory.getItemsByType ItemType.Food))
|
||||||
|
|
||||||
[<SlashCommand("inventory", "Check your inventory")>]
|
// [<SlashCommand("inventory", "Check your inventory")>]
|
||||||
member this.Inventory (ctx : InteractionContext) =
|
// member this.Inventory (ctx : InteractionContext) =
|
||||||
enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" Inventory.filterByShields)
|
// enforceChannel (DiscordInteractionContext(ctx)) (sell "Shields" (Inventory.getItemsByType ItemType))
|
||||||
|
|
||||||
|
@ -19,10 +19,10 @@ let TrainerEvents = [
|
|||||||
Adversary = Sensei
|
Adversary = Sensei
|
||||||
Success = true
|
Success = true
|
||||||
IsInstigator = true
|
IsInstigator = true
|
||||||
HackId = defaultHack.Id } }
|
HackId = defaultHack.Item.Id } }
|
||||||
{ Timestamp = System.DateTime.UtcNow
|
{ Timestamp = System.DateTime.UtcNow
|
||||||
Cooldown = defaultShield.Cooldown
|
Cooldown = defaultShield.Cooldown
|
||||||
Type = Shielding defaultShield.Id }
|
Type = Shielding defaultShield.Item.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 - `{defaultShield.Name}`\n"
|
+ $"Type the `/shield` command now, then select - `{defaultShield.Item.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 = [ Inventory.shieldToItem defaultShield ] ; Name = name } true
|
let embed = Embeds.pickDefense "Trainer-2" { PlayerData.empty with Inventory = [ Shield 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 **{defaultHack.Name}**"
|
do! sendMessage' $"Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now with **{defaultHack.Item.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 defaultHack.Name)
|
do! sendFollowUpMessageWithButton ctx (handleDefenseMsg defaultHack.Item.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 `{defaultHack.Name}`")
|
+ $"Type the `/hack` command now, then choose me - <@{Sensei.Id}> as your target, and select `{defaultHack.Item.Name}`")
|
||||||
|
|
||||||
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
|
do! ctx.Respond(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask
|
||||||
} |> Async.StartAsTask :> Task
|
} |> Async.StartAsTask :> Task
|
||||||
@ -115,7 +115,7 @@ 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 player = { PlayerData.empty with Inventory = [ Hack 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" player bot true
|
let embed = Embeds.pickHack "Trainer-4" player bot true
|
||||||
|
|
||||||
@ -151,7 +151,7 @@ let handleHack (ctx : IDiscordContext) =
|
|||||||
do! DbService.addAchievement player.DiscordId trainerAchievement
|
do! DbService.addAchievement player.DiscordId trainerAchievement
|
||||||
|> Async.Ignore
|
|> Async.Ignore
|
||||||
|
|
||||||
sb.Append($"I'm going to gift you a hack,`{defaultHack.Name}` and a shield, `{defaultShield.Name}`") |> ignore
|
sb.Append($"I'm going to gift you a hack,`{defaultHack.Item.Name}` and a shield, `{defaultShield.Item.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
|
||||||
@ -168,13 +168,13 @@ let handleArsenal (ctx : IDiscordContext) =
|
|||||||
PlayerInteractions.executePlayerAction ctx (fun player -> async {
|
PlayerInteractions.executePlayerAction ctx (fun player -> async {
|
||||||
let hasStockWeapons =
|
let hasStockWeapons =
|
||||||
player.Inventory
|
player.Inventory
|
||||||
|> List.choose (fun item -> if item.Id = defaultHack.Id || item.Id = defaultShield.Id then Some item else None)
|
|> List.choose (fun item -> if item.Id = defaultHack.Item.Id || item.Id = defaultShield.Item.Id then Some item else None)
|
||||||
|> List.length > 0
|
|> 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 @ player.Events
|
Events = TrainerEvents @ player.Events
|
||||||
Inventory = Inventory.hackToItem defaultHack::Inventory.shieldToItem defaultShield::player.Inventory
|
Inventory = Hack defaultHack::Shield defaultShield::player.Inventory
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Player.removeExpiredActions player
|
Player.removeExpiredActions player
|
||||||
@ -191,7 +191,7 @@ let handleArsenal (ctx : IDiscordContext) =
|
|||||||
let! completed = DbService.checkHasAchievement player.DiscordId trainerAchievement
|
let! completed = DbService.checkHasAchievement player.DiscordId trainerAchievement
|
||||||
if not completed then
|
if not completed then
|
||||||
do! Async.Sleep 3000
|
do! Async.Sleep 3000
|
||||||
let rewards = [ $"{defaultHack.Name} Hack" ; $"{defaultShield.Name} Shield" ]
|
let rewards = [ $"{defaultHack.Item.Name} Hack" ; $"{defaultShield.Item.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
|
||||||
|
322
Bot/Items.json
322
Bot/Items.json
@ -1,177 +1,205 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Id": 0,
|
"Case": "Hack",
|
||||||
"Name": "Virus",
|
"Fields": [
|
||||||
"Price": 0,
|
{
|
||||||
"Type": {
|
"Power": 25,
|
||||||
"Case": "Hack",
|
"Class": 0,
|
||||||
"Fields": [
|
"Cooldown": 1,
|
||||||
25,
|
"Item": {
|
||||||
0,
|
"Id": 0,
|
||||||
1
|
"Name": "Virus",
|
||||||
]
|
"Price": 0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 1,
|
"Case": "Hack",
|
||||||
"Name": "Remote Access",
|
"Fields": [
|
||||||
"Price": 500,
|
{
|
||||||
"Type": {
|
"Power": 75,
|
||||||
"Case": "Hack",
|
"Class": 1,
|
||||||
"Fields": [
|
"Cooldown": 3,
|
||||||
75,
|
"Item": {
|
||||||
1,
|
"Id": 1,
|
||||||
3
|
"Name": "Remote Access",
|
||||||
]
|
"Price": 500
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 2,
|
"Case": "Hack",
|
||||||
"Name": "Worm",
|
"Fields": [
|
||||||
"Price": 5000,
|
{
|
||||||
"Type": {
|
"Power": 150,
|
||||||
"Case": "Hack",
|
"Class": 2,
|
||||||
"Fields": [
|
"Cooldown": 5,
|
||||||
150,
|
"Item": {
|
||||||
2,
|
"Id": 2,
|
||||||
5
|
"Name": "Worm",
|
||||||
]
|
"Price": 5000
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 6,
|
"Case": "Shield",
|
||||||
"Name": "Firewall",
|
"Fields": [
|
||||||
"Price": 0,
|
{
|
||||||
"Type": {
|
"Class": 0,
|
||||||
"Case": "Shield",
|
"Cooldown": 120,
|
||||||
"Fields": [
|
"Item": {
|
||||||
0,
|
"Id": 6,
|
||||||
120
|
"Name": "Firewall",
|
||||||
]
|
"Price": 0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 7,
|
"Case": "Shield",
|
||||||
"Name": "Encryption",
|
"Fields": [
|
||||||
"Price": 500,
|
{
|
||||||
"Type": {
|
"Class": 1,
|
||||||
"Case": "Shield",
|
"Cooldown": 240,
|
||||||
"Fields": [
|
"Item": {
|
||||||
1,
|
"Id": 7,
|
||||||
240
|
"Name": "Encryption",
|
||||||
]
|
"Price": 500
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 8,
|
"Case": "Shield",
|
||||||
"Name": "Cypher",
|
"Fields": [
|
||||||
"Price": 5000,
|
{
|
||||||
"Type": {
|
"Class": 2,
|
||||||
"Case": "Shield",
|
"Cooldown": 380,
|
||||||
"Fields": [
|
"Item": {
|
||||||
2,
|
"Id": 8,
|
||||||
380
|
"Name": "Cypher",
|
||||||
]
|
"Price": 5000
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 12,
|
"Case": "Food",
|
||||||
"Name": "Protein Powder",
|
"Fields": [
|
||||||
"Price": 50,
|
{
|
||||||
"Type": {
|
"TargetStat" : 0,
|
||||||
"Case": "Food",
|
"BoostAmount" : 30,
|
||||||
"Fields": [
|
"Item": {
|
||||||
0,
|
"Id": 12,
|
||||||
30
|
"Name": "Protein Powder",
|
||||||
]
|
"Price": 50
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 13,
|
"Case": "Food",
|
||||||
"Name": "Toro Loco",
|
"Fields": [
|
||||||
"Price": 50,
|
{
|
||||||
"Type": {
|
"TargetStat" : 1,
|
||||||
"Case": "Food",
|
"BoostAmount" : 30,
|
||||||
"Fields": [
|
"Item": {
|
||||||
1,
|
"Id": 13,
|
||||||
30
|
"Name": "Toro Loco",
|
||||||
]
|
"Price": 50
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 14,
|
"Case": "Food",
|
||||||
"Name": "Cigarettes",
|
"Fields": [
|
||||||
"Price": 50,
|
{
|
||||||
"Type": {
|
"TargetStat" : 2,
|
||||||
"Case": "Food",
|
"BoostAmount" : 30,
|
||||||
"Fields": [
|
"Item": {
|
||||||
2,
|
"Id": 14,
|
||||||
30
|
"Name": "Oldports Cigs",
|
||||||
]
|
"Price": 50
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 15,
|
"Case": "Food",
|
||||||
"Name": "Moon Pie",
|
"Fields": [
|
||||||
"Price": 50,
|
{
|
||||||
"Type": {
|
"TargetStat" : 3,
|
||||||
"Case": "Food",
|
"BoostAmount" : 30,
|
||||||
"Fields": [
|
"Item": {
|
||||||
3,
|
"Id": 15,
|
||||||
30
|
"Name": "Moon Pie",
|
||||||
]
|
"Price": 50
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 20,
|
"Case": "Accessory",
|
||||||
"Name": "Kettle Bell",
|
"Fields": [
|
||||||
"Price": 250,
|
{
|
||||||
"Type": {
|
"TargetStat" : 0,
|
||||||
"Case": "Accessory",
|
"FloorBoost" : 25,
|
||||||
"Fields": [
|
"CeilBoost" : 0,
|
||||||
0,
|
"Item": {
|
||||||
25,
|
"Id": 20,
|
||||||
0
|
"Name": "Kettlebell",
|
||||||
]
|
"Price": 250
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 21,
|
"Case": "Accessory",
|
||||||
"Name": "Headphones",
|
"Fields": [
|
||||||
"Price": 250,
|
{
|
||||||
"Type": {
|
"TargetStat" : 1,
|
||||||
"Case": "Accessory",
|
"FloorBoost" : 25,
|
||||||
"Fields": [
|
"CeilBoost" : 0,
|
||||||
1,
|
"Item": {
|
||||||
25,
|
"Id": 21,
|
||||||
0
|
"Name": "Headphones",
|
||||||
]
|
"Price": 250
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 22,
|
"Case": "Accessory",
|
||||||
"Name": "Silk Shirt",
|
"Fields": [
|
||||||
"Price": 250,
|
{
|
||||||
"Type": {
|
"TargetStat" : 2,
|
||||||
"Case": "Accessory",
|
"FloorBoost" : 0,
|
||||||
"Fields": [
|
"CeilBoost" : 25,
|
||||||
2,
|
"Item": {
|
||||||
0,
|
"Id": 22,
|
||||||
25
|
"Name": "Rolox Watch",
|
||||||
]
|
"Price": 250
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Id": 23,
|
"Case": "Accessory",
|
||||||
"Name": "Buddha Keychain",
|
"Fields": [
|
||||||
"Price": 250,
|
{
|
||||||
"Type": {
|
"TargetStat" : 3,
|
||||||
"Case": "Accessory",
|
"FloorBoost" : 0,
|
||||||
"Fields": [
|
"CeilBoost" : 25,
|
||||||
3,
|
"Item": {
|
||||||
0,
|
"Id": 23,
|
||||||
25
|
"Name": "Buddha Keychain",
|
||||||
]
|
"Price": 250
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user