First pass on thief game
This commit is contained in:
parent
dd33492418
commit
bb9c04fe6e
10
Bot/Bot.fs
10
Bot/Bot.fs
@ -6,6 +6,7 @@ open DSharpPlus.SlashCommands
|
|||||||
open Degenz
|
open Degenz
|
||||||
open Degenz.HackerBattle
|
open Degenz.HackerBattle
|
||||||
open Degenz.Store
|
open Degenz.Store
|
||||||
|
open Degenz.Thief
|
||||||
open Emzi0767.Utilities
|
open Emzi0767.Utilities
|
||||||
//open Degenz.SlotMachine
|
//open Degenz.SlotMachine
|
||||||
|
|
||||||
@ -36,12 +37,13 @@ let storeBot = new DiscordClient(storeConfig)
|
|||||||
//let slotMachineBot = new DiscordClient(slotMachineConfig)
|
//let slotMachineBot = new DiscordClient(slotMachineConfig)
|
||||||
|
|
||||||
//let clients = [| hackerBattleBot ; storeBot ; slotMachineBot |]
|
//let clients = [| hackerBattleBot ; storeBot ; slotMachineBot |]
|
||||||
let sc1 = hackerBattleBot.UseSlashCommands()
|
let hackerCommands = hackerBattleBot.UseSlashCommands()
|
||||||
let sc2 = storeBot.UseSlashCommands()
|
let storeCommands = storeBot.UseSlashCommands()
|
||||||
//let sc3 = slotMachineBot.UseSlashCommands()
|
//let sc3 = slotMachineBot.UseSlashCommands()
|
||||||
|
|
||||||
sc1.RegisterCommands<HackerGame>(guild);
|
hackerCommands.RegisterCommands<HackerGame>(guild);
|
||||||
sc2.RegisterCommands<Store>(guild);
|
hackerCommands.RegisterCommands<StealGame>(guild);
|
||||||
|
storeCommands.RegisterCommands<Store>(guild);
|
||||||
//sc3.RegisterCommands<SlotMachine>(guild);
|
//sc3.RegisterCommands<SlotMachine>(guild);
|
||||||
|
|
||||||
hackerBattleBot.add_ComponentInteractionCreated(AsyncEventHandler(HackerBattle.handleButtonEvent))
|
hackerBattleBot.add_ComponentInteractionCreated(AsyncEventHandler(HackerBattle.handleButtonEvent))
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
<Compile Include="PlayerInteractions.fs" />
|
<Compile Include="PlayerInteractions.fs" />
|
||||||
<Compile Include="Embeds.fs" />
|
<Compile Include="Embeds.fs" />
|
||||||
<Compile Include="Store.fs" />
|
<Compile Include="Store.fs" />
|
||||||
|
<Compile Include="Thief.fs" />
|
||||||
|
<Compile Include="SlotMachine.fs" />
|
||||||
<Compile Include="Trainer.fs" />
|
<Compile Include="Trainer.fs" />
|
||||||
<Compile Include="HackerBattle.fs" />
|
<Compile Include="HackerBattle.fs" />
|
||||||
<Compile Include="SlotMachine.fs" />
|
|
||||||
<Compile Include="Bot.fs" />
|
<Compile Include="Bot.fs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
19
Bot/Game.fs
19
Bot/Game.fs
@ -38,7 +38,24 @@ module Game =
|
|||||||
let! playerResult = tryFindPlayer (ctx.GetDiscordMember().Id)
|
let! playerResult = tryFindPlayer (ctx.GetDiscordMember().Id)
|
||||||
match playerResult with
|
match playerResult with
|
||||||
| Some player -> do! dispatch player
|
| Some player -> do! dispatch player
|
||||||
| None -> do! Messaging.sendSimpleResponse ctx "You are currently not a hacker, first use the /redpill command to become one"
|
| None -> do! Messaging.sendFollowUpMessage ctx "You are currently not a hacker, first use the /redpill command to become one"
|
||||||
|
} |> Async.StartAsTask :> Task
|
||||||
|
|
||||||
|
let executePlayerWithTargetAction (targetPlayer : DiscordUser) (ctx : IDiscordContext) (dispatch : PlayerData -> PlayerData -> Async<unit>) =
|
||||||
|
async {
|
||||||
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
|
builder.IsEphemeral <- true
|
||||||
|
builder.Content <- "Content"
|
||||||
|
do! ctx.Respond InteractionResponseType.DeferredChannelMessageWithSource builder |> Async.AwaitTask
|
||||||
|
let! playerResult = tryFindPlayer (ctx.GetDiscordMember().Id)
|
||||||
|
let! targetResult = tryFindPlayer targetPlayer.Id
|
||||||
|
match playerResult , targetResult with
|
||||||
|
| Some player , Some target -> do! dispatch player target
|
||||||
|
| None , _ -> do! Messaging.sendFollowUpMessage ctx "You are currently not a hacker, first use the /redpill command to become one"
|
||||||
|
| _ , None ->
|
||||||
|
if targetPlayer.IsBot
|
||||||
|
then do! Messaging.sendFollowUpMessage ctx $"{targetPlayer.Username} is a bot, pick a real human to hack"
|
||||||
|
else do! Messaging.sendFollowUpMessage ctx "Your target is not connected to the network, they must join first by using the /redpill command"
|
||||||
} |> Async.StartAsTask :> Task
|
} |> Async.StartAsTask :> Task
|
||||||
|
|
||||||
module Player =
|
module Player =
|
||||||
|
@ -120,26 +120,18 @@ let failedHack (ctx : IDiscordContext) attacker defender hack =
|
|||||||
}
|
}
|
||||||
|
|
||||||
let attack (target : DiscordUser) (ctx : IDiscordContext) =
|
let attack (target : DiscordUser) (ctx : IDiscordContext) =
|
||||||
Game.executePlayerAction ctx (fun attacker -> async {
|
Game.executePlayerWithTargetAction target ctx (fun attacker defender -> async {
|
||||||
let! defender = DbService.tryFindPlayer target.Id
|
do! attacker
|
||||||
match defender with
|
|> checkAlreadyHackedTarget defender.DiscordId
|
||||||
| Some defender ->
|
<!> (Player.removeExpiredActions true)
|
||||||
do! attacker
|
>>= checkHasEmptyHacks
|
||||||
|> checkAlreadyHackedTarget defender.DiscordId
|
>>= checkTargetHasMoney defender
|
||||||
<!> (Player.removeExpiredActions true)
|
>>= checkPlayerIsAttackingThemselves defender
|
||||||
>>= checkHasEmptyHacks
|
|> function
|
||||||
>>= checkTargetHasMoney defender
|
| Ok atkr ->
|
||||||
>>= checkPlayerIsAttackingThemselves defender
|
let embed = Embeds.pickHack "Attack" atkr defender false
|
||||||
|> function
|
ctx.FollowUp(embed) |> Async.AwaitTask
|
||||||
| Ok atkr ->
|
| Error msg -> sendFollowUpMessage ctx msg
|
||||||
let embed = Embeds.pickHack "Attack" atkr defender false
|
|
||||||
ctx.FollowUp(embed) |> Async.AwaitTask
|
|
||||||
| Error msg -> sendFollowUpMessage ctx msg
|
|
||||||
| None ->
|
|
||||||
if target.IsBot
|
|
||||||
then do! sendFollowUpMessage ctx $"{target.Username} is a bot, pick a real human to hack"
|
|
||||||
else do! sendFollowUpMessage ctx "Your target is not connected to the network, they must join first by using the /redpill command"
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
let handleAttack (ctx : IDiscordContext) =
|
let handleAttack (ctx : IDiscordContext) =
|
||||||
@ -208,6 +200,7 @@ let handleButtonEvent (_ : DiscordClient) (event : ComponentInteractionCreateEve
|
|||||||
| id when id.StartsWith("Attack") -> handleAttack eventCtx
|
| id when id.StartsWith("Attack") -> handleAttack eventCtx
|
||||||
| id when id.StartsWith("Defend") -> handleDefense eventCtx
|
| id when id.StartsWith("Defend") -> handleDefense eventCtx
|
||||||
| id when id.StartsWith("Trainer") -> Trainer.handleButtonEvent eventCtx |> Async.StartAsTask :> Task
|
| id when id.StartsWith("Trainer") -> Trainer.handleButtonEvent eventCtx |> Async.StartAsTask :> Task
|
||||||
|
| id when id.StartsWith("Steal") -> Thief.handleSteal eventCtx
|
||||||
| _ ->
|
| _ ->
|
||||||
task {
|
task {
|
||||||
let builder = DiscordInteractionResponseBuilder()
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
|
@ -16,6 +16,8 @@ module Commands =
|
|||||||
Name = nickname
|
Name = nickname
|
||||||
Arsenal = [| hack ; shield |]
|
Arsenal = [| hack ; shield |]
|
||||||
Actions = [||]
|
Actions = [||]
|
||||||
|
XP = 0
|
||||||
|
Stats = PlayerStats.empty
|
||||||
Bank = 100<GBT> }
|
Bank = 100<GBT> }
|
||||||
|
|
||||||
let addHackerRole (ctx : InteractionContext) =
|
let addHackerRole (ctx : InteractionContext) =
|
||||||
|
102
Bot/Thief.fs
Normal file
102
Bot/Thief.fs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
module Degenz.Thief
|
||||||
|
|
||||||
|
open System
|
||||||
|
open System.Threading.Tasks
|
||||||
|
open DSharpPlus
|
||||||
|
open DSharpPlus.Entities
|
||||||
|
open DSharpPlus.SlashCommands
|
||||||
|
open Degenz.Messaging
|
||||||
|
|
||||||
|
let getRandomStealBtnLabels () =
|
||||||
|
let rand = Random(Guid.NewGuid().GetHashCode())
|
||||||
|
let affirmative = [| "LFG" ; "YOLO" ; "IDGAF" |]
|
||||||
|
let negative = [| "NOPE" ; "IM OUT" ; "BAIL" |]
|
||||||
|
( affirmative.[rand.Next(0, 3)] , negative.[rand.Next(0, 3)] )
|
||||||
|
|
||||||
|
let chanceOfSuccessMsg = function
|
||||||
|
| amt when amt < 0.20 -> "Looking pretty bad"
|
||||||
|
| amt when amt < 0.50 -> "I mean, maybe"
|
||||||
|
| amt when amt < 0.80 -> "I think you got this"
|
||||||
|
| _ -> "Totally worth it"
|
||||||
|
|
||||||
|
let targetEvaluationMsg = function
|
||||||
|
| amt when amt < 0.20 -> "but man, they look swole."
|
||||||
|
| amt when amt < 0.50 -> "but they look a little confident"
|
||||||
|
| amt when amt < 0.80 -> "and they're looking a little nervous"
|
||||||
|
| _ -> "and they look weak af man"
|
||||||
|
|
||||||
|
let payoutChance targetBank chance = targetBank * 0.1 * (1.0 - chance)
|
||||||
|
|
||||||
|
let getStealEmbed chance (target : PlayerData) (player : PlayerData) =
|
||||||
|
let buttons =
|
||||||
|
let yes , no = getRandomStealBtnLabels ()
|
||||||
|
[ DiscordButtonComponent(ButtonStyle.Success, $"Steal-yes-{target.DiscordId}-{target.Name}-{chance}", yes)
|
||||||
|
DiscordButtonComponent(ButtonStyle.Danger, $"Steal-no", no) ]
|
||||||
|
|> Seq.cast<DiscordComponent>
|
||||||
|
let embed =
|
||||||
|
DiscordEmbedBuilder()
|
||||||
|
.AddField("Chance of Success", $"{chanceOfSuccessMsg chance}", true)
|
||||||
|
.WithDescription($"{target.Name} is coming towards you in a dark alley, {targetEvaluationMsg chance}")
|
||||||
|
.WithImageUrl("https://cdnb.artstation.com/p/assets/images/images/017/553/457/large/maarten-hof-backalley-mainshot.jpg")
|
||||||
|
.WithTitle($"Steal Money")
|
||||||
|
|
||||||
|
DiscordFollowupMessageBuilder()
|
||||||
|
.AddEmbed(embed)
|
||||||
|
.AddComponents(buttons)
|
||||||
|
.AsEphemeral(true)
|
||||||
|
|
||||||
|
|
||||||
|
let steal target (ctx : IDiscordContext) =
|
||||||
|
Game.executePlayerWithTargetAction target ctx (fun attacker defender -> async {
|
||||||
|
let winPercentage = if attacker.Stats.Strength > defender.Stats.Strength then 1.0 else 0.0
|
||||||
|
let embed = getStealEmbed winPercentage defender attacker
|
||||||
|
|
||||||
|
do! ctx.FollowUp(embed) |> Async.AwaitTask
|
||||||
|
})
|
||||||
|
|
||||||
|
let handleSteal (ctx : IDiscordContext) =
|
||||||
|
let split = ctx.GetInteractionId().Split("-")
|
||||||
|
let answer = split.[1]
|
||||||
|
if answer = "yes" then
|
||||||
|
Game.executePlayerAction ctx (fun player -> async {
|
||||||
|
let targetId = uint64 split.[2]
|
||||||
|
let targetName = split.[3]
|
||||||
|
let chance = double split.[4]
|
||||||
|
|
||||||
|
let rand = Random(Guid.NewGuid().GetHashCode())
|
||||||
|
let result = rand.NextDouble()
|
||||||
|
|
||||||
|
if chance >= result then
|
||||||
|
let! target = DbService.tryFindPlayer targetId
|
||||||
|
do! Messaging.sendFollowUpMessage ctx $"You stole {targetName} money"
|
||||||
|
else
|
||||||
|
do! Messaging.sendFollowUpMessage ctx "You failed miserably"
|
||||||
|
|
||||||
|
return ()
|
||||||
|
})
|
||||||
|
else
|
||||||
|
async {
|
||||||
|
let builder = DiscordInteractionResponseBuilder()
|
||||||
|
builder.Content <- "I thought better of it"
|
||||||
|
do! ctx.Respond InteractionResponseType.UpdateMessage builder |> Async.AwaitTask
|
||||||
|
} |> Async.StartAsTask :> Task
|
||||||
|
|
||||||
|
|
||||||
|
type StealGame() =
|
||||||
|
inherit ApplicationCommandModule ()
|
||||||
|
|
||||||
|
let enforceChannel (ctx : IDiscordContext) (storeFn : IDiscordContext -> Task) =
|
||||||
|
match ctx.GetChannel().Id with
|
||||||
|
| id when id = GuildEnvironment.channelArmory -> storeFn ctx
|
||||||
|
| _ ->
|
||||||
|
task {
|
||||||
|
let msg = $"You must go to <#{GuildEnvironment.channelArmory}> channel to buy or sell weapons"
|
||||||
|
do! Messaging.sendSimpleResponse ctx msg
|
||||||
|
}
|
||||||
|
|
||||||
|
[<SlashCommand("steal", "Steal some money from another player, but you might go to prison if caught")>]
|
||||||
|
member this.Steal (ctx : InteractionContext, [<Option("target", "Who do you want to steal from?")>] target : DiscordUser) =
|
||||||
|
// enforceChannel (DiscordInteractionContext ctx) (steal target)
|
||||||
|
steal target (DiscordInteractionContext ctx)
|
||||||
|
|
||||||
|
|
@ -67,6 +67,8 @@ let private mapBack (player : PlayerEntry) : PlayerData = {
|
|||||||
let atks = player.Attacks |> Array.map attackToAction
|
let atks = player.Attacks |> Array.map attackToAction
|
||||||
let dfns = player.Defenses |> Array.map defenseToAction
|
let dfns = player.Defenses |> Array.map defenseToAction
|
||||||
Array.append atks dfns
|
Array.append atks dfns
|
||||||
|
Stats = PlayerStats.empty
|
||||||
|
XP = 0
|
||||||
Bank = player.Bank * 1<GBT>
|
Bank = player.Bank * 1<GBT>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,12 +74,31 @@ module Types =
|
|||||||
Type : ActionType
|
Type : ActionType
|
||||||
Timestamp : DateTime }
|
Timestamp : DateTime }
|
||||||
|
|
||||||
|
type StatAmount = int
|
||||||
|
type XPAmount = int
|
||||||
|
|
||||||
|
type AttributeId =
|
||||||
|
| Strength = 0
|
||||||
|
| Cunning = 1
|
||||||
|
|
||||||
|
type PlayerStats = {
|
||||||
|
Strength : int
|
||||||
|
Focus : int
|
||||||
|
}
|
||||||
|
with static member empty = { Strength = 0 ; Focus = 0 }
|
||||||
|
|
||||||
|
type PlayerXP = {
|
||||||
|
Amount : XPAmount
|
||||||
|
}
|
||||||
|
|
||||||
[<CLIMutable>]
|
[<CLIMutable>]
|
||||||
type PlayerData =
|
type PlayerData =
|
||||||
{ DiscordId : uint64
|
{ DiscordId : uint64
|
||||||
Name : string
|
Name : string
|
||||||
Arsenal : BattleItem array
|
Arsenal : BattleItem array
|
||||||
Actions : Action array
|
Actions : Action array
|
||||||
|
Stats : PlayerStats
|
||||||
|
XP : int
|
||||||
Bank : int<GBT> }
|
Bank : int<GBT> }
|
||||||
|
|
||||||
module Armory =
|
module Armory =
|
||||||
@ -175,6 +194,15 @@ module Messaging =
|
|||||||
do! ctx.FollowUp(builder) |> Async.AwaitTask
|
do! ctx.FollowUp(builder) |> Async.AwaitTask
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let sendFollowUpEmbed (ctx : IDiscordContext) embed =
|
||||||
|
async {
|
||||||
|
let builder =
|
||||||
|
DiscordFollowupMessageBuilder()
|
||||||
|
.AsEphemeral(true)
|
||||||
|
.AddEmbed(embed)
|
||||||
|
do! ctx.FollowUp(builder) |> Async.AwaitTask
|
||||||
|
}
|
||||||
|
|
||||||
let sendFollowUpMessageWithButton (ctx : IDiscordContext) interactiveMessage =
|
let sendFollowUpMessageWithButton (ctx : IDiscordContext) interactiveMessage =
|
||||||
async {
|
async {
|
||||||
let builder = DiscordFollowupMessageBuilder()
|
let builder = DiscordFollowupMessageBuilder()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user