Fixed bug with defending and small changes to gameplay
This commit is contained in:
parent
162f6af03f
commit
5ab49e674e
@ -23,7 +23,7 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
|
|||||||
| Some attacker , Some defender ->
|
| Some attacker , Some defender ->
|
||||||
let updatedAttacks =
|
let updatedAttacks =
|
||||||
attacker.Attacks
|
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
|
do! DbService.updateAttacks attacker.DiscordId updatedAttacks
|
||||||
if updatedAttacks.Length < 2 then
|
if updatedAttacks.Length < 2 then
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
@ -61,11 +61,11 @@ let defend (ctx : InteractionContext) =
|
|||||||
let! player = DbService.tryFindPlayer ctx.Member.Id
|
let! player = DbService.tryFindPlayer ctx.Member.Id
|
||||||
match player with
|
match player with
|
||||||
| Some player ->
|
| 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 }
|
do! DbService.updatePlayer <| { player with Defenses = updatedDefenses }
|
||||||
if updatedDefenses.Length < 2 then
|
if updatedDefenses.Length < 3 then
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
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
|
constructButtons "Defend" (string player.DiscordId) player.Shields
|
||||||
|> Seq.cast<DiscordComponent>
|
|> Seq.cast<DiscordComponent>
|
||||||
@ -80,7 +80,8 @@ let defend (ctx : InteractionContext) =
|
|||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
let timestamp = updatedDefenses |> Array.rev |> Array.head |> fun a -> a.Timestamp // This should be the next expiring timestamp
|
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 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
|
builder.AsEphemeral true |> ignore
|
||||||
|
|
||||||
@ -101,43 +102,46 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
|
|||||||
let! resultTarget = DbService.tryFindPlayer targetId
|
let! resultTarget = DbService.tryFindPlayer targetId
|
||||||
match resultPlayer , resultTarget , resultHack , resultId with
|
match resultPlayer , resultTarget , resultHack , resultId with
|
||||||
| Some player , Some target , true , true ->
|
| 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 =
|
let wasSuccessfulHack =
|
||||||
target.Defenses
|
updatedDefenses
|
||||||
|> Seq.toArray
|
|> Seq.toArray
|
||||||
|> Array.map (fun dfn -> int dfn.DefenseType)
|
|> Array.map (fun dfn -> int dfn.DefenseType)
|
||||||
|> Array.map (calculateDamage weapon)
|
|> Array.map (calculateDamage weapon)
|
||||||
|> Array.contains Weak
|
|> Array.contains Weak
|
||||||
match wasSuccessfulHack with
|
match wasSuccessfulHack with
|
||||||
| false ->
|
| 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] } }
|
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 <| updatePlayer prize attack player
|
||||||
|
do! DbService.updatePlayer { target with Bank = MathF.Max(target.Bank - prize, 0f)}
|
||||||
|
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
builder.IsEphemeral <- true
|
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)
|
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|
||||||
|> Async.AwaitTask
|
|> Async.AwaitTask
|
||||||
|
|
||||||
let builder = DiscordMessageBuilder()
|
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))
|
let channel = (event.Guild.GetChannel(battleChannel))
|
||||||
do! channel.SendMessageAsync(builder)
|
do! channel.SendMessageAsync(builder)
|
||||||
|> Async.AwaitTask
|
|> Async.AwaitTask
|
||||||
|> Async.Ignore
|
|> Async.Ignore
|
||||||
| true ->
|
| true ->
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
let loss = -0.0623f
|
let prize = 0.0623f
|
||||||
builder.IsEphemeral <- true
|
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)
|
do! event.Interaction.CreateResponseAsync(InteractionResponseType.UpdateMessage, builder)
|
||||||
|> Async.AwaitTask
|
|> Async.AwaitTask
|
||||||
|
|
||||||
let attack = { HackType = enum<Weapon>(weapon) ; Timestamp = DateTime.UtcNow ; Target = { Id = targetId ; Name = split.[3] } }
|
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()
|
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))
|
let channel = (event.Guild.GetChannel(battleChannel))
|
||||||
do! channel.SendMessageAsync(builder)
|
do! channel.SendMessageAsync(builder)
|
||||||
|> Async.AwaitTask
|
|> Async.AwaitTask
|
||||||
|
@ -94,6 +94,9 @@ module Commands =
|
|||||||
let! player = DbService.tryFindPlayer ctx.Member.Id
|
let! player = DbService.tryFindPlayer ctx.Member.Id
|
||||||
match player with
|
match player with
|
||||||
| Some p ->
|
| 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()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
builder.IsEphemeral <- true
|
builder.IsEphemeral <- true
|
||||||
builder.Content <- statusFormat p
|
builder.Content <- statusFormat p
|
||||||
|
@ -26,55 +26,56 @@ type Shield =
|
|||||||
| Sanitation = 5
|
| Sanitation = 5
|
||||||
| Cypher = 3
|
| Cypher = 3
|
||||||
|
|
||||||
let getClass = function
|
let getClass =
|
||||||
| 0 | 1 -> Network
|
function
|
||||||
| 2 | 3 -> Exploit
|
| 0
|
||||||
| 4 | _ -> Penetration
|
| 1 -> Network
|
||||||
|
| 2
|
||||||
|
| 3 -> Exploit
|
||||||
|
| 4
|
||||||
|
| _ -> Penetration
|
||||||
|
|
||||||
type HackResult =
|
type HackResult =
|
||||||
| Strong
|
| Strong
|
||||||
| Weak
|
| Weak
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type DiscordPlayer = {
|
type DiscordPlayer = { Id: uint64; Name: string }
|
||||||
Id : uint64
|
|
||||||
Name : string
|
|
||||||
}
|
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type Attack = {
|
type Attack =
|
||||||
HackType : Weapon
|
{ HackType: Weapon
|
||||||
Target : DiscordPlayer
|
Target: DiscordPlayer
|
||||||
Timestamp : DateTime
|
Timestamp: DateTime }
|
||||||
}
|
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type Defense = {
|
type Defense =
|
||||||
DefenseType : Shield
|
{ DefenseType: Shield
|
||||||
Timestamp : DateTime
|
Timestamp: DateTime }
|
||||||
}
|
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type Player = {
|
type Player =
|
||||||
DiscordId : uint64
|
{ DiscordId: uint64
|
||||||
Name : string
|
Name: string
|
||||||
Weapons : Weapon array
|
Weapons: Weapon array
|
||||||
Shields : Shield array
|
Shields: Shield array
|
||||||
Attacks : Attack array
|
Attacks: Attack array
|
||||||
Defenses : Defense array
|
Defenses: Defense array
|
||||||
Bank : single
|
Bank: single }
|
||||||
}
|
|
||||||
|
|
||||||
let createSimpleResponseAsync msg (ctx : InteractionContext) =
|
let createSimpleResponseAsync msg (ctx: InteractionContext) =
|
||||||
async {
|
async {
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
builder.Content <- msg
|
builder.Content <- msg
|
||||||
builder.AsEphemeral true |> ignore
|
builder.AsEphemeral true |> ignore
|
||||||
do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|
|
||||||
|
do!
|
||||||
|
ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
|
||||||
|> Async.AwaitTask
|
|> 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 = ""
|
let hackDescription = ""
|
||||||
|
|
||||||
@ -85,20 +86,12 @@ Active Hacks: {player.Attacks |> Array.toList}
|
|||||||
Active Defenses: {player.Defenses |> Array.toList}
|
Active Defenses: {player.Defenses |> Array.toList}
|
||||||
Bank: {player.Bank}"
|
Bank: {player.Bank}"
|
||||||
|
|
||||||
let constructButtons (actionType : string) (playerInfo : string) (weapons : 'a array) =
|
let constructButtons (actionType: string) (playerInfo: string) (weapons: 'a array) =
|
||||||
weapons
|
weapons
|
||||||
|> Seq.map (fun hack ->
|
|> Seq.map (fun hack -> DiscordButtonComponent(ButtonStyle.Primary, $"{actionType}-{hack}-{playerInfo}", $"{hack}"))
|
||||||
DiscordButtonComponent(
|
|
||||||
ButtonStyle.Primary,
|
|
||||||
$"{actionType}-{hack}-{playerInfo}",
|
|
||||||
$"{hack}"))
|
|
||||||
|
|
||||||
let removeExpiredActions timespan (timestamp : 'a -> DateTime) actions =
|
let removeExpiredActions timespan (timestamp: 'a -> DateTime) actions =
|
||||||
actions
|
actions |> Array.filter (fun act -> DateTime.UtcNow - (timestamp act) < timespan)
|
||||||
|> Array.filter (fun act ->
|
|
||||||
if DateTime.UtcNow - (timestamp act) < timespan
|
|
||||||
then true
|
|
||||||
else false)
|
|
||||||
|
|
||||||
let constructEmbed message =
|
let constructEmbed message =
|
||||||
let builder = DiscordEmbedBuilder()
|
let builder = DiscordEmbedBuilder()
|
||||||
@ -111,10 +104,10 @@ let constructEmbed message =
|
|||||||
builder.Author <- author
|
builder.Author <- author
|
||||||
builder.Build()
|
builder.Build()
|
||||||
|
|
||||||
let calculateDamage (hack : int) (shield : int) =
|
let calculateDamage (hack: int) (shield: int) =
|
||||||
let hackClass = getClass hack
|
let hackClass = getClass hack
|
||||||
let protectionClass = getClass shield
|
let protectionClass = getClass shield
|
||||||
match hackClass , protectionClass with
|
|
||||||
| h , p when h = p -> Weak
|
|
||||||
| _ -> Strong
|
|
||||||
|
|
||||||
|
match hackClass, protectionClass with
|
||||||
|
| h, p when h = p -> Weak
|
||||||
|
| _ -> Strong
|
||||||
|
Loading…
x
Reference in New Issue
Block a user