Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add combos system #54

Merged
merged 10 commits into from
Sep 5, 2024
18 changes: 18 additions & 0 deletions src/Application/Common/Resources/Messages.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/Application/Common/Resources/Messages.resx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@
<data name="EmptyWeaponPackage" xml:space="preserve">
<value>You have no items in your weapon package</value>
</data>
<data name="InsufficientPoints" xml:space="preserve">
<value>You do not have enough points to obtain this combo</value>
</data>
<data name="InvalidInterval" xml:space="preserve">
<value>The interval must be between 0 to {Max}</value>
</data>
Expand Down Expand Up @@ -192,6 +195,9 @@
<data name="RankUpAward" xml:space="preserve">
<value>You have gained +100 points, +100 armour, and +100 health</value>
</data>
<data name="RedeemedPoints" xml:space="preserve">
<value>{PlayerName} redeemed their points for the benefit: {BenefitName}</value>
</data>
<data name="SpawnLocationFailure" xml:space="preserve">
<value>A spawn location can only be obtained for the alpha or beta team</value>
</data>
Expand Down
15 changes: 15 additions & 0 deletions src/Application/Players/Combos/Benefits/GrenadesArmour.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace CTF.Application.Players.Combos.Benefits;

public class GrenadesArmour : IBenefit
{
public string Name => "2 Grenades and 20 Armour";
public int RequiredPoints => 25;

public void Give(Player player)
{
PlayerInfo playerInfo = player.GetInfo();
player.GiveWeapon(Weapon.Grenade, ammo: 2);
player.AddArmour(20);
playerInfo.StatsPerRound.SubtractPoints(-25);
}
}
15 changes: 15 additions & 0 deletions src/Application/Players/Combos/Benefits/HealthArmour.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace CTF.Application.Players.Combos.Benefits;

public class HealthArmour : IBenefit
{
public string Name => "150 Health and 100 Armour";
public int RequiredPoints => 100;

public void Give(Player player)
{
PlayerInfo playerInfo = player.GetInfo();
player.Health = 150;
player.Armour = 100;
playerInfo.StatsPerRound.ResetPoints();
}
}
15 changes: 15 additions & 0 deletions src/Application/Players/Combos/Benefits/MolotovAmour.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace CTF.Application.Players.Combos.Benefits;

public class MolotovAmour : IBenefit
{
public string Name => "2 Molotov cocktail and 20 Armour";
public int RequiredPoints => 25;

public void Give(Player player)
{
PlayerInfo playerInfo = player.GetInfo();
player.GiveWeapon(Weapon.Moltov, ammo: 2);
player.AddArmour(20);
playerInfo.StatsPerRound.SubtractPoints(-25);
}
}
16 changes: 16 additions & 0 deletions src/Application/Players/Combos/Benefits/SatchelChargesAmour.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace CTF.Application.Players.Combos.Benefits;

public class SatchelChargesAmour : IBenefit
{
public string Name => "4 Satchel charges and 30 Armour";
public int RequiredPoints => 40;

public void Give(Player player)
{
PlayerInfo playerInfo = player.GetInfo();
player.GiveWeapon(Weapon.SatchelCharge, ammo: 4);
player.GiveWeapon(Weapon.Detonator, ammo: 1);
player.AddArmour(30);
playerInfo.StatsPerRound.SubtractPoints(-40);
}
}
15 changes: 15 additions & 0 deletions src/Application/Players/Combos/Benefits/TearGasHealth.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace CTF.Application.Players.Combos.Benefits;

public class TearGasHealth : IBenefit
{
public string Name => "20 Tear gas and 30 Health";
public int RequiredPoints => 20;

public void Give(Player player)
{
PlayerInfo playerInfo = player.GetInfo();
player.GiveWeapon(Weapon.Teargas, ammo: 20);
player.AddHealth(30);
playerInfo.StatsPerRound.SubtractPoints(-20);
}
}
59 changes: 59 additions & 0 deletions src/Application/Players/Combos/ComboSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
namespace CTF.Application.Players.Combos;

public class ComboSystem : ISystem
{
private readonly IDialogService _dialogService;
private readonly TablistDialog _tablistDialog;
private readonly IWorldService _worldService;
private readonly IEnumerable<IBenefit> _benefits;

public ComboSystem(
IDialogService dialogService,
IWorldService worldService,
IEnumerable<IBenefit> benefits)
{
_dialogService = dialogService;
_worldService = worldService;
_benefits = benefits;
var columnHeaders = new[]
{
"Combo",
"Required Points"
};
_tablistDialog = new TablistDialog(
caption: "Combos",
button1: "Select",
button2: "Close",
columnHeaders);

foreach (IBenefit benefit in benefits)
_tablistDialog.Add(benefit.Name, benefit.RequiredPoints.ToString());
}

[PlayerCommand("combos")]
public async void ShowCombos(Player player)
{
TablistDialogResponse response = await _dialogService.ShowAsync(player, _tablistDialog);
if (response.Response == DialogResponse.RightButtonOrCancel)
return;

string selectedItemName = response.Item.Columns[0];
IBenefit selectedBenefit = _benefits.First(benefit => benefit.Name == selectedItemName);
PlayerStatsPerRound playerStats = player.GetInfo().StatsPerRound;
if(playerStats.HasInsufficientPoints(selectedBenefit.RequiredPoints))
{
player.SendClientMessage(Color.Red, Messages.InsufficientPoints);
ShowCombos(player);
return;
}

var message = Smart.Format(Messages.RedeemedPoints, new
{
PlayerName = player.Name,
BenefitName = selectedBenefit.Name
});
_worldService.SendClientMessage(Color.Yellow, message);
selectedBenefit.Give(player);
ShowCombos(player);
}
}
8 changes: 8 additions & 0 deletions src/Application/Players/Combos/IBenefit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace CTF.Application.Players.Combos;

public interface IBenefit
{
string Name { get; }
int RequiredPoints { get; }
void Give(Player player);
}
16 changes: 16 additions & 0 deletions src/Application/Players/Combos/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace CTF.Application.Players.Combos;

public static class ComboServicesExtensions
{
public static IServiceCollection AddComboServices(this IServiceCollection services)
{
services
.AddSingleton<IBenefit, HealthArmour>()
.AddSingleton<IBenefit, GrenadesArmour>()
.AddSingleton<IBenefit, MolotovAmour>()
.AddSingleton<IBenefit, SatchelChargesAmour>()
.AddSingleton<IBenefit, TearGasHealth>();

return services;
}
}
36 changes: 36 additions & 0 deletions src/Application/Players/Extensions/HealthArmourExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
namespace CTF.Application.Players.Extensions;

public static class HealthArmourExtensions
{
/// <summary>
/// Increases the amount of health of a player.
/// </summary>
/// <param name="player">The current player.</param>
/// <param name="amount">The amount of health to be added.</param>
public static void AddHealth(this Player player, float amount)
{
if(amount < 0)
amount = -amount;
float total = player.Health + amount;
if (total > 100)
player.Health = 100;
else
player.Health += amount;
}

/// <summary>
/// Increases the amount of armour of a player.
/// </summary>
/// <param name="player">The current player.</param>
/// <param name="amount">The amount of armour to be added.</param>
public static void AddArmour(this Player player, float amount)
{
if (amount < 0)
amount = -amount;
float total = player.Armour + amount;
if (total > 100)
player.Armour = 100;
else
player.Armour += amount;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace CTF.Application.Players;
namespace CTF.Application.Players.Extensions;

public static class InvalidPlayerExtensions
{
Expand Down
22 changes: 22 additions & 0 deletions src/Application/Players/Extensions/PlayerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace CTF.Application.Players.Extensions;

public static class PlayerExtensions
{
/// <summary>
/// Gets the information from a player.
/// </summary>
/// <param name="player">The current player.</param>
/// <returns>
/// An instance of type <see cref="PlayerInfo"/>.
/// </returns>
/// <exception cref="InvalidOperationException">
/// when the player is not assigned the <see cref="AccountComponent"/> component.
/// </exception>
public static PlayerInfo GetInfo(this Player player)
{
AccountComponent accountComponent = player.GetComponent<AccountComponent>();
return accountComponent is null ?
throw new InvalidOperationException($"The player is not assigned the {nameof(AccountComponent)} component") :
accountComponent.PlayerInfo;
}
}
3 changes: 2 additions & 1 deletion src/Application/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ public static IServiceCollection AddApplicationServices(this IServiceCollection
{
services
.AddSingleton<ServerTimeService>()
.AddSingleton<MapInfoService>();
.AddSingleton<MapInfoService>()
.AddComboServices();

return services;
}
Expand Down
3 changes: 3 additions & 0 deletions src/Application/Usings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
global using CTF.Application.Common.Extensions;
global using CTF.Application.Players.Accounts;
global using CTF.Application.Players.Ranks;
global using CTF.Application.Players.Combos;
global using CTF.Application.Players.Combos.Benefits;
global using CTF.Application.Players.Extensions;
global using CTF.Application.Teams;
global using CTF.Application.Teams.Flags;
global using CTF.Application.Maps.Services;
14 changes: 14 additions & 0 deletions tests/Application.Tests/FakePlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

public class FakePlayer : Player
{
private float _health = 100;
private float _armour = 0;
private readonly int _id;
private readonly Guid _type;
public FakePlayer(int id, string name, TeamId team = TeamId.NoTeam)
Expand All @@ -25,4 +27,16 @@ public override bool SetAttachedObject(
Vector3 scale,
Color materialColor1,
Color materialColor2) => true;

public override float Health
{
get => _health;
set => _health = value;
}

public override float Armour
{
get => _armour;
set => _armour = value;
}
}
Loading
Loading