Finish adding back the class system, fix messaging
This commit is contained in:
parent
34b24c29aa
commit
5df4ed9399
@ -40,13 +40,14 @@ let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerDat
|
||||
let action =
|
||||
player.Events
|
||||
|> Array.tryFind (fun i -> i.ItemId = item.Id)
|
||||
let btnColor = itemType
|
||||
match action , ignoreCooldown with
|
||||
| None , _ | Some _ , true ->
|
||||
DiscordButtonComponent(ButtonStyle.Primary, $"{actionId}-{item.Id}-{buttonInfo}-{player.Name}", $"{item.Name}")
|
||||
DiscordButtonComponent(Game.getClassButtonColor item.Class, $"{actionId}-{item.Id}-{buttonInfo}-{player.Name}", $"{item.Name}")
|
||||
| Some act , false ->
|
||||
let c = ((Armory.getItem act.ItemId).Cooldown)
|
||||
let time = Messaging.getShortTimeText (TimeSpan.FromMinutes(int c)) act.Timestamp
|
||||
DiscordButtonComponent(ButtonStyle.Primary, $"{actionId}-{item.Id}", $"{item.Name} ({time} left)", true))
|
||||
DiscordButtonComponent(Game.getClassButtonColor item.Class, $"{actionId}-{item.Id}", $"{item.Name} ({time} left)", true))
|
||||
|> Seq.cast<DiscordComponent>
|
||||
|
||||
let pickDefense actionId player isTrainer =
|
||||
@ -77,12 +78,13 @@ let pickHack actionId attacker defender isTrainer =
|
||||
.AddEmbed(embed.Build())
|
||||
.AsEphemeral true
|
||||
|
||||
let responseSuccessfulHack earnedMoney (targetId : uint64) (hack : Item) =
|
||||
let embed = DiscordEmbedBuilder()
|
||||
embed.ImageUrl <- getHackGif (enum<HackId>(hack.Id))
|
||||
embed.Title <- "Hack Attack"
|
||||
embed.Description <- $"You successfully hacked <@{targetId}> using {hack.Name}"
|
||||
+ (if earnedMoney then $", and stole {Game.HackPrize} 💰$GBT from them!" else "!")
|
||||
let responseSuccessfulHack earnedMoney (targetId : uint64) amountTaken (hack : Item) =
|
||||
let embed =
|
||||
DiscordEmbedBuilder()
|
||||
.WithImageUrl(getHackGif (enum<HackId>(hack.Id)))
|
||||
.WithTitle("Hack Attack")
|
||||
.WithDescription($"You successfully hacked <@{targetId}> using {hack.Name}"
|
||||
+ (if earnedMoney then $", and took {amountTaken} 💰$GBT from them!" else "!"))
|
||||
|
||||
DiscordFollowupMessageBuilder()
|
||||
.AddEmbed(embed.Build())
|
||||
@ -99,7 +101,7 @@ let responseCreatedShield (shield : Item) =
|
||||
|
||||
let eventSuccessfulHack (ctx : IDiscordContext) target prize =
|
||||
DiscordMessageBuilder()
|
||||
.WithContent($"{ctx.GetDiscordMember().Username} successfully hacked <@{target.DiscordId}> for a total of {prize} GoodBoyTokenz")
|
||||
.WithContent($"{ctx.GetDiscordMember().Username} successfully hacked <@{target.DiscordId}> and took {prize} GoodBoyTokenz")
|
||||
|
||||
let getBuyItemsEmbed (player : PlayerData) (itemType : ItemType) (store : Item array) =
|
||||
let embeds , buttons =
|
||||
@ -110,24 +112,26 @@ let getBuyItemsEmbed (player : PlayerData) (itemType : ItemType) (store : Item a
|
||||
match item.Type with
|
||||
| ItemType.Hack ->
|
||||
embed
|
||||
.AddField($"Hacking Power |", string item.Power, true)
|
||||
.AddField($"$GBT Reward |", string item.Power, true)
|
||||
.AddField("Cooldown |", $"{TimeSpan.FromMinutes(int item.Cooldown).Minutes} minutes", true)
|
||||
.WithThumbnail(getHackIcon (enum<HackId>(item.Id)))
|
||||
|> ignore
|
||||
| _ ->
|
||||
embed
|
||||
.AddField($"Defensive Strength |", string item.Power, true)
|
||||
// .AddField($"Defensive Strength |", string item.Power, true)
|
||||
.AddField($"Strong against |", Game.getGoodAgainst item.Class |> snd |> string, true)
|
||||
.AddField("Active For |", $"{TimeSpan.FromMinutes(int item.Cooldown).Hours} hours", true)
|
||||
.WithThumbnail(getShieldIcon (enum<ShieldId>(item.Id)))
|
||||
|> ignore
|
||||
embed
|
||||
.AddField("Price 💰", $"{item.Price} $GBT", true)
|
||||
.AddField("Price 💰", (if item.Price = 0<GBT> then "Free" else $"{item.Price} $GBT"), true)
|
||||
.WithColor(Game.getClassEmbedColor item.Class)
|
||||
.WithTitle($"{item.Name}")
|
||||
|> ignore
|
||||
let button =
|
||||
if player.Inventory |> Array.exists (fun i -> i.Id = item.Id)
|
||||
then DiscordButtonComponent(ButtonStyle.Primary, $"Buy-{item.Id}", $"Own {item.Name}", true)
|
||||
else DiscordButtonComponent(ButtonStyle.Primary, $"Buy-{item.Id}", $"Buy {item.Name}")
|
||||
then DiscordButtonComponent(Game.getClassButtonColor item.Class, $"Buy-{item.Id}", $"Own {item.Name}", true)
|
||||
else DiscordButtonComponent(Game.getClassButtonColor item.Class, $"Buy-{item.Id}", $"Buy {item.Name}")
|
||||
embed.Build() , button :> DiscordComponent)
|
||||
|> Array.unzip
|
||||
|
||||
@ -136,7 +140,7 @@ let getBuyItemsEmbed (player : PlayerData) (itemType : ItemType) (store : Item a
|
||||
.AddComponents(buttons)
|
||||
.AsEphemeral(true)
|
||||
|
||||
let getSellItemsEmbed (itemType : ItemType) (player : PlayerData) =
|
||||
let getSellEmbed (itemType : ItemType) (player : PlayerData) =
|
||||
let embeds , buttons =
|
||||
player.Inventory
|
||||
|> Array.filter (fun i -> i.Type = itemType)
|
||||
@ -148,8 +152,9 @@ let getSellItemsEmbed (itemType : ItemType) (player : PlayerData) =
|
||||
embed
|
||||
.AddField("Sell For 💰", $"{item.Price} $GBT", true)
|
||||
.WithTitle($"{item.Name}")
|
||||
.WithColor(Game.getClassEmbedColor item.Class)
|
||||
|> ignore
|
||||
let button = DiscordButtonComponent(ButtonStyle.Primary, $"Sell-{item.Id}", $"Sell {item.Name}")
|
||||
let button = DiscordButtonComponent(Game.getClassButtonColor item.Class, $"Sell-{item.Id}", $"Sell {item.Name}")
|
||||
embed.Build() , button :> DiscordComponent)
|
||||
|> Array.unzip
|
||||
|
||||
|
18
Bot/Game.fs
18
Bot/Game.fs
@ -9,10 +9,22 @@ open Degenz.DbService
|
||||
open Degenz.Messaging
|
||||
|
||||
module Game =
|
||||
let HackPrize = 10<GBT>
|
||||
let ShieldPrize = 5<GBT>
|
||||
let SameTargetAttackCooldown = System.TimeSpan.FromHours(2)
|
||||
|
||||
let SameTargetAttackCooldown = System.TimeSpan.FromHours(6)
|
||||
let getClassButtonColor = function
|
||||
| 0 -> ButtonStyle.Danger
|
||||
| 1 -> ButtonStyle.Success
|
||||
| _ -> ButtonStyle.Primary
|
||||
|
||||
let getClassEmbedColor = function
|
||||
| 0 -> DiscordColor.Red
|
||||
| 1 -> DiscordColor.Blurple
|
||||
| _ -> DiscordColor.Green
|
||||
|
||||
let getGoodAgainst = function
|
||||
| 0 -> ( ShieldId.Firewall , HackId.Virus )
|
||||
| 1 -> ( ShieldId.Cypher , HackId.RemoteAccess )
|
||||
| _ -> ( ShieldId.Encryption , HackId.Worm )
|
||||
|
||||
let executePlayerAction (ctx : IDiscordContext) (dispatch : PlayerData -> Async<unit>) =
|
||||
async {
|
||||
|
@ -33,7 +33,7 @@ let checkWeaponHasCooldown (weapon : Item) attacker =
|
||||
|
||||
let checkHasEmptyHacks attacker =
|
||||
match Player.getHacks attacker with
|
||||
| [||] -> Error $"You currently do not have any Hacks to steal 💰$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
|
||||
|
||||
let checkPlayerOwnsWeapon (item : Item) player =
|
||||
@ -41,19 +41,14 @@ let checkPlayerOwnsWeapon (item : Item) player =
|
||||
| true -> Ok player
|
||||
| false -> Error $"You sold your weapon already, you cheeky bastard..."
|
||||
|
||||
let checkTargetHasMoney (target : PlayerData) attacker =
|
||||
if target.Bank < Game.HackPrize
|
||||
then Error $"{target.Name} does not have enough 💰$GBT to steal from, the broke loser. Pick a different target."
|
||||
else Ok attacker
|
||||
|
||||
let checkPlayerHasShieldSlotsAvailable (shield : Item) player =
|
||||
let updatedPlayer = player |> Player.removeExpiredActions
|
||||
let defenses = Player.getShieldEvents updatedPlayer
|
||||
match defenses |> Array.length >= 2 with
|
||||
match defenses |> Array.length >= 3 with
|
||||
| true ->
|
||||
let timestamp = defenses |> Array.rev |> Array.head |> fun a -> a.Timestamp // This should be the next expiring timestamp
|
||||
let cooldown = getTimeText true (TimeSpan.FromMinutes(int shield.Cooldown)) timestamp
|
||||
Error $"You are only allowed two shields at a time. Wait {cooldown} to add another shield"
|
||||
Error $"You are only allowed three shields at a time. Wait {cooldown} to add another shield"
|
||||
| false -> Ok updatedPlayer
|
||||
|
||||
let calculateDamage (hack : Item) (shield : Item) =
|
||||
@ -94,12 +89,13 @@ let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerDa
|
||||
|
||||
let successfulHack (ctx : IDiscordContext) attacker defender hack =
|
||||
async {
|
||||
do! updateCombatants true attacker defender hack Game.HackPrize
|
||||
let finalAmount = max 0 (int defender.Bank - hack.Power) * 1<GBT>
|
||||
do! updateCombatants true attacker defender hack finalAmount
|
||||
|
||||
let embed = Embeds.responseSuccessfulHack true defender.DiscordId hack
|
||||
let embed = Embeds.responseSuccessfulHack true defender.DiscordId finalAmount hack
|
||||
do! ctx.FollowUp embed |> Async.AwaitTask
|
||||
|
||||
let builder = Embeds.eventSuccessfulHack ctx defender Game.HackPrize
|
||||
let builder = Embeds.eventSuccessfulHack ctx defender finalAmount
|
||||
let channel = ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle)
|
||||
do! channel.SendMessageAsync(builder)
|
||||
|> Async.AwaitTask
|
||||
@ -108,26 +104,26 @@ let successfulHack (ctx : IDiscordContext) attacker defender hack =
|
||||
|
||||
let failedHack (ctx : IDiscordContext) attacker defender hack =
|
||||
async {
|
||||
let msg = $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {Game.ShieldPrize} $GBT!"
|
||||
let finalAmount = max 0 (int defender.Bank - hack.Power) * 1<GBT>
|
||||
let msg = $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {finalAmount} $GBT!"
|
||||
do! sendFollowUpMessage ctx msg
|
||||
|
||||
do! updateCombatants false attacker defender hack -Game.ShieldPrize
|
||||
do! updateCombatants false attacker defender hack -finalAmount
|
||||
|
||||
let builder = DiscordMessageBuilder()
|
||||
builder.WithContent($"Hacking attempt failed! <@{defender.DiscordId}> defended hack from {ctx.GetDiscordMember().Username} and stole {Game.ShieldPrize} $GBT from them! ") |> ignore
|
||||
builder.WithContent($"Hacking attempt failed! <@{defender.DiscordId}> defended hack from {ctx.GetDiscordMember().Username} and took {finalAmount} $GBT from them! ") |> ignore
|
||||
let channel = (ctx.GetGuild().GetChannel(GuildEnvironment.channelEventsHackerBattle))
|
||||
do! channel.SendMessageAsync(builder)
|
||||
|> Async.AwaitTask
|
||||
|> Async.Ignore
|
||||
}
|
||||
|
||||
let attack (target : DiscordUser) (ctx : IDiscordContext) =
|
||||
let hack (target : DiscordUser) (ctx : IDiscordContext) =
|
||||
Game.executePlayerActionWithTarget target ctx (fun attacker defender -> async {
|
||||
do! attacker
|
||||
|> Player.removeExpiredActions
|
||||
|> checkAlreadyHackedTarget defender
|
||||
<!> Player.removeExpiredActions
|
||||
>>= checkHasEmptyHacks
|
||||
>>= checkTargetHasMoney defender
|
||||
>>= checkPlayerIsAttackingThemselves defender
|
||||
|> function
|
||||
| Ok atkr ->
|
||||
@ -261,7 +257,7 @@ type HackerGame() =
|
||||
|
||||
[<SlashCommand("hack", "Send a hack attack to another player")>]
|
||||
member this.AttackCommand (ctx : InteractionContext, [<Option("target", "The player you want to hack")>] target : DiscordUser) =
|
||||
enforceChannels (DiscordInteractionContext ctx) (Trainer.hack target) (attack target)
|
||||
enforceChannels (DiscordInteractionContext ctx) (Trainer.hack target) (hack target)
|
||||
|
||||
[<SlashCommand("shield", "Create a passive shield that will protect you for a certain time")>]
|
||||
member this.ShieldCommand (ctx : InteractionContext) =
|
||||
|
@ -4,8 +4,8 @@
|
||||
"Name": "Virus",
|
||||
"Type": 0,
|
||||
"Price": 0,
|
||||
"Power": 10,
|
||||
"Cooldown": 2,
|
||||
"Power": 25,
|
||||
"Cooldown": 1,
|
||||
"Class": 0,
|
||||
"Attributes": {
|
||||
"Sell": false,
|
||||
@ -19,8 +19,8 @@
|
||||
"Name": "RemoteAccess",
|
||||
"Type": 0,
|
||||
"Price": 500,
|
||||
"Power": 50,
|
||||
"Cooldown": 2,
|
||||
"Power": 75,
|
||||
"Cooldown": 3,
|
||||
"Class": 1,
|
||||
"Attributes": {
|
||||
"Sell": true,
|
||||
@ -34,8 +34,8 @@
|
||||
"Name": "Worm",
|
||||
"Type": 0,
|
||||
"Price": 5000,
|
||||
"Power": 80,
|
||||
"Cooldown": 2,
|
||||
"Power": 150,
|
||||
"Cooldown": 5,
|
||||
"Class": 2,
|
||||
"Attributes": {
|
||||
"Sell": true,
|
||||
@ -51,7 +51,7 @@
|
||||
"Price": 0,
|
||||
"Power": 10,
|
||||
"Class": 0,
|
||||
"Cooldown": 600,
|
||||
"Cooldown": 120,
|
||||
"Attributes": {
|
||||
"Sell": false,
|
||||
"Buy": false,
|
||||
@ -63,10 +63,10 @@
|
||||
"Id": 7,
|
||||
"Name": "Encryption",
|
||||
"Type": 1,
|
||||
"Price": 5000,
|
||||
"Power": 80,
|
||||
"Price": 500,
|
||||
"Power": 50,
|
||||
"Class": 1,
|
||||
"Cooldown": 600,
|
||||
"Cooldown": 240,
|
||||
"Attributes": {
|
||||
"Sell": true,
|
||||
"Buy": true,
|
||||
@ -78,10 +78,10 @@
|
||||
"Id": 8,
|
||||
"Name": "Cypher",
|
||||
"Type": 1,
|
||||
"Price": 500,
|
||||
"Power": 50,
|
||||
"Price": 5000,
|
||||
"Power": 80,
|
||||
"Class": 2,
|
||||
"Cooldown": 600,
|
||||
"Cooldown": 380,
|
||||
"Attributes": {
|
||||
"Sell": true,
|
||||
"Buy": true,
|
||||
|
@ -37,7 +37,7 @@ let buy itemType (ctx : IDiscordContext) =
|
||||
let sell itemType (ctx : IDiscordContext) =
|
||||
Game.executePlayerAction ctx (fun player -> async {
|
||||
match checkHasItemsInArsenal itemType player with
|
||||
| Ok _ -> let itemStore = Embeds.getSellItemsEmbed itemType player
|
||||
| Ok _ -> let itemStore = Embeds.getSellEmbed itemType player
|
||||
do! ctx.FollowUp(itemStore) |> Async.AwaitTask
|
||||
| Error e -> do! sendFollowUpMessage ctx e
|
||||
})
|
||||
|
@ -38,7 +38,7 @@ let sendInitialEmbed (client : DiscordClient) =
|
||||
embed.ImageUrl <- "https://s10.gifyu.com/images/MasterTraining_Degenz.gif"
|
||||
builder.AddEmbed embed |> ignore
|
||||
builder.Content <- "Welcome Degen… To the Hacker Training Program.\n"
|
||||
+ "Here you will learn how to defend yourself, and hack other Degenz to steal their 💰$GBT.\n"
|
||||
+ "Here you will learn how to defend yourself, and hack other Degenz to take their 💰$GBT.\n"
|
||||
+ "Are you ready?"
|
||||
let button = DiscordButtonComponent(ButtonStyle.Success, $"Trainer-1", $"LFG") :> DiscordComponent
|
||||
builder.AddComponents [| button |] |> ignore
|
||||
@ -52,7 +52,7 @@ let handleTrainerStep1 (ctx : IDiscordContext) =
|
||||
let role = ctx.GetGuild().GetRole(GuildEnvironment.roleTrainee)
|
||||
do! ctx.GetDiscordMember().GrantRoleAsync(role)
|
||||
|> Async.AwaitTask
|
||||
let msg = "Beautopia© is a dangerous place... quick, put up a SHIELD 🛡 before another Degen hacks you, and steals 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"
|
||||
+ $"Type the `/shield` command now, then select - `{defaultShield.Name}`\n"
|
||||
let builder =
|
||||
@ -135,13 +135,13 @@ let handleHack (ctx : IDiscordContext) =
|
||||
Game.executePlayerAction ctx (fun player -> async {
|
||||
let sendMessage' = sendFollowUpMessage ctx
|
||||
do! Async.Sleep 1000
|
||||
let embed = Embeds.responseSuccessfulHack false Sensei.Id defaultHack
|
||||
let embed = Embeds.responseSuccessfulHack false Sensei.Id defaultHack.Power defaultHack
|
||||
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
||||
do! Async.Sleep 5000
|
||||
do! sendMessage'
|
||||
("🎉 **Congratulations**\n\n"
|
||||
+ "You successfully **HACKED** me, and are now an **Elite Haxor!**\n\n"
|
||||
+ "When you **HACK** other Degenz, you **STEAL** their 💰$GBT.\n"
|
||||
+ "When you **HACK** other Degenz, you **TAKE** their 💰$GBT.\n"
|
||||
+ "But remember, hacks take time to recover, so use them wisely.")
|
||||
|
||||
do! Async.Sleep 6000
|
||||
|
Loading…
x
Reference in New Issue
Block a user