New player events model

This commit is contained in:
Joseph Ferano 2022-02-22 22:53:49 +07:00
parent 014862d642
commit 6d7ee2ed16
8 changed files with 101 additions and 101 deletions

View File

@ -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 =

View File

@ -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 ->
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}")
match act.Type with
| Hacking h ->
let item = Armory.getItem h.HackId
let cooldown = Messaging.getTimeText false Game.SameTargetAttackCooldown act.Timestamp
$"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 =

View File

@ -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,12 +27,16 @@ 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 ->
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
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
let checkHasEmptyHacks attacker =
match Player.getHacks attacker with
@ -59,28 +66,32 @@ 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
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
| true , true -> PlayerEventResult.Negative
| false , true -> PlayerEventResult.Positive
| true , false -> PlayerEventResult.Positive
| false , false -> PlayerEventResult.Negative
}
let event isDefenderEvent =
let hackEvent = {
HackId = hack.Id
Adversary = if isDefenderEvent then attacker.basicPlayer else defender.basicPlayer
IsInstigator = not isDefenderEvent
Result =
match successfulHack , isDefenderEvent with
| true , true -> PlayerEventResult.Negative
| false , true -> PlayerEventResult.Positive
| 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

View File

@ -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

View File

@ -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,14 +152,10 @@ 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
}
}
let getResultEmbed' = getResultEmbed winPercentage prize thief.Bank thief dp
// TODO: Send event to the hall of privacy
// TODO: We need to check if the player is on cooldown
@ -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
Cooldown = ThiefCooldown.Minutes * 1<mins>
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

View File

@ -15,19 +15,15 @@ let defaultShield = Armory.battleItems |> Array.find (fun i -> i.Id = int Shield
let TrainerEvents = [|
{ Timestamp = System.DateTime.UtcNow
Adversary = Sensei
Type = PlayerEventType.Hacking
Result = PlayerEventResult.Positive
Cooldown = 5<mins>
IsInstigator = true
ItemId = defaultHack.Id }
Cooldown = 2<mins>
Type = Hacking {
Adversary = Sensei
Result = PlayerEventResult.Positive
IsInstigator = true
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) =

View File

@ -73,10 +73,10 @@ 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),
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")
|> 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")
|> Sql.parameters [ ( "did" , Sql.string (string did) ) ; ( "achievement", Sql.string achievement ) ]
|> Sql.executeNonQueryAsync

View File

@ -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 }