Fixed bug with defending and small changes to gameplay

This commit is contained in:
Joseph Ferano 2022-01-16 02:46:42 +07:00
parent 162f6af03f
commit 5ab49e674e
3 changed files with 58 additions and 58 deletions

View File

@ -23,7 +23,7 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
| Some attacker , Some defender ->
let updatedAttacks =
attacker.Attacks
|> removeExpiredActions (TimeSpan.FromMinutes(5)) (fun (atk : Attack) -> atk.Timestamp)
|> removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp)
do! DbService.updateAttacks attacker.DiscordId updatedAttacks
if updatedAttacks.Length < 2 then
let builder = DiscordInteractionResponseBuilder()
@ -61,11 +61,11 @@ let defend (ctx : InteractionContext) =
let! player = DbService.tryFindPlayer ctx.Member.Id
match player with
| Some player ->
let updatedDefenses = removeExpiredActions (TimeSpan.FromMinutes(60)) (fun (pro : Defense) -> pro.Timestamp) player.Defenses
let updatedDefenses = removeExpiredActions (TimeSpan.FromHours(24)) (fun (pro : Defense) -> pro.Timestamp) player.Defenses
do! DbService.updatePlayer <| { player with Defenses = updatedDefenses }
if updatedDefenses.Length < 2 then
if updatedDefenses.Length < 3 then
let builder = DiscordInteractionResponseBuilder()
builder.AddEmbed (constructEmbed "Pick a defense to mount for a duration of time") |> ignore
builder.AddEmbed (constructEmbed "Pick a defense to mount for 24 hours") |> ignore
constructButtons "Defend" (string player.DiscordId) player.Shields
|> Seq.cast<DiscordComponent>
@ -80,7 +80,8 @@ let defend (ctx : InteractionContext) =
let builder = DiscordInteractionResponseBuilder()
let timestamp = updatedDefenses |> Array.rev |> Array.head |> fun a -> a.Timestamp // This should be the next expiring timestamp
let timeRemaining = TimeSpan.FromMinutes(15) - (DateTime.UtcNow - timestamp)
builder.Content <- $"Cannot add new defense, please wait {timeRemaining.Minutes} minutes and {timeRemaining.Seconds} seconds to add another defense"
// TODO: Make this handle hours and minutes
builder.Content <- $"Cannot add new defense, please wait {timeRemaining.Hours} hours and {timeRemaining.Minutes} minutes to add another defense"
builder.AsEphemeral true |> ignore
@ -101,43 +102,46 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
let! resultTarget = DbService.tryFindPlayer targetId
match resultPlayer , resultTarget , resultHack , resultId with
| Some player , Some target , true , true ->
let updatedDefenses = removeExpiredActions (TimeSpan.FromHours(24)) (fun (p : Defense) -> p.Timestamp) target.Defenses
do! DbService.updatePlayer <| { player with Defenses = updatedDefenses }
let wasSuccessfulHack =
target.Defenses
updatedDefenses
|> Seq.toArray
|> Array.map (fun dfn -> int dfn.DefenseType)
|> Array.map (calculateDamage weapon)
|> Array.contains Weak
match wasSuccessfulHack with
| false ->
let prize = 0.1726f
let prize = 1.337f // LEET
let attack = { HackType = enum<Weapon>(weapon) ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } }
do! DbService.updatePlayer <| updatePlayer prize attack player
do! DbService.updatePlayer { target with Bank = MathF.Max(target.Bank - prize, 0f)}
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- $"Successfully hacked {split.[3]} using {weapon}! You just won {prize} genz!"
builder.Content <- $"Successfully hacked {split.[3]} using {weapon}! You just won {prize} GoodBoyTokenz!"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|> Async.AwaitTask
let builder = DiscordMessageBuilder()
builder.WithContent($"{event.User.Username} successfully hacked <@{targetId}>!") |> ignore
builder.WithContent($"{event.User.Username} successfully hacked <@{targetId}> for a total of {prize} GoodBoyTokenz") |> ignore
let channel = (event.Guild.GetChannel(battleChannel))
do! channel.SendMessageAsync(builder)
|> Async.AwaitTask
|> Async.Ignore
| true ->
let builder = DiscordInteractionResponseBuilder()
let loss = -0.0623f
let prize = 0.0623f
builder.IsEphemeral <- true
builder.Content <- $"Hack failed! {split.[3]} was able to mount a successful defense! You lost {loss} genz!"
builder.Content <- $"Hack failed! {split.[3]} was able to mount a successful defense! You lost {prize} GoodBoyTokenz!"
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|> Async.AwaitTask
let attack = { HackType = enum<Weapon>(weapon) ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } }
do! DbService.updatePlayer <| updatePlayer loss attack player
do! DbService.updatePlayer <| updatePlayer -prize attack player
let builder = DiscordMessageBuilder()
builder.WithContent($"{event.User.Username} failed to hack <@{targetId}>!") |> ignore
builder.WithContent($"Hacking attempt failed! <@{targetId}> defended hack from {event.User} and took {prize} from them! ") |> ignore
let channel = (event.Guild.GetChannel(battleChannel))
do! channel.SendMessageAsync(builder)
|> Async.AwaitTask

View File

@ -94,6 +94,9 @@ module Commands =
let! player = DbService.tryFindPlayer ctx.Member.Id
match player with
| Some p ->
let updatedAttacks = p.Attacks |> removeExpiredActions (TimeSpan.FromMinutes(15)) (fun (atk : Attack) -> atk.Timestamp)
let updatedDefenses = p.Defenses |> removeExpiredActions (TimeSpan.FromHours(24)) (fun (p : Defense) -> p.Timestamp)
do! DbService.updatePlayer <| { p with Attacks = updatedAttacks ; Defenses = updatedDefenses }
let builder = DiscordInteractionResponseBuilder()
builder.IsEphemeral <- true
builder.Content <- statusFormat p

View File

@ -26,55 +26,56 @@ type Shield =
| Sanitation = 5
| Cypher = 3
let getClass = function
| 0 | 1 -> Network
| 2 | 3 -> Exploit
| 4 | _ -> Penetration
let getClass =
function
| 0
| 1 -> Network
| 2
| 3 -> Exploit
| 4
| _ -> Penetration
type HackResult =
| Strong
| Weak
[<CLIMutable>]
type DiscordPlayer = {
Id : uint64
Name : string
}
type DiscordPlayer = { Id: uint64; Name: string }
[<CLIMutable>]
type Attack = {
HackType : Weapon
type Attack =
{ HackType: Weapon
Target: DiscordPlayer
Timestamp : DateTime
}
Timestamp: DateTime }
[<CLIMutable>]
type Defense = {
DefenseType : Shield
Timestamp : DateTime
}
type Defense =
{ DefenseType: Shield
Timestamp: DateTime }
[<CLIMutable>]
type Player = {
DiscordId : uint64
type Player =
{ DiscordId: uint64
Name: string
Weapons: Weapon array
Shields: Shield array
Attacks: Attack array
Defenses: Defense array
Bank : single
}
Bank: single }
let createSimpleResponseAsync msg (ctx: InteractionContext) =
async {
let builder = DiscordInteractionResponseBuilder()
builder.Content <- msg
builder.AsEphemeral true |> ignore
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
do!
ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|> Async.AwaitTask
}
let notYetAHackerMsg = createSimpleResponseAsync "You are not currently a hacker, first use the /redpill command to become one"
let notYetAHackerMsg =
createSimpleResponseAsync "You are not currently a hacker, first use the /redpill command to become one"
let hackDescription = ""
@ -87,18 +88,10 @@ Bank: {player.Bank}"
let constructButtons (actionType: string) (playerInfo: string) (weapons: 'a array) =
weapons
|> Seq.map (fun hack ->
DiscordButtonComponent(
ButtonStyle.Primary,
$"{actionType}-{hack}-{playerInfo}",
$"{hack}"))
|> Seq.map (fun hack -> DiscordButtonComponent(ButtonStyle.Primary, $"{actionType}-{hack}-{playerInfo}", $"{hack}"))
let removeExpiredActions timespan (timestamp: 'a -> DateTime) actions =
actions
|> Array.filter (fun act ->
if DateTime.UtcNow - (timestamp act) < timespan
then true
else false)
actions |> Array.filter (fun act -> DateTime.UtcNow - (timestamp act) < timespan)
let constructEmbed message =
let builder = DiscordEmbedBuilder()
@ -114,7 +107,7 @@ let constructEmbed message =
let calculateDamage (hack: int) (shield: int) =
let hackClass = getClass hack
let protectionClass = getClass shield
match hackClass, protectionClass with
| h, p when h = p -> Weak
| _ -> Strong