diff --git a/Bot/HackerBattle.fs b/Bot/HackerBattle.fs index 3cf8c58..33ca5a1 100644 --- a/Bot/HackerBattle.fs +++ b/Bot/HackerBattle.fs @@ -9,6 +9,15 @@ open DSharpPlus.SlashCommands open Degenz open Degenz.Shared +let getTimeTillCooldownFinishes (timespan : TimeSpan) timestamp = + let timeRemaining = timespan - (DateTime.UtcNow - timestamp) + if timeRemaining.Hours > 0 then + $"{timeRemaining.Hours} hours" + elif timeRemaining.Minutes > 0 then + $"{timeRemaining.Minutes} minutes" + else + $"{timeRemaining.Seconds} seconds" + let checkForExistingHack attacker defenderId = let updatedAttacks = attacker.Attacks @@ -17,8 +26,8 @@ let checkForExistingHack attacker defenderId = |> Array.tryFind (fun a -> a.Target.Id = defenderId) |> function | Some attack -> - let timeRemaining = TimeSpan.FromHours(24) - (DateTime.UtcNow - attack.Timestamp) - Error $"You can only hack the same target once every 24 hours, wait {timeRemaining.Seconds} seconds to attempt another hack on {attack.Target.Name}." + let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(24)) attack.Timestamp + Error $"You can only hack the same target once every 24 hours, wait {cooldown} to attempt another hack on {attack.Target.Name}." | None -> Ok updatedAttacks @@ -28,12 +37,12 @@ let checkIfHackHasCooldown hack updatedAttacks = |> Array.tryFind (fun a -> a.HackType = hack) |> function | Some a -> a.Timestamp - | None -> DateTime.UtcNow - if DateTime.UtcNow - mostRecentHackAttack <= TimeSpan.FromMinutes(5) then + | None -> DateTime.MinValue + if DateTime.UtcNow - mostRecentHackAttack > TimeSpan.FromMinutes(5) then Ok updatedAttacks else - let timeRemaining = TimeSpan.FromMinutes(5) - (DateTime.UtcNow - mostRecentHackAttack) - Error $"You can only attack once a minute, wait {timeRemaining.Seconds} seconds to attack again." + let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromMinutes(5)) mostRecentHackAttack + Error $"{hack} is currently on cooldown, wait {cooldown} to use it again." let calculateDamage (hack: int) (shield: int) = let hackClass = getClass hack @@ -43,7 +52,7 @@ let calculateDamage (hack: int) (shield: int) = | h, p when h = p -> Weak | _ -> Strong -let runHackerBattle attacker defender hack = +let runHackerBattle defender hack = defender.Defenses |> removeExpiredActions (TimeSpan.FromHours(6)) (fun (pro : Defense) -> pro.Timestamp) |> Seq.toArray @@ -70,8 +79,7 @@ let successfulHack (event : ComponentInteractionCreateEventArgs) attacker defend let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true builder.Content <- $"Successfully hacked {defender.Name} using {hack}! You just won {prize} GoodBoyTokenz!" - // TODO: Don't make this an Update - do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) + do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask let builder = Embeds.eventSuccessfulHack event defender.DiscordId prize @@ -87,7 +95,7 @@ let failedHack (event : ComponentInteractionCreateEventArgs) attacker defender h let prize = 2 builder.IsEphemeral <- true builder.Content <- $"Hack failed! {defender.Name} was able to mount a successful defense! You lost {prize} GoodBoyTokenz!" - do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) + do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask do! updateCombatants attacker defender hack -prize @@ -109,13 +117,16 @@ let attack (ctx : InteractionContext) (target : DiscordUser) = let existingHack = checkForExistingHack attacker defender.DiscordId match existingHack with | Ok _ -> - let embed = Embeds.pickHack "Attack" attacker defender - do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed) - |> Async.AwaitTask + let embed = Embeds.pickHack "Attack" attacker defender + do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed) + |> Async.AwaitTask | Error msg -> - let builder = DiscordInteractionResponseBuilder().WithContent(msg).AsEphemeral(true) - do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) - |> Async.AwaitTask + let builder = + DiscordInteractionResponseBuilder() + .WithContent(msg) + .AsEphemeral(true) + do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) + |> Async.AwaitTask | None , _ -> do! notYetAHackerMsg ctx | _ , None -> do! createSimpleResponseAsync "Your target is not connected to the network, they must join first by using the /redpill command" ctx } |> Async.StartAsTask @@ -136,13 +147,16 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) = |> Result.bind (checkIfHackHasCooldown hack) |> function | Ok _ -> - runHackerBattle attacker defender hack + runHackerBattle defender hack |> function | false -> successfulHack event attacker defender hack | true -> failedHack event attacker defender hack | Error msg -> - let builder = DiscordInteractionResponseBuilder() - event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder.WithContent(msg)) + let builder = + DiscordInteractionResponseBuilder() + .WithContent(msg) + .AsEphemeral(true) + event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask | _ -> let builder = DiscordInteractionResponseBuilder() @@ -201,19 +215,17 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) = let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true 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) - let hours = if timeRemaining.Hours > 0 then $"{timeRemaining.Hours} hours and " else "" - builder.Content <- $"You are only allowed two shields at a time. Wait {hours}{timeRemaining.Minutes} minutes to add another shield" - do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder) + let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(6)) timestamp + builder.Content <- $"You are only allowed two shields at a time. Wait {cooldown} minutes to add another shield" + do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask do! DbService.updatePlayer <| { player with Defenses = updatedDefenses } | true , _ -> let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true let timestamp = updatedDefenses |> Array.find (fun d -> d.DefenseType = shield) |> fun a -> a.Timestamp - let timeRemaining = TimeSpan.FromMinutes(15) - (DateTime.UtcNow - timestamp) - let hours = if timeRemaining.Hours > 0 then $"{timeRemaining.Hours} hours and " else "" - builder.Content <- $"{shield} shield is already in use. Wait {hours}{timeRemaining.Minutes} minutes to use this shield again" + let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(6)) timestamp + builder.Content <- $"{shield} shield is already in use. Wait {cooldown} minutes to use this shield again" do! event.Interaction.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder) |> Async.AwaitTask do! DbService.updatePlayer <| { player with Defenses = updatedDefenses } diff --git a/Bot/PlayerInteractions.fs b/Bot/PlayerInteractions.fs index 8655de7..3f32c2e 100644 --- a/Bot/PlayerInteractions.fs +++ b/Bot/PlayerInteractions.fs @@ -40,13 +40,13 @@ module Commands = | Some _ -> async.Return false | None -> async { - do! newPlayer ctx.Member.Username ctx.Member.Id + do! newPlayer ctx.Member.DisplayName ctx.Member.Id |> DbService.insertNewPlayer - for role in ctx.Guild.Roles do - if role.Value.Name = "Hacker" then - do! ctx.Member.GrantRoleAsync(role.Value) - |> Async.AwaitTask +// for role in ctx.Guild.Roles do +// if role.Value.Name = "Hacker" then +// do! ctx.Member.GrantRoleAsync(role.Value) +// |> Async.AwaitTask return true } @@ -64,10 +64,10 @@ module Commands = let removeHackerRole (ctx : InteractionContext) = async { - for role in ctx.Member.Roles do - if role.Name = "Hacker" then - do! ctx.Member.RevokeRoleAsync(role) - |> Async.AwaitTask +// for role in ctx.Member.Roles do +// if role.Name = "Hacker" then +// do! ctx.Member.RevokeRoleAsync(role) +// |> Async.AwaitTask do! DbService.removePlayer ctx.Member.Id diff --git a/Bot/Store.fs b/Bot/Store.fs index d54e497..400ad5b 100644 --- a/Bot/Store.fs +++ b/Bot/Store.fs @@ -148,7 +148,7 @@ let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCrea let itemName = split.[1] match itemType with | ItemType.Hack -> do! sellItem event updateHacks player player.Weapons ItemType.Hack itemName - | ItemType.Shield -> do! sellItem event updateShields player player.Shields ItemType.Hack itemName + | ItemType.Shield -> do! sellItem event updateShields player player.Shields ItemType.Shield itemName | None -> let builder = DiscordInteractionResponseBuilder() builder.IsEphemeral <- true