New player events model
This commit is contained in:
parent
014862d642
commit
6d7ee2ed16
@ -39,15 +39,18 @@ let constructButtons (actionId: string) (buttonInfo : string) (player: PlayerDat
|
||||
|> Array.map (fun item ->
|
||||
let action =
|
||||
player.Events
|
||||
|> Array.tryFind (fun i -> i.ItemId = item.Id)
|
||||
let btnColor = itemType
|
||||
|> Array.tryFind (fun i ->
|
||||
match i.Type with
|
||||
| Hacking h -> h.HackId = item.Id
|
||||
| Shielding id -> id = item.Id
|
||||
| _ -> false)
|
||||
let btnColor = Game.getClassButtonColor item.Class
|
||||
match action , ignoreCooldown with
|
||||
| None , _ | Some _ , true ->
|
||||
DiscordButtonComponent(Game.getClassButtonColor item.Class, $"{actionId}-{item.Id}-{buttonInfo}-{player.Name}", $"{item.Name}")
|
||||
| Some act , false ->
|
||||
let c = ((Armory.getItem act.ItemId).Cooldown)
|
||||
let time = Messaging.getShortTimeText (TimeSpan.FromMinutes(int c)) act.Timestamp
|
||||
DiscordButtonComponent(Game.getClassButtonColor item.Class, $"{actionId}-{item.Id}", $"{item.Name} ({time} left)", true))
|
||||
DiscordButtonComponent(btnColor, $"{actionId}-{item.Id}-{buttonInfo}-{player.Name}", $"{item.Name}")
|
||||
| Some event , false ->
|
||||
let time = Messaging.getShortTimeText (TimeSpan.FromMinutes(int event.Cooldown)) event.Timestamp
|
||||
DiscordButtonComponent(btnColor, $"{actionId}-{item.Id}", $"{item.Name} ({time} left)", true))
|
||||
|> Seq.cast<DiscordComponent>
|
||||
|
||||
let pickDefense actionId player isTrainer =
|
||||
|
19
Bot/Game.fs
19
Bot/Game.fs
@ -76,10 +76,10 @@ module Player =
|
||||
let getShields (player : PlayerData) = getItems ItemType.Shield player
|
||||
let getHackEvents player =
|
||||
player.Events
|
||||
|> Array.filter (fun act -> match act.Type with PlayerEventType.Hacking -> true | _ -> false && act.ItemId < 12)
|
||||
|> Array.filter (fun act -> match act.Type with PlayerEventType.Hacking _ -> true | _ -> false)
|
||||
let getShieldEvents player =
|
||||
player.Events
|
||||
|> Array.filter (fun act -> match act.Type with PlayerEventType.Shielding -> true | _ -> false && act.ItemId < 12)
|
||||
|> Array.filter (fun act -> match act.Type with PlayerEventType.Shielding _ -> true | _ -> false)
|
||||
|
||||
let removeExpiredActions player =
|
||||
let actions =
|
||||
@ -102,14 +102,17 @@ module Arsenal =
|
||||
| [||] -> "None"
|
||||
| _ -> actions
|
||||
|> Array.map (fun act ->
|
||||
let item = Armory.getItem act.ItemId
|
||||
match act.Type with
|
||||
| PlayerEventType.Hacking ->
|
||||
| Hacking h ->
|
||||
let item = Armory.getItem h.HackId
|
||||
let cooldown = Messaging.getTimeText false Game.SameTargetAttackCooldown act.Timestamp
|
||||
$"Hacked {act.Adversary.Name} with {item.Name} {cooldown} ago"
|
||||
| _ ->
|
||||
let cooldown = Messaging.getTimeText true (System.TimeSpan.FromMinutes(int item.Cooldown)) act.Timestamp
|
||||
$"{item.Name} Shield active for {cooldown}")
|
||||
$"Hacked {h.Adversary.Name} with {item.Name} {cooldown} ago"
|
||||
| Shielding id ->
|
||||
let item = Armory.getItem id
|
||||
let cooldown = Messaging.getTimeText true (System.TimeSpan.FromMinutes(int act.Cooldown)) act.Timestamp
|
||||
$"{item.Name} Shield active for {cooldown}"
|
||||
| _ -> "")
|
||||
|> Array.filter (System.String.IsNullOrWhiteSpace)
|
||||
|> String.concat "\n"
|
||||
|
||||
let statusFormat p =
|
||||
|
@ -16,7 +16,10 @@ let checkPlayerIsAttackingThemselves defender attacker =
|
||||
|
||||
let checkAlreadyHackedTarget defender attacker =
|
||||
defender.Events
|
||||
|> Array.tryFind (fun event -> event.Adversary.Id = attacker.DiscordId && event.IsInstigator = false)
|
||||
|> Array.tryFind (fun event ->
|
||||
match event.Type with
|
||||
| Hacking h -> h.Adversary.Id = attacker.DiscordId && h.IsInstigator = false
|
||||
| _ -> false)
|
||||
|> function
|
||||
| Some event ->
|
||||
let cooldown = getTimeText true Game.SameTargetAttackCooldown event.Timestamp
|
||||
@ -24,9 +27,13 @@ let checkAlreadyHackedTarget defender attacker =
|
||||
| None -> Ok attacker
|
||||
|
||||
let checkWeaponHasCooldown (weapon : Item) attacker =
|
||||
let cooldown = attacker.Events |> Array.tryFind (fun a -> a.ItemId = weapon.Id)
|
||||
match cooldown with
|
||||
| Some event ->
|
||||
attacker.Events
|
||||
|> Array.tryPick (fun a ->
|
||||
match a.Type with
|
||||
| Hacking h -> if h.HackId = weapon.Id then Some ( h , a ) else None
|
||||
| _ -> None)
|
||||
|> function
|
||||
| Some ( _ , event ) ->
|
||||
let cooldown = getTimeText true (TimeSpan.FromMinutes(int event.Cooldown)) event.Timestamp
|
||||
Error $"{weapon.Name} is still active, it will expire in {cooldown}."
|
||||
| None -> Ok attacker
|
||||
@ -59,20 +66,21 @@ let calculateDamage (hack : Item) (shield : Item) =
|
||||
let runHackerBattle defender hack =
|
||||
defender
|
||||
|> Player.removeExpiredActions
|
||||
|> Player.getShieldEvents
|
||||
|> Array.map (fun dfn -> Armory.battleItems |> Array.find (fun w -> w.Id = dfn.ItemId))
|
||||
|> Array.map (calculateDamage (hack))
|
||||
|> fun p -> p.Events
|
||||
|> Array.choose (fun event ->
|
||||
match event.Type with
|
||||
| Shielding id -> Armory.battleItems |> Array.find (fun w -> w.Id = id) |> Some
|
||||
| _ -> None)
|
||||
|> Array.map (calculateDamage hack)
|
||||
|> Array.contains Weak
|
||||
|
||||
let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerData) (hack : Item) prize =
|
||||
let updatePlayer amount attack p =
|
||||
{ p with Events = Array.append [| attack |] p.Events ; Bank = max (p.Bank + amount) 0<GBT> }
|
||||
let event isDefenderEvent = {
|
||||
ItemId = hack.Id
|
||||
Type = PlayerEventType.Hacking
|
||||
let event isDefenderEvent =
|
||||
let hackEvent = {
|
||||
HackId = hack.Id
|
||||
Adversary = if isDefenderEvent then attacker.basicPlayer else defender.basicPlayer
|
||||
Cooldown = if isDefenderEvent then Game.SameTargetAttackCooldown.Minutes * 1<mins> else hack.Cooldown
|
||||
Timestamp = DateTime.UtcNow
|
||||
IsInstigator = not isDefenderEvent
|
||||
Result =
|
||||
match successfulHack , isDefenderEvent with
|
||||
@ -81,6 +89,9 @@ let updateCombatants successfulHack (attacker : PlayerData) (defender : PlayerDa
|
||||
| true , false -> PlayerEventResult.Positive
|
||||
| false , false -> PlayerEventResult.Negative
|
||||
}
|
||||
{ Type = Hacking hackEvent
|
||||
Timestamp = DateTime.UtcNow
|
||||
Cooldown = if isDefenderEvent then Game.SameTargetAttackCooldown.Minutes * 1<mins> else hack.Cooldown }
|
||||
|
||||
[ DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer prize (event false) attacker
|
||||
DbService.updatePlayer GuildEnvironment.pgDb <| updatePlayer -prize (event true) defender ]
|
||||
@ -182,13 +193,9 @@ let handleDefense (ctx : IDiscordContext) =
|
||||
let embed = Embeds.responseCreatedShield shield
|
||||
do! ctx.FollowUp embed |> Async.AwaitTask
|
||||
let defense = {
|
||||
ItemId = shieldId
|
||||
Type = PlayerEventType.Shielding
|
||||
Result = PlayerEventResult.Positive
|
||||
Timestamp = DateTime.UtcNow
|
||||
Type = Shielding shieldId
|
||||
Cooldown = shield.Cooldown
|
||||
IsInstigator = true
|
||||
Adversary = DiscordPlayer.empty
|
||||
Timestamp = DateTime.UtcNow
|
||||
}
|
||||
do! DbService.updatePlayer GuildEnvironment.pgDb <| { p with Events = Array.append [| defense |] p.Events }
|
||||
|> Async.Ignore
|
||||
|
@ -68,10 +68,7 @@ let handleSell (ctx : IDiscordContext) itemId =
|
||||
player with
|
||||
Bank = player.Bank + item.Price
|
||||
Inventory = player.Inventory |> Array.filter (fun i -> i.Id <> itemId)
|
||||
Events =
|
||||
if item.Type = ItemType.Shield
|
||||
then player.Events |> Array.filter (fun a -> a.ItemId <> itemId)
|
||||
else player.Events
|
||||
Events = player.Events |> Array.filter (fun e -> match e.Type with Shielding _ -> true | _ -> false)
|
||||
}
|
||||
do! DbService.updatePlayer GuildEnvironment.pgDb updatedPlayer
|
||||
|> Async.Ignore
|
||||
|
35
Bot/Thief.fs
35
Bot/Thief.fs
@ -66,11 +66,13 @@ let getResultEmbed chance prize (bank : int<GBT>) thief (victim : DiscordPlayer)
|
||||
.WithDescription(msg)
|
||||
.WithImageUrl(img)
|
||||
|
||||
// TODO: See if we are going to keep this
|
||||
let checkVictimStealingCooldown defender attacker =
|
||||
defender
|
||||
|> Player.removeExpiredActions
|
||||
|> fun p -> p.Events
|
||||
|> Array.tryFind (fun pe -> pe.Type = PlayerEventType.Steal && pe.Result = PlayerEventResult.Negative)
|
||||
|> Array.tryFind (fun e ->
|
||||
match e.Type with Stealing _ -> true | _ -> false)
|
||||
|> function
|
||||
| Some act ->
|
||||
let cooldown = VictimRecovery - (DateTime.UtcNow - act.Timestamp)
|
||||
@ -82,7 +84,7 @@ let checkThiefCooldown attacker =
|
||||
attacker
|
||||
|> Player.removeExpiredActions
|
||||
|> fun p -> p.Events
|
||||
|> Array.tryFind (fun pe -> pe.Type = PlayerEventType.Steal)
|
||||
|> Array.tryFind (fun pe -> match pe.Type with Stealing _ -> true | _ -> false)
|
||||
|> function
|
||||
| Some act ->
|
||||
let cooldown = ThiefCooldown - (DateTime.UtcNow - act.Timestamp)
|
||||
@ -104,8 +106,9 @@ let calculateWinPercentage amountRequested bank attackerStrength defenderStrengt
|
||||
|
||||
let steal target amount (ctx : IDiscordContext) =
|
||||
Game.executePlayerActionWithTarget target ctx (fun thief victim -> async { do!
|
||||
thief
|
||||
|> checkVictimStealingCooldown victim
|
||||
// thief
|
||||
// |> checkVictimStealingCooldown victim
|
||||
Ok thief
|
||||
|> handleResultWithResponse ctx (fun _ -> async {
|
||||
let cappedPrize , winPercentage , wasCapped =
|
||||
calculateWinPercentage amount (int victim.Bank) thief.Traits.Strength victim.Traits.Strength
|
||||
@ -149,11 +152,7 @@ let handleSteal (ctx : IDiscordContext) =
|
||||
let num = rand.NextDouble()
|
||||
let dp = { DiscordPlayer.Id = targetId ; DiscordPlayer.Name = targetName }
|
||||
let stealAction result = {
|
||||
ItemId = -1
|
||||
Type = PlayerEventType.Steal
|
||||
Result = result
|
||||
Adversary = dp
|
||||
IsInstigator = true
|
||||
Type = Stealing ( true , dp )
|
||||
Cooldown = ThiefCooldown.Minutes * 1<mins>
|
||||
Timestamp = DateTime.UtcNow
|
||||
}
|
||||
@ -167,12 +166,8 @@ let handleSteal (ctx : IDiscordContext) =
|
||||
match! DbService.tryFindPlayer GuildEnvironment.pgDb targetId with
|
||||
| Some t ->
|
||||
let mugged = {
|
||||
ItemId = -1
|
||||
Type = PlayerEventType.Steal
|
||||
Result = PlayerEventResult.Negative
|
||||
Adversary = thief.basicPlayer
|
||||
Type = Stealing ( false , thief.basicPlayer )
|
||||
Timestamp = DateTime.UtcNow
|
||||
IsInstigator = false
|
||||
Cooldown = VictimRecovery.Minutes * 1<mins>
|
||||
}
|
||||
let actions = t |> Player.removeExpiredActions |> fun p -> Array.append [| mugged |] p.Events
|
||||
@ -181,13 +176,9 @@ let handleSteal (ctx : IDiscordContext) =
|
||||
| None -> ()
|
||||
|
||||
let stole = {
|
||||
ItemId = -1
|
||||
Type = PlayerEventType.Steal
|
||||
Result = PlayerEventResult.Positive
|
||||
Adversary = dp
|
||||
Timestamp = DateTime.UtcNow
|
||||
IsInstigator = true
|
||||
Type = Stealing ( true , dp )
|
||||
Cooldown = ThiefCooldown.Minutes * 1<mins>
|
||||
Timestamp = DateTime.UtcNow
|
||||
}
|
||||
let actions = thief |> Player.removeExpiredActions |> fun p -> Array.append [| stole |] p.Events
|
||||
do! DbService.updatePlayer GuildEnvironment.pgDb { thief with Bank = thief.Bank + prize ; Events = actions }
|
||||
@ -206,8 +197,8 @@ let handleSteal (ctx : IDiscordContext) =
|
||||
Game.executePlayerActionWithTargetId true targetId ctx (fun attacker defender -> async {
|
||||
do! attacker
|
||||
|> Player.removeExpiredActions
|
||||
|> checkVictimStealingCooldown defender
|
||||
>>= checkThiefCooldown
|
||||
// |> checkVictimStealingCooldown defender
|
||||
|> checkThiefCooldown
|
||||
|> handleResultWithResponse ctx (handleYes defender )
|
||||
})
|
||||
else
|
||||
|
@ -15,19 +15,15 @@ let defaultShield = Armory.battleItems |> Array.find (fun i -> i.Id = int Shield
|
||||
|
||||
let TrainerEvents = [|
|
||||
{ Timestamp = System.DateTime.UtcNow
|
||||
Cooldown = 2<mins>
|
||||
Type = Hacking {
|
||||
Adversary = Sensei
|
||||
Type = PlayerEventType.Hacking
|
||||
Result = PlayerEventResult.Positive
|
||||
Cooldown = 5<mins>
|
||||
IsInstigator = true
|
||||
ItemId = defaultHack.Id }
|
||||
HackId = defaultHack.Id } }
|
||||
{ Timestamp = System.DateTime.UtcNow
|
||||
Adversary = DiscordPlayer.empty
|
||||
Type = PlayerEventType.Shielding
|
||||
Result = PlayerEventResult.Positive
|
||||
Cooldown = defaultShield.Cooldown
|
||||
IsInstigator = true
|
||||
ItemId = defaultShield.Id }
|
||||
Type = Shielding defaultShield.Id }
|
||||
|]
|
||||
|
||||
let sendInitialEmbed (client : DiscordClient) =
|
||||
|
@ -73,8 +73,8 @@ let updatePlayer connStr (player : PlayerData) =
|
||||
let addAchievement connStr (did : uint64) (achievement : string) =
|
||||
connStr
|
||||
|> Sql.connect
|
||||
|> Sql.query (
|
||||
"WITH ach AS (INSERT INTO achievement (symbol) VALUES (@symbol) RETURNING id),
|
||||
|> Sql.query
|
||||
("WITH ach AS (INSERT INTO achievement (symbol) VALUES (@symbol) RETURNING id),
|
||||
usr AS (SELECT id FROM \"user\" WHERE discord_id = @did)
|
||||
INSERT INTO user_achievements_achievement (user_id, achievement_id) SELECT usr.id, ach.id FROM usr, ach")
|
||||
|
||||
|
@ -88,23 +88,26 @@ module Types =
|
||||
with static member empty = { Id = 0uL ; Name = "None" }
|
||||
|
||||
type PlayerEventResult =
|
||||
| Positive = 0
|
||||
| Neutral = 1
|
||||
| Negative = 2
|
||||
| Positive
|
||||
| Neutral
|
||||
| Negative
|
||||
|
||||
type HackEvent = {
|
||||
IsInstigator : bool
|
||||
Adversary : DiscordPlayer
|
||||
Result : PlayerEventResult
|
||||
HackId : int
|
||||
}
|
||||
|
||||
type PlayerEventType =
|
||||
| Hacking = 0
|
||||
| Shielding = 1
|
||||
| Steal = 2
|
||||
| Imprison = 3
|
||||
| Hacking of HackEvent
|
||||
| Shielding of shieldId : int
|
||||
| Stealing of instigator : bool * adversary : DiscordPlayer
|
||||
| Imprison
|
||||
|
||||
[<CLIMutable>]
|
||||
type PlayerEvent =
|
||||
{ Type : PlayerEventType
|
||||
Result : PlayerEventResult
|
||||
IsInstigator : bool
|
||||
Adversary : DiscordPlayer
|
||||
ItemId : int
|
||||
Cooldown : int<mins>
|
||||
Timestamp : DateTime }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user