Fixes to Trainer copy, Check if defender has money, bring back status (arsenal)
This commit is contained in:
		
							parent
							
								
									e772a6d6f3
								
							
						
					
					
						commit
						ad613064a8
					
				@ -9,14 +9,7 @@ open DSharpPlus.SlashCommands
 | 
			
		||||
open Degenz
 | 
			
		||||
open Degenz.Messaging
 | 
			
		||||
 | 
			
		||||
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 (>>=) x f = Result.bind f x
 | 
			
		||||
 | 
			
		||||
let checkIfPlayerIsAttackingThemselves defender attacker  =
 | 
			
		||||
    match attacker.DiscordId = defender.DiscordId with
 | 
			
		||||
@ -30,10 +23,9 @@ let checkForExistingHack defenderId attacker =
 | 
			
		||||
    |> Array.tryFind (fun (_,t,_) -> t.Id = defenderId)
 | 
			
		||||
    |> function
 | 
			
		||||
       | Some ( atk , target , _ ) ->
 | 
			
		||||
           let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(24)) atk.Timestamp
 | 
			
		||||
           Error $"You can only hack the same target once every 24 hours, wait {cooldown} to attempt another hack on {target.Name}."
 | 
			
		||||
       | None ->
 | 
			
		||||
           Ok attacker
 | 
			
		||||
           let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromHours(2)) atk.Timestamp
 | 
			
		||||
           Error $"You can only hack the same target once every 2 hours, wait {cooldown} to attempt another hack on {target.Name}."
 | 
			
		||||
       | None -> Ok attacker
 | 
			
		||||
 | 
			
		||||
let checkIfHackHasCooldown hackId attacker =
 | 
			
		||||
    let mostRecentHackAttack =
 | 
			
		||||
@ -54,6 +46,11 @@ let checkIfInventoryIsEmpty attacker =
 | 
			
		||||
    | [||] -> Error $"You currently do not have any Hacks to steal 💰$GBT from others. Please go to the <#{GuildEnvironment.channelArmory}> and purchase one."
 | 
			
		||||
    | _ -> Ok attacker
 | 
			
		||||
 | 
			
		||||
let checkIfTargetHasMoney (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 calculateDamage (hack : BattleItem) (shield : BattleItem) =
 | 
			
		||||
    if hack.Class = shield.Class
 | 
			
		||||
        then Strong
 | 
			
		||||
@ -115,22 +112,22 @@ let attack (ctx : InteractionContext) (target : DiscordUser) =
 | 
			
		||||
        let! defender = DbService.tryFindPlayer target.Id
 | 
			
		||||
        match defender with
 | 
			
		||||
        | Some defender ->
 | 
			
		||||
            let hackAttempt =
 | 
			
		||||
                checkForExistingHack defender.DiscordId attacker
 | 
			
		||||
                |> Result.bind checkIfInventoryIsEmpty
 | 
			
		||||
                |> Result.bind (checkIfPlayerIsAttackingThemselves defender)
 | 
			
		||||
            match hackAttempt with
 | 
			
		||||
            | Ok _ ->
 | 
			
		||||
                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
 | 
			
		||||
          do! checkForExistingHack defender.DiscordId attacker
 | 
			
		||||
              >>= checkIfInventoryIsEmpty
 | 
			
		||||
              >>= (checkIfTargetHasMoney defender)
 | 
			
		||||
              >>= (checkIfPlayerIsAttackingThemselves defender)
 | 
			
		||||
              |> function
 | 
			
		||||
                 | Ok _ ->
 | 
			
		||||
                     let embed = Embeds.pickHack "Attack" attacker defender
 | 
			
		||||
                     ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, embed)
 | 
			
		||||
                     |> Async.AwaitTask
 | 
			
		||||
                 | Error msg ->
 | 
			
		||||
                     let builder =
 | 
			
		||||
                         DiscordInteractionResponseBuilder()
 | 
			
		||||
                             .WithContent(msg)
 | 
			
		||||
                             .AsEphemeral(true)
 | 
			
		||||
                     ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
 | 
			
		||||
                     |> Async.AwaitTask
 | 
			
		||||
        | None -> do! sendSimpleResponse ctx "Your target is not connected to the network, they must join first by using the /redpill command"
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
@ -260,7 +257,7 @@ type HackerGame() =
 | 
			
		||||
        else
 | 
			
		||||
            attack ctx target
 | 
			
		||||
 | 
			
		||||
    [<SlashCommand("shield", "Create a passive defense that will last 24 hours")>]
 | 
			
		||||
    [<SlashCommand("shield", "Create a passive shield that will protect you for a certain time")>]
 | 
			
		||||
    member this.ShieldCommand (ctx : InteractionContext) =
 | 
			
		||||
        if ctx.Channel.Id = GuildEnvironment.channelTraining then
 | 
			
		||||
            Trainer.defend ctx
 | 
			
		||||
 | 
			
		||||
@ -71,27 +71,12 @@ module Commands =
 | 
			
		||||
//        } |> Async.StartAsTask
 | 
			
		||||
//        :> Task
 | 
			
		||||
 | 
			
		||||
    let status (ctx : InteractionContext) =
 | 
			
		||||
        Game.executePlayerInteraction ctx (fun player -> async {
 | 
			
		||||
            let updatedActions = Player.removeExpiredActions player.Actions
 | 
			
		||||
            let updatedPlayer = { player with Actions = updatedActions }
 | 
			
		||||
            let builder = DiscordInteractionResponseBuilder()
 | 
			
		||||
            builder.IsEphemeral <- true
 | 
			
		||||
            builder.Content <- Messaging.statusFormat updatedPlayer
 | 
			
		||||
            do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
 | 
			
		||||
                |> Async.AwaitTask
 | 
			
		||||
            do! DbService.updatePlayer updatedPlayer
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
type PlayerInteractions() =
 | 
			
		||||
    inherit ApplicationCommandModule ()
 | 
			
		||||
 | 
			
		||||
    [<SlashCommand("redpill", "Take the redpill and become a hacker")>]
 | 
			
		||||
    member _.AddHackerRole (ctx : InteractionContext) = Commands.addHackerRole ctx
 | 
			
		||||
 | 
			
		||||
    [<SlashCommand("status", "Get your current status like bank account, and active hacks and defenses")>]
 | 
			
		||||
    member this.Status (ctx : InteractionContext) = Commands.status ctx
 | 
			
		||||
 | 
			
		||||
//    [<SlashCommand("leaderboard", "View the current list of players ranked by highest earnings")>]
 | 
			
		||||
//    member this.Leaderboard (ctx : InteractionContext) = Commands.leaderboard ctx
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								Bot/Store.fs
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								Bot/Store.fs
									
									
									
									
									
								
							@ -94,12 +94,29 @@ let handleSellButtonEvents (_ : DiscordClient) (event : ComponentInteractionCrea
 | 
			
		||||
    } |> Async.StartAsTask
 | 
			
		||||
    :> Task
 | 
			
		||||
 | 
			
		||||
let status (ctx : InteractionContext) =
 | 
			
		||||
    Game.executePlayerInteraction ctx (fun player -> async {
 | 
			
		||||
        let updatedActions = Player.removeExpiredActions player.Actions
 | 
			
		||||
        let updatedPlayer = { player with Actions = updatedActions }
 | 
			
		||||
        let builder = DiscordInteractionResponseBuilder()
 | 
			
		||||
        let embed = DiscordEmbedBuilder()
 | 
			
		||||
        embed.AddField("Arsenal", Messaging.statusFormat updatedPlayer) |> ignore
 | 
			
		||||
        builder.AddEmbed(embed) |> ignore
 | 
			
		||||
        builder.IsEphemeral <- true
 | 
			
		||||
        do! ctx.CreateResponseAsync(InteractionResponseType.ChannelMessageWithSource, builder)
 | 
			
		||||
            |> Async.AwaitTask
 | 
			
		||||
        do! DbService.updatePlayer updatedPlayer
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
type Store() =
 | 
			
		||||
    inherit ApplicationCommandModule ()
 | 
			
		||||
//    [<SlashCommand("view-store", "View items available for purchase")>]
 | 
			
		||||
 | 
			
		||||
//    member _.ViewStore (ctx : InteractionContext) = viewStore ctx
 | 
			
		||||
 | 
			
		||||
    [<SlashCommand("arsenal", "Get the Hacks and Shields you own, and which ones are active")>]
 | 
			
		||||
    member this.Arsenal (ctx : InteractionContext) = status ctx
 | 
			
		||||
 | 
			
		||||
    [<SlashCommand("buy-hack", "Purchase a hack attack you can use to earn GoodBoyTokenz")>]
 | 
			
		||||
    member _.BuyHack (ctx : InteractionContext) = buyItem ctx Hack
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
module Degenz.Trainer
 | 
			
		||||
 | 
			
		||||
open System.Threading.Tasks
 | 
			
		||||
open DSharpPlus
 | 
			
		||||
open System.Threading.Tasks
 | 
			
		||||
open DSharpPlus.Entities
 | 
			
		||||
open DSharpPlus.EventArgs
 | 
			
		||||
open DSharpPlus.SlashCommands
 | 
			
		||||
@ -39,7 +39,7 @@ let handleTrainerStep1 (event : ComponentInteractionCreateEventArgs) =
 | 
			
		||||
 | 
			
		||||
        do! sendInteractionEvent event
 | 
			
		||||
                ("Beautopia© is a dangerous place...\n"
 | 
			
		||||
               + "Quick, put up a DEFENSE 🛡 before another Degen hacks you, and steals your 💰$GBT.\n"
 | 
			
		||||
               + "Quick, put up a SHIELD 🛡 before another Degen hacks you, and steals your 💰$GBT.\n"
 | 
			
		||||
               + shieldMessage
 | 
			
		||||
               + "To enable it, you need to run the `/shield` slash command.\n\n"
 | 
			
		||||
               + $"Type the `/shield` command now, then select - `{weaponName}`\n")
 | 
			
		||||
@ -60,7 +60,7 @@ let defend (ctx : InteractionContext) =
 | 
			
		||||
let handleDefenseMsg = {
 | 
			
		||||
    ButtonId = "Trainer-3"
 | 
			
		||||
    ButtonText = "Got it"
 | 
			
		||||
    Message = "🎉 Congratulations 🎉\n\n"
 | 
			
		||||
    Message = "🎉 Congratulations\n\n"
 | 
			
		||||
            + "You successfully defended my hack!\n\n"
 | 
			
		||||
            + "Because I tried hacking you when you had your defense up, you stole money from me...\n"
 | 
			
		||||
            + "Defenses only protect you for a LIMITED TIME, so remember to keep at least 1 defense up at all times, or risk getting hacked!"
 | 
			
		||||
@ -77,7 +77,7 @@ let handleDefense (event : ComponentInteractionCreateEventArgs) =
 | 
			
		||||
        do! Async.Sleep 2000
 | 
			
		||||
        do! sendMessage' "Ok, good, let me make sure that worked.\n\nI'll try to **hack** you now"
 | 
			
		||||
        do! Async.Sleep 4000
 | 
			
		||||
        do! sendMessage' $"❌ HACKING FAILED! ❌\n\n{player.Name} defended the hack from <@{GuildEnvironment.botHackerBattle}>, and stole 💰$GBT {Game.ShieldPrize} from them!"
 | 
			
		||||
        do! sendMessage' $"❌ HACKING FAILED!\n\n{player.Name} defended the hack from <@{GuildEnvironment.botHackerBattle}>, and stole 💰$GBT {Game.ShieldPrize} from them!"
 | 
			
		||||
        do! Async.Sleep 3000
 | 
			
		||||
        do! sendFollowUpMessageWithButton event handleDefenseMsg
 | 
			
		||||
    })
 | 
			
		||||
@ -133,15 +133,17 @@ let handleAttack (event : ComponentInteractionCreateEventArgs) =
 | 
			
		||||
        let embed = Embeds.responseSuccessfulHackTrainer hack
 | 
			
		||||
        do! event.Interaction.CreateFollowupMessageAsync(embed) |> Async.AwaitTask |> Async.Ignore
 | 
			
		||||
        do! Async.Sleep 3000
 | 
			
		||||
        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"
 | 
			
		||||
                        + "But remember, hacks take time to recover, so use them wisely.")
 | 
			
		||||
        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"
 | 
			
		||||
               + "But remember, hacks take time to recover, so use them wisely.")
 | 
			
		||||
        do! Async.Sleep 7000
 | 
			
		||||
        do! sendFollowUpMessage event ("Your training is **complete!**\n\n"
 | 
			
		||||
                                    + "But, you’re going to need more **HACKS & DEFENSES** 🛡 to survive in **Beautopia©...**\n"
 | 
			
		||||
                                    + $"You can purchase them from <@{GuildEnvironment.botArmory}>, at <#{GuildEnvironment.channelArmory}> anytime you want...\n\n"
 | 
			
		||||
                                    + "Go there **NOW** to buy **HACKS** & **SHIELDS** before you get hacked! 😱")
 | 
			
		||||
        do! sendFollowUpMessage event
 | 
			
		||||
               ("Your training is **complete!**\n\n"
 | 
			
		||||
               + "But, you’re going to need more **HACKS & SHIELDS** 🛡 to survive in **Beautopia©...**\n"
 | 
			
		||||
               + $"You can purchase them from <@{GuildEnvironment.botArmory}> anytime you want...\n\n"
 | 
			
		||||
               + $"Go to the <#{GuildEnvironment.channelArmory}> **NOW** and type the `/buy-shield` slash command! 😱")
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
let handleButtonEvent (event : ComponentInteractionCreateEventArgs) =
 | 
			
		||||
 | 
			
		||||
@ -76,7 +76,6 @@ module Types =
 | 
			
		||||
          Actions : Action array
 | 
			
		||||
          Bank : int<GBT> }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module Armory =
 | 
			
		||||
    let battleItems =
 | 
			
		||||
        let file = System.IO.File.ReadAllText("Items.json")
 | 
			
		||||
@ -89,9 +88,10 @@ module Player =
 | 
			
		||||
    let shields player = player.Arsenal |> Array.filter (fun bi -> bi.Type = Shield)
 | 
			
		||||
    let attacks player =
 | 
			
		||||
        player.Actions
 | 
			
		||||
        |> Array.choose (fun act -> match act.Type with Attack ar -> Some (act,ar.Target,ar.Result) | Defense -> None)
 | 
			
		||||
    let defenses player = player.Actions |> Array.filter (fun act -> match act.Type with Defense _ -> true | _ -> false)
 | 
			
		||||
        |> Array.filter (fun act -> match act.Type with Attack _ -> true | _ -> false)
 | 
			
		||||
    let defenses player = player.Actions |> Array.filter (fun act -> match act.Type with Defense -> true | _ -> false)
 | 
			
		||||
 | 
			
		||||
    // TODO: I have to fix this, this will remove hacks before the single target cooldown expires
 | 
			
		||||
    let removeExpiredActions actions =
 | 
			
		||||
        actions
 | 
			
		||||
        |> Array.filter (fun (act : Action) ->
 | 
			
		||||
@ -110,12 +110,39 @@ module Messaging =
 | 
			
		||||
        Message : string
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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 battleItemFormat (items : BattleItem array) =
 | 
			
		||||
        match items with
 | 
			
		||||
        | [||] -> "None"
 | 
			
		||||
        | _ -> items |> Array.toList |> List.map (fun i -> i.Name) |> String.concat ", "
 | 
			
		||||
 | 
			
		||||
    let actionFormat (actions : Action array) =
 | 
			
		||||
        match actions with
 | 
			
		||||
        | [||] -> "None"
 | 
			
		||||
        | _ ->
 | 
			
		||||
            actions
 | 
			
		||||
            |> Array.map (fun act ->
 | 
			
		||||
                match act.Type with
 | 
			
		||||
                | Attack atk -> $"Hacked {atk.Target} at {act.Timestamp.ToLongDateString()}"
 | 
			
		||||
                | Defense ->
 | 
			
		||||
                    let item = Armory.getItem act.ActionId
 | 
			
		||||
                    let cooldown = getTimeTillCooldownFinishes (TimeSpan.FromMinutes(int item.Cooldown))
 | 
			
		||||
                    $"{item.Name} active for {cooldown}")
 | 
			
		||||
            |> String.concat "\n"
 | 
			
		||||
 | 
			
		||||
    let statusFormat p =
 | 
			
		||||
        $"Hacks: {Player.hacks p |> Array.toList}
 | 
			
		||||
    Shields: {Player.shields p |> Array.toList}
 | 
			
		||||
    Hack Attacks: {Player.attacks p |> Array.toList}
 | 
			
		||||
    Active Defenses: {Player.defenses p |> Array.toList}
 | 
			
		||||
    Bank: {p.Bank}"
 | 
			
		||||
        $"**Hacks:** {Player.hacks p |> battleItemFormat}\n
 | 
			
		||||
**Shields:** {Player.shields p |> battleItemFormat}\n
 | 
			
		||||
**Hack Attacks:** {Player.attacks p |> actionFormat}\n
 | 
			
		||||
**Active Shields:** {Player.defenses p |> actionFormat}"
 | 
			
		||||
 | 
			
		||||
    let constructButtons (actionType: string) (playerInfo: string) (weapons: BattleItem array) =
 | 
			
		||||
        weapons
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user