From 1312d9b0b808acc950e935fe4c072724c2271cbb Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 15:29:10 -0500 Subject: [PATCH 01/10] chore: Update global usings --- src/Application/Usings.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Application/Usings.cs b/src/Application/Usings.cs index ea957b85..8e649a92 100644 --- a/src/Application/Usings.cs +++ b/src/Application/Usings.cs @@ -29,6 +29,7 @@ global using CTF.Application.Teams; global using CTF.Application.Teams.ClassSelection; global using CTF.Application.Teams.Flags; +global using CTF.Application.Teams.Flags.Events; global using CTF.Application.Teams.Services; global using CTF.Application.Maps; global using CTF.Application.Maps.Services; \ No newline at end of file From 7075b54856bef3ca945303420d62d72e180a3d7c Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 15:49:32 -0500 Subject: [PATCH 02/10] chore: Add new resources --- .../Common/Resources/Messages.Designer.cs | 72 +++++++++++++++++++ .../Common/Resources/Messages.resx | 24 +++++++ 2 files changed, 96 insertions(+) diff --git a/src/Application/Common/Resources/Messages.Designer.cs b/src/Application/Common/Resources/Messages.Designer.cs index c6d44a0c..b51cc955 100644 --- a/src/Application/Common/Resources/Messages.Designer.cs +++ b/src/Application/Common/Resources/Messages.Designer.cs @@ -87,6 +87,15 @@ internal static string BetaIsWinner { } } + /// + /// Looks up a localized string similar to ~n~~n~~n~~b~The blue flag is not at its base position. + /// + internal static string BlueFlagIsNotAtBasePosition { + get { + return ResourceManager.GetString("BlueFlagIsNotAtBasePosition", resourceCulture); + } + } + /// /// Looks up a localized string similar to {PlayerName} has had {Kills} consecutive kills without dying. /// @@ -330,6 +339,60 @@ internal static string NoPermissions { } } + /// + /// Looks up a localized string similar to ~n~~n~~n~Defend this flag from enemy capture!. + /// + internal static string OnFlagAtBasePosition { + get { + return ResourceManager.GetString("OnFlagAtBasePosition", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {PlayerName} has captured the {TeamName} team's {ColorName} flag! Keep an eye on the score!. + /// + internal static string OnFlagCaptured { + get { + return ResourceManager.GetString("OnFlagCaptured", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {PlayerName} has dropped the {TeamName} team's {ColorName} flag! Retrieve it before the enemy does!. + /// + internal static string OnFlagDropped { + get { + return ResourceManager.GetString("OnFlagDropped", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {PlayerName} has returned the {TeamName} team's {ColorName} flag to its base! Keep up the defense!. + /// + internal static string OnFlagReturned { + get { + return ResourceManager.GetString("OnFlagReturned", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {PlayerName} scored a point for the {TeamName} team by bringing the {RivalName} flag back to {TeamName} team's base!. + /// + internal static string OnFlagScore { + get { + return ResourceManager.GetString("OnFlagScore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {PlayerName} has taken the {TeamName} team's {ColorName} flag! Keep an eye on the score!. + /// + internal static string OnFlagTaken { + get { + return ResourceManager.GetString("OnFlagTaken", resourceCulture); + } + } + /// /// Looks up a localized string similar to Password cannot be empty. /// @@ -402,6 +465,15 @@ internal static string RedeemedPoints { } } + /// + /// Looks up a localized string similar to ~n~~n~~n~~r~The red flag is not at its base position. + /// + internal static string RedFlagIsNotAtBasePosition { + get { + return ResourceManager.GetString("RedFlagIsNotAtBasePosition", resourceCulture); + } + } + /// /// Looks up a localized string similar to A spawn location can only be obtained for the alpha or beta team. /// diff --git a/src/Application/Common/Resources/Messages.resx b/src/Application/Common/Resources/Messages.resx index 2c8d567f..bd08c7e4 100644 --- a/src/Application/Common/Resources/Messages.resx +++ b/src/Application/Common/Resources/Messages.resx @@ -126,6 +126,9 @@ This round was won by the Beta team + + ~n~~n~~n~~b~The blue flag is not at its base position + {PlayerName} has had {Kills} consecutive kills without dying @@ -207,6 +210,24 @@ You do not have permissions to use this command + + ~n~~n~~n~Defend this flag from enemy capture! + + + {PlayerName} has captured the {TeamName} team's {ColorName} flag! Keep an eye on the score! + + + {PlayerName} has dropped the {TeamName} team's {ColorName} flag! Retrieve it before the enemy does! + + + {PlayerName} has returned the {TeamName} team's {ColorName} flag to its base! Keep up the defense! + + + {PlayerName} scored a point for the {TeamName} team by bringing the {RivalName} flag back to {TeamName} team's base! + + + {PlayerName} has taken the {TeamName} team's {ColorName} flag! Keep an eye on the score! + Password cannot be empty @@ -231,6 +252,9 @@ {PlayerName} redeemed their points for the combo: {ComboName} + + ~n~~n~~n~~r~The red flag is not at its base position + A spawn location can only be obtained for the alpha or beta team From 7d93fc03f78d62caa04906de2ab2c74c390d6d68 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 15:52:05 -0500 Subject: [PATCH 03/10] feat: Use pickup models that are exterior markers --- src/Application/Teams/PickupInfo.cs | 10 ++++++++++ src/Application/Teams/Services/TeamPickupService.cs | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/Application/Teams/PickupInfo.cs diff --git a/src/Application/Teams/PickupInfo.cs b/src/Application/Teams/PickupInfo.cs new file mode 100644 index 00000000..ac1f86b0 --- /dev/null +++ b/src/Application/Teams/PickupInfo.cs @@ -0,0 +1,10 @@ +namespace CTF.Application.Teams; + +/// +/// See +/// +public enum PickupInfo +{ + Red = 19605, + Blue = 19607 +} diff --git a/src/Application/Teams/Services/TeamPickupService.cs b/src/Application/Teams/Services/TeamPickupService.cs index 8396d208..254a4c84 100644 --- a/src/Application/Teams/Services/TeamPickupService.cs +++ b/src/Application/Teams/Services/TeamPickupService.cs @@ -82,7 +82,7 @@ public void CreatePickupWithInfo(Team team) if (team.Id == TeamId.Alpha) { _alphaPickupInfo = _worldService.CreatePickup( - model: 1239, + model: (int)PickupInfo.Red, type: PickupType.ScriptedActionsOnlyEveryFewSeconds, position: currentMap.FlagLocations.Red ); @@ -90,7 +90,7 @@ public void CreatePickupWithInfo(Team team) else if(team.Id == TeamId.Beta) { _betaPickupInfo = _worldService.CreatePickup( - model: 1239, + model: (int)PickupInfo.Blue, type: PickupType.ScriptedActionsOnlyEveryFewSeconds, position: currentMap.FlagLocations.Blue ); From b8f3d266c09de5a68bea15df82cd294de7ecd578 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 15:53:31 -0500 Subject: [PATCH 04/10] fix: Destroy all pickups and icons when the map is loading --- src/Application/Maps/Services/MapRotationService.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Application/Maps/Services/MapRotationService.cs b/src/Application/Maps/Services/MapRotationService.cs index 32d5dd2a..9f9c5fd5 100644 --- a/src/Application/Maps/Services/MapRotationService.cs +++ b/src/Application/Maps/Services/MapRotationService.cs @@ -104,8 +104,10 @@ private void OnLoadingMap() _worldService.SendClientMessage(Color.Orange, message); IMap nextMap = currentMap.NextMap; _mapInfoService.Load(nextMap); + _teamPickupService.DestroyAllPickups(); _teamPickupService.CreateFlagFromBasePosition(Team.Alpha); _teamPickupService.CreateFlagFromBasePosition(Team.Beta); + _teamIconService.DestroyAll(); _teamIconService.CreateFromBasePosition(Team.Alpha); _teamIconService.CreateFromBasePosition(Team.Beta); _serverService.SendRconCommand($"loadfs {nextMap.Name}"); From cf68a27f825a04044e3ced116100d4b3a29f124f Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 15:58:27 -0500 Subject: [PATCH 05/10] fix: Remove the flag carrier when the map is loading --- src/Application/Maps/Services/MapRotationService.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Application/Maps/Services/MapRotationService.cs b/src/Application/Maps/Services/MapRotationService.cs index 9f9c5fd5..f04d53ef 100644 --- a/src/Application/Maps/Services/MapRotationService.cs +++ b/src/Application/Maps/Services/MapRotationService.cs @@ -104,6 +104,8 @@ private void OnLoadingMap() _worldService.SendClientMessage(Color.Orange, message); IMap nextMap = currentMap.NextMap; _mapInfoService.Load(nextMap); + Team.Alpha.Flag.RemoveCarrier(); + Team.Beta.Flag.RemoveCarrier(); _teamPickupService.DestroyAllPickups(); _teamPickupService.CreateFlagFromBasePosition(Team.Alpha); _teamPickupService.CreateFlagFromBasePosition(Team.Beta); From 10df2e69ba5f82fdff06e97b22d7108dfaa44681 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 16:00:04 -0500 Subject: [PATCH 06/10] refactor: Change a team's color name to lowercase --- src/Application/Teams/Team.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Application/Teams/Team.cs b/src/Application/Teams/Team.cs index dfe1e2b9..7b1ead88 100644 --- a/src/Application/Teams/Team.cs +++ b/src/Application/Teams/Team.cs @@ -13,7 +13,7 @@ static Team() Id = TeamId.Alpha, SkinId = SkinTeamId.Alpha, Name = "Alpha", - ColorName = "Red", + ColorName = "red", GameText = "~r~", ColorHex = new Color(255, 32, 64, 00), Sounds = TeamSounds.Alpha, @@ -31,7 +31,7 @@ static Team() Id = TeamId.Beta, SkinId = SkinTeamId.Beta, Name = "Beta", - ColorName = "Blue", + ColorName = "blue", GameText = "~b~", ColorHex = new Color(0, 136, 255, 00), Sounds = TeamSounds.Beta, @@ -51,7 +51,7 @@ static Team() Id = TeamId.NoTeam, SkinId = SkinTeamId.NoTeam, Name = "NoTeam", - ColorName = "White", + ColorName = "white", GameText = "~w~", ColorHex = new Color(255, 255, 255, 00), Sounds = TeamSounds.None, From 48bdb65bb585ab5461d46db9c7df433e3ebe3bfd Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 16:02:46 -0500 Subject: [PATCH 07/10] feat: Implement a service to play team sounds for players --- .../Teams/Services/TeamSoundsService.cs | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/Application/Teams/Services/TeamSoundsService.cs diff --git a/src/Application/Teams/Services/TeamSoundsService.cs b/src/Application/Teams/Services/TeamSoundsService.cs new file mode 100644 index 00000000..00a7e405 --- /dev/null +++ b/src/Application/Teams/Services/TeamSoundsService.cs @@ -0,0 +1,35 @@ +namespace CTF.Application.Teams.Services; + +public class TeamSoundsService +{ + /// + /// Plays the sound when the team's flag is taken. + /// + public void PlayFlagTakenSound(Team team) + => PlayAudioStreamToAll(team.Sounds.FlagTaken); + + /// + /// Plays the sound when the team's flag is dropped. + /// + public void PlayFlagDroppedSound(Team team) + => PlayAudioStreamToAll(team.Sounds.FlagDropped); + + /// + /// Plays the sound when the team's flag is returned. + /// + public void PlayFlagReturnedSound(Team team) + => PlayAudioStreamToAll(team.Sounds.FlagReturned); + + /// + /// Plays the sound when the team scores. + /// + public void PlayTeamScoresSound(Team team) + => PlayAudioStreamToAll(team.Sounds.TeamScores); + + private void PlayAudioStreamToAll(string url) + { + IEnumerable players = AlphaBetaTeamPlayers.GetAll(); + foreach (Player player in players) + player.PlayAudioStream(url); + } +} From c81fc9ed730a39d008ac0aa3727b1322add04715 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 18:13:21 -0500 Subject: [PATCH 08/10] refactor: Update messages used in the game --- src/Application/Common/Resources/Messages.Designer.cs | 4 ++-- src/Application/Common/Resources/Messages.resx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Application/Common/Resources/Messages.Designer.cs b/src/Application/Common/Resources/Messages.Designer.cs index b51cc955..6f3e1028 100644 --- a/src/Application/Common/Resources/Messages.Designer.cs +++ b/src/Application/Common/Resources/Messages.Designer.cs @@ -340,7 +340,7 @@ internal static string NoPermissions { } /// - /// Looks up a localized string similar to ~n~~n~~n~Defend this flag from enemy capture!. + /// Looks up a localized string similar to ~n~~n~~n~{GameText}Defend this flag from enemy capture!. /// internal static string OnFlagAtBasePosition { get { @@ -376,7 +376,7 @@ internal static string OnFlagReturned { } /// - /// Looks up a localized string similar to {PlayerName} scored a point for the {TeamName} team by bringing the {RivalName} flag back to {TeamName} team's base!. + /// Looks up a localized string similar to {PlayerName} has brought the {RivalName} flag to the {TeamName} team's base. Point scored!. /// internal static string OnFlagScore { get { diff --git a/src/Application/Common/Resources/Messages.resx b/src/Application/Common/Resources/Messages.resx index bd08c7e4..49b81293 100644 --- a/src/Application/Common/Resources/Messages.resx +++ b/src/Application/Common/Resources/Messages.resx @@ -211,7 +211,7 @@ You do not have permissions to use this command - ~n~~n~~n~Defend this flag from enemy capture! + ~n~~n~~n~{GameText}Defend this flag from enemy capture! {PlayerName} has captured the {TeamName} team's {ColorName} flag! Keep an eye on the score! @@ -223,7 +223,7 @@ {PlayerName} has returned the {TeamName} team's {ColorName} flag to its base! Keep up the defense! - {PlayerName} scored a point for the {TeamName} team by bringing the {RivalName} flag back to {TeamName} team's base! + {PlayerName} has brought the {RivalName} flag to the {TeamName} team's base. Point scored! {PlayerName} has taken the {TeamName} team's {ColorName} flag! Keep an eye on the score! From 73dfc7139e2e00f4015fadc6db50091ce0684133 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 18:20:18 -0500 Subject: [PATCH 09/10] feat: Implement flag pickup mechanic for Capture the Flag mode --- .../Flags/Events/OnFlagAtBasePosition.cs | 15 +++++ .../Teams/Flags/Events/OnFlagCaptured.cs | 35 +++++++++++ .../Teams/Flags/Events/OnFlagDropped.cs | 32 ++++++++++ .../Teams/Flags/Events/OnFlagReturned.cs | 35 +++++++++++ .../Teams/Flags/Events/OnFlagScore.cs | 50 +++++++++++++++ .../Teams/Flags/Events/OnFlagTaken.cs | 26 ++++++++ src/Application/Teams/Flags/FlagSystem.cs | 63 +++++++++++++++++++ src/Application/Teams/Flags/IFlagEvent.cs | 19 ++++++ .../Flags/ServiceCollectionExtensions.cs | 24 +++++++ .../Teams/ServiceCollectionExtensions.cs | 4 +- 10 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 src/Application/Teams/Flags/Events/OnFlagAtBasePosition.cs create mode 100644 src/Application/Teams/Flags/Events/OnFlagCaptured.cs create mode 100644 src/Application/Teams/Flags/Events/OnFlagDropped.cs create mode 100644 src/Application/Teams/Flags/Events/OnFlagReturned.cs create mode 100644 src/Application/Teams/Flags/Events/OnFlagScore.cs create mode 100644 src/Application/Teams/Flags/Events/OnFlagTaken.cs create mode 100644 src/Application/Teams/Flags/FlagSystem.cs create mode 100644 src/Application/Teams/Flags/IFlagEvent.cs create mode 100644 src/Application/Teams/Flags/ServiceCollectionExtensions.cs diff --git a/src/Application/Teams/Flags/Events/OnFlagAtBasePosition.cs b/src/Application/Teams/Flags/Events/OnFlagAtBasePosition.cs new file mode 100644 index 00000000..809b7f6f --- /dev/null +++ b/src/Application/Teams/Flags/Events/OnFlagAtBasePosition.cs @@ -0,0 +1,15 @@ +namespace CTF.Application.Teams.Flags.Events; + +/// +/// This event occurs when a player attempts to pick up their own team's flag, which is currently at the base. +/// +public class OnFlagAtBasePosition : IFlagEvent +{ + public FlagStatus FlagStatus => FlagStatus.InitialPosition; + + public void Handle(Team team, Player player) + { + var text = Smart.Format(Messages.OnFlagAtBasePosition, team); + player.GameText(text, 5000, 3); + } +} diff --git a/src/Application/Teams/Flags/Events/OnFlagCaptured.cs b/src/Application/Teams/Flags/Events/OnFlagCaptured.cs new file mode 100644 index 00000000..1ecf56fd --- /dev/null +++ b/src/Application/Teams/Flags/Events/OnFlagCaptured.cs @@ -0,0 +1,35 @@ +namespace CTF.Application.Teams.Flags.Events; + +/// +/// This event occurs when a player has captured the opposing team's flag from their base. +/// +public class OnFlagCaptured( + IPlayerRepository playerRepository, + IWorldService worldService, + TeamPickupService teamPickupService, + TeamSoundsService teamSoundsService, + PlayerStatsRenderer playerStatsRenderer) : IFlagEvent +{ + public FlagStatus FlagStatus => FlagStatus.Captured; + + public void Handle(Team team, Player player) + { + teamPickupService.CreatePickupWithInfo(team); + teamPickupService.DestroyFlag(team); + teamSoundsService.PlayFlagTakenSound(team); + var message = Smart.Format(Messages.OnFlagCaptured, new + { + PlayerName = player.Name, + TeamName = team.Name, + ColorName = team.ColorName + }); + worldService.SendClientMessage(team.ColorHex, message); + worldService.GameText($"~n~~n~~n~{team.GameText}{team.ColorName} flag captured!", 5000, 3); + + PlayerInfo playerInfo = player.GetInfo(); + playerInfo.StatsPerRound.AddPoints(5); + playerInfo.AddCapturedFlags(); + playerRepository.UpdateCapturedFlags(playerInfo); + playerStatsRenderer.UpdateTextDraw(player); + } +} diff --git a/src/Application/Teams/Flags/Events/OnFlagDropped.cs b/src/Application/Teams/Flags/Events/OnFlagDropped.cs new file mode 100644 index 00000000..be070e2d --- /dev/null +++ b/src/Application/Teams/Flags/Events/OnFlagDropped.cs @@ -0,0 +1,32 @@ +namespace CTF.Application.Teams.Flags.Events; + +/// +/// This event occurs when a player has dropped the opposing team's flag. +/// +public class OnFlagDropped( + IPlayerRepository playerRepository, + IWorldService worldService, + TeamPickupService teamPickupService, + TeamSoundsService teamSoundsService) : IFlagEvent +{ + public FlagStatus FlagStatus => FlagStatus.Dropped; + + public void Handle(Team team, Player player) + { + teamPickupService.CreateFlagFromVector3(team, player.Position); + teamSoundsService.PlayFlagDroppedSound(team); + team.Flag.RemoveCarrier(); + var message = Smart.Format(Messages.OnFlagDropped, new + { + PlayerName = player.Name, + TeamName = team.Name, + ColorName = team.ColorName + }); + worldService.SendClientMessage(team.ColorHex, message); + worldService.GameText($"~n~~n~~n~{team.GameText}{team.ColorName} flag dropped!", 5000, 3); + + PlayerInfo playerInfo = player.GetInfo(); + playerInfo.AddDroppedFlags(); + playerRepository.UpdateDroppedFlags(playerInfo); + } +} diff --git a/src/Application/Teams/Flags/Events/OnFlagReturned.cs b/src/Application/Teams/Flags/Events/OnFlagReturned.cs new file mode 100644 index 00000000..5b95be71 --- /dev/null +++ b/src/Application/Teams/Flags/Events/OnFlagReturned.cs @@ -0,0 +1,35 @@ +namespace CTF.Application.Teams.Flags.Events; + +/// +/// This event occurs when a player has returned the flag to their team's base. +/// +public class OnFlagReturned( + IPlayerRepository playerRepository, + IWorldService worldService, + TeamPickupService teamPickupService, + TeamSoundsService teamSoundsService, + PlayerStatsRenderer playerStatsRenderer) : IFlagEvent +{ + public FlagStatus FlagStatus => FlagStatus.Returned; + + public void Handle(Team team, Player player) + { + teamPickupService.CreateFlagFromBasePosition(team); + teamPickupService.DestroyPickupWithInfo(team); + teamSoundsService.PlayFlagReturnedSound(team); + var message = Smart.Format(Messages.OnFlagReturned, new + { + PlayerName = player.Name, + TeamName = team.Name, + ColorName = team.ColorName + }); + worldService.SendClientMessage(team.ColorHex, message); + worldService.GameText($"~n~~n~~n~{team.GameText}{team.ColorName} flag returned!", 5000, 3); + + PlayerInfo playerInfo = player.GetInfo(); + playerInfo.StatsPerRound.AddPoints(5); + playerInfo.AddReturnedFlags(); + playerRepository.UpdateReturnedFlags(playerInfo); + playerStatsRenderer.UpdateTextDraw(player); + } +} diff --git a/src/Application/Teams/Flags/Events/OnFlagScore.cs b/src/Application/Teams/Flags/Events/OnFlagScore.cs new file mode 100644 index 00000000..c83d8121 --- /dev/null +++ b/src/Application/Teams/Flags/Events/OnFlagScore.cs @@ -0,0 +1,50 @@ +namespace CTF.Application.Teams.Flags.Events; + +/// +/// This event occurs when a player has captured the opposing team's flag and brought it back to their own base. +/// +public class OnFlagScore( + IPlayerRepository playerRepository, + IWorldService worldService, + TeamPickupService teamPickupService, + TeamSoundsService teamSoundsService, + TeamTextDrawRenderer teamTextDrawRenderer, + PlayerStatsRenderer playerStatsRenderer) : IFlagEvent +{ + public FlagStatus FlagStatus => FlagStatus.Brought; + + public void Handle(Team team, Player player) + { + teamPickupService.CreateFlagFromBasePosition(team.RivalTeam); + teamPickupService.DestroyPickupWithInfo(team.RivalTeam); + teamSoundsService.PlayTeamScoresSound(team); + teamTextDrawRenderer.UpdateTeamScore(team); + + var message = Smart.Format(Messages.OnFlagScore, new + { + PlayerName = player.Name, + TeamName = team.Name, + RivalName = team.RivalTeam.ColorName + }); + worldService.SendClientMessage(team.ColorHex, message); + worldService.GameText($"~n~~n~~n~{team.GameText}{team.ColorName} team scores!", 5000, 3); + + PlayerInfo playerInfo = player.GetInfo(); + playerInfo.StatsPerRound.AddPoints(8); + playerInfo.AddBroughtFlags(); + playerRepository.UpdateBroughtFlags(playerInfo); + GiveRewards(team); + } + + private void GiveRewards(Team team) + { + TeamMembers teamMembers = team.Members; + foreach (Player player in teamMembers) + { + PlayerInfo playerInfo = player.GetInfo(); + playerInfo.StatsPerRound.AddPoints(5); + player.AddHealth(10); + playerStatsRenderer.UpdateTextDraw(player); + } + } +} diff --git a/src/Application/Teams/Flags/Events/OnFlagTaken.cs b/src/Application/Teams/Flags/Events/OnFlagTaken.cs new file mode 100644 index 00000000..fd4c4852 --- /dev/null +++ b/src/Application/Teams/Flags/Events/OnFlagTaken.cs @@ -0,0 +1,26 @@ +namespace CTF.Application.Teams.Flags.Events; + +/// +/// This event occurs when a player has taken the flag from a position other than the base. +/// +public class OnFlagTaken( + IWorldService worldService, + TeamPickupService teamPickupService, + TeamSoundsService teamSoundsService) : IFlagEvent +{ + public FlagStatus FlagStatus => FlagStatus.Taken; + + public void Handle(Team team, Player player) + { + teamPickupService.DestroyFlag(team); + teamSoundsService.PlayFlagTakenSound(team); + var message = Smart.Format(Messages.OnFlagTaken, new + { + PlayerName = player.Name, + TeamName = team.Name, + ColorName = team.ColorName + }); + worldService.SendClientMessage(team.ColorHex, message); + worldService.GameText($"~n~~n~~n~{team.GameText}{team.ColorName} flag taken!", 5000, 3); + } +} diff --git a/src/Application/Teams/Flags/FlagSystem.cs b/src/Application/Teams/Flags/FlagSystem.cs new file mode 100644 index 00000000..2092b28c --- /dev/null +++ b/src/Application/Teams/Flags/FlagSystem.cs @@ -0,0 +1,63 @@ +namespace CTF.Application.Teams.Flags; + +public class FlagSystem( + IDictionary flagEvents, + PlayerStatsRenderer playerStatsRenderer, + OnFlagDropped onFlagDropped) : ISystem +{ + [Event] + public void OnPlayerDisconnect(Player player, DisconnectReason reason) + { + PlayerInfo playerInfo = player.GetInfo(); + if (playerInfo.HasCapturedFlag()) + { + Team currentTeam = playerInfo.Team; + onFlagDropped.Handle(currentTeam.RivalTeam, player); + } + } + + [Event] + public void OnPlayerDeath(Player deadPlayer, Player killer, Weapon reason) + { + PlayerInfo deadPlayerInfo = deadPlayer.GetInfo(); + if (deadPlayerInfo.HasCapturedFlag()) + { + Team currentTeam = deadPlayerInfo.Team; + onFlagDropped.Handle(currentTeam.RivalTeam, deadPlayer); + if (killer.IsValidPlayer()) + { + PlayerInfo killerInfo = killer.GetInfo(); + killerInfo.StatsPerRound.AddPoints(4); + killer.AddHealth(10); + playerStatsRenderer.UpdateTextDraw(killer); + } + } + } + + [Event] + public void OnPlayerPickUpPickup(Player player, Pickup pickup) + { + if (pickup.Model == (int)FlagModel.Red) + { + FlagStatus flagStatus = Team.Alpha.GetFlagStatus(flagPicker: player); + IFlagEvent flagEvent = flagEvents[flagStatus]; + flagEvent.Handle(Team.Alpha, player); + } + else if (pickup.Model == (int)FlagModel.Blue) + { + FlagStatus flagStatus = Team.Beta.GetFlagStatus(flagPicker: player); + IFlagEvent flagEvent = flagEvents[flagStatus]; + flagEvent.Handle(Team.Beta, player); + } + else if (pickup.Model == (int)PickupInfo.Red) + { + if (player.Team == (int)TeamId.Alpha) + player.GameText(Messages.RedFlagIsNotAtBasePosition, 5000, 3); + } + else if (pickup.Model == (int)PickupInfo.Blue) + { + if (player.Team == (int)TeamId.Beta) + player.GameText(Messages.BlueFlagIsNotAtBasePosition, 5000, 3); + } + } +} diff --git a/src/Application/Teams/Flags/IFlagEvent.cs b/src/Application/Teams/Flags/IFlagEvent.cs new file mode 100644 index 00000000..42945a4e --- /dev/null +++ b/src/Application/Teams/Flags/IFlagEvent.cs @@ -0,0 +1,19 @@ +namespace CTF.Application.Teams.Flags; + +/// +/// Represents an event related to the flag in the game. +/// +public interface IFlagEvent +{ + /// + /// Gets the current status of the flag associated with the event. + /// + FlagStatus FlagStatus { get; } + + /// + /// Handles the event when the flag is involved, updating the game state accordingly. + /// + /// The team associated with the event. + /// The player who triggered the event. + void Handle(Team team, Player player); +} diff --git a/src/Application/Teams/Flags/ServiceCollectionExtensions.cs b/src/Application/Teams/Flags/ServiceCollectionExtensions.cs new file mode 100644 index 00000000..a8f72f60 --- /dev/null +++ b/src/Application/Teams/Flags/ServiceCollectionExtensions.cs @@ -0,0 +1,24 @@ +namespace CTF.Application.Teams.Flags; + +public static class FlagServicesExtensions +{ + public static IServiceCollection AddFlagServices(this IServiceCollection services) + { + services + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(); + + services.AddSingleton(); + services.AddSingleton>(serviceProvider => + { + var flagEvents = serviceProvider.GetRequiredService>(); + return flagEvents.ToDictionary(flagEvent => flagEvent.FlagStatus, flagEvent => flagEvent); + }); + + return services; + } +} diff --git a/src/Application/Teams/ServiceCollectionExtensions.cs b/src/Application/Teams/ServiceCollectionExtensions.cs index 4694f127..05e9b727 100644 --- a/src/Application/Teams/ServiceCollectionExtensions.cs +++ b/src/Application/Teams/ServiceCollectionExtensions.cs @@ -7,8 +7,10 @@ public static IServiceCollection AddTeamServices(this IServiceCollection service services .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() - .AddSingleton(); + .AddSingleton() + .AddFlagServices(); return services; } From 64bdeff475361a162bd1943021c6e9f1d7c25ed8 Mon Sep 17 00:00:00 2001 From: MrDave1999 Date: Sat, 21 Sep 2024 18:38:39 -0500 Subject: [PATCH 10/10] refactor: Update placeholder name to ColorName --- src/Application/Common/Resources/Messages.Designer.cs | 2 +- src/Application/Common/Resources/Messages.resx | 2 +- src/Application/Teams/Flags/Events/OnFlagScore.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Application/Common/Resources/Messages.Designer.cs b/src/Application/Common/Resources/Messages.Designer.cs index 6f3e1028..d59393c4 100644 --- a/src/Application/Common/Resources/Messages.Designer.cs +++ b/src/Application/Common/Resources/Messages.Designer.cs @@ -376,7 +376,7 @@ internal static string OnFlagReturned { } /// - /// Looks up a localized string similar to {PlayerName} has brought the {RivalName} flag to the {TeamName} team's base. Point scored!. + /// Looks up a localized string similar to {PlayerName} has brought the {ColorName} flag to the {TeamName} team's base. Point scored!. /// internal static string OnFlagScore { get { diff --git a/src/Application/Common/Resources/Messages.resx b/src/Application/Common/Resources/Messages.resx index 49b81293..83359fe2 100644 --- a/src/Application/Common/Resources/Messages.resx +++ b/src/Application/Common/Resources/Messages.resx @@ -223,7 +223,7 @@ {PlayerName} has returned the {TeamName} team's {ColorName} flag to its base! Keep up the defense! - {PlayerName} has brought the {RivalName} flag to the {TeamName} team's base. Point scored! + {PlayerName} has brought the {ColorName} flag to the {TeamName} team's base. Point scored! {PlayerName} has taken the {TeamName} team's {ColorName} flag! Keep an eye on the score! diff --git a/src/Application/Teams/Flags/Events/OnFlagScore.cs b/src/Application/Teams/Flags/Events/OnFlagScore.cs index c83d8121..470e98f3 100644 --- a/src/Application/Teams/Flags/Events/OnFlagScore.cs +++ b/src/Application/Teams/Flags/Events/OnFlagScore.cs @@ -24,7 +24,7 @@ public void Handle(Team team, Player player) { PlayerName = player.Name, TeamName = team.Name, - RivalName = team.RivalTeam.ColorName + ColorName = team.RivalTeam.ColorName }); worldService.SendClientMessage(team.ColorHex, message); worldService.GameText($"~n~~n~~n~{team.GameText}{team.ColorName} team scores!", 5000, 3);