Skip to content

Commit

Permalink
0.0.6 (#7)
Browse files Browse the repository at this point in the history
* Add nomination menu

* Add min rounds to enable command config

* Add change immediatly config

* Add localization

* Add pt-br translation

* Update README

* Update module version
  • Loading branch information
abnerfs authored Jan 20, 2024
1 parent af92b17 commit 72e0a64
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 58 deletions.
13 changes: 10 additions & 3 deletions AsyncVoteManager.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

using CounterStrikeSharp.API.Core;

namespace cs2_rockthevote
{
public enum VoteResult {
Expand Down Expand Up @@ -28,17 +30,22 @@ public VoteResult AddVote(int userId)
if (VotesAlreadyReached)
return VoteResult.VotesAlreadyReached;

VoteResult? result = null;
if (votes.IndexOf(userId) != -1)
return VoteResult.AlreadyAddedBefore;
result = VoteResult.AlreadyAddedBefore;
else
{
votes.Add(userId);
result = VoteResult.Added;
}

votes.Add(userId);
if(VoteValidator.CheckVotes(votes.Count))
{
VotesAlreadyReached = true;
return VoteResult.VotesReached;
}

return VoteResult.Added;
return result.Value;
}

public void RemoveVote(int userId)
Expand Down
2 changes: 1 addition & 1 deletion AsyncVoteValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public AsyncVoteValidator(int votePercentage, ServerManager server)

public bool CheckVotes(int numberOfVotes)
{
return numberOfVotes >= RequiredVotes;
return numberOfVotes > 0 && numberOfVotes >= RequiredVotes;
}
}
}
4 changes: 3 additions & 1 deletion Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ namespace cs2_rockthevote
{
public class Config : IBasePluginConfig
{
public int Version { get; set; } = 3;
public int Version { get; set; } = 4;
public int RtvVotePercentage { get; set; } = 60;
public int RtvMinPlayers { get; set; } = 0;
public bool DisableVotesInWarmup { get; set; } = false;
public int MapsToShowInVote { get; set; } = 5;
public int MinRounds { get; set; } = 0;
public bool ChangeImmediatly { get; set; } = true;
}
}
75 changes: 68 additions & 7 deletions NominationManager.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,86 @@

using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Menu;

namespace cs2_rockthevote
{
public class NominationManager
{
Dictionary<int, string> Nominations = new();
Dictionary<int, List<string>> Nominations = new();
ChatMenu? nominationMenu = null;

public RockTheVote Plugin { get; }

private string[] Maps;
public NominationManager(RockTheVote plugin, string[] maps)
{
Plugin = plugin;
Maps = maps;
nominationMenu = new("Nomination");
foreach (var map in Maps)
{
nominationMenu.AddMenuOption(map, (CCSPlayerController player, ChatMenuOption option) =>
{
Nominate(player, option.Text);
});
}
}

public void Nominate(int userId, string map)
public void OpenNominationMenu(CCSPlayerController player)
{
Nominations[userId] = map;
ChatMenus.OpenMenu(player!, nominationMenu!);
}

public void Nominate(CCSPlayerController player, string map)
{
if (Maps.FirstOrDefault(x => x.ToLower() == map) is null)
{
player!.PrintToChat(Plugin.Localize("invalid-map"));
return;

}

if (map == Server.MapName)
{
player!.PrintToChat(Plugin.Localize("nominate-current"));
return;
}

var userId = player.UserId!.Value;
if(!Nominations.ContainsKey(userId))
Nominations[userId] = new();

if(Nominations[userId].IndexOf(map) == -1)
Nominations[userId].Add(map);

var totalVotes = Nominations.Select(x => x.Value.Where(y => y == map).Count())
.Sum();

Server.PrintToChatAll(Plugin.Localize("nominated", player.PlayerName, map, totalVotes));
}

public List<string> Votes()
public List<string> NominationWinners()
{
return Nominations
if(Nominations.Count == 0)
return new List<string>();

var rawNominations = Nominations
.Select(x => x.Value)
.Aggregate((acc, x) => acc.Concat(x).ToList());

return rawNominations
.Distinct()
.Select(map => new KeyValuePair<string, int>(map, Nominations.Select(x => x.Value == map).Count()))
.Select(map => new KeyValuePair<string, int>(map, rawNominations.Count(x => x == map)))
.OrderByDescending(x => x.Value)
.Select(x => x.Key)
.Take(5)
.ToList();
}

public void RemoveNominations(int userId)
{
if (!Nominations.ContainsKey(userId))
Nominations.Remove(userId);
}
}
}
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,25 @@ Players can type rtv to request the map to be changed, once a number of votes is

```json
{
"Version": 2,
"Version": 4,
"RtvVotePercentage": 60,
"RtvMinPlayers": 0,
"DisableVotesInWarmup": false,
"MapsToShowInVote": 5
"MapsToShowInVote": 5,
"ChangeImmediatly": true,
"MinRounds": 0
}
```

Maps that will be used in RTV are located in addons/counterstrikesharp/configs/plugins/RockTheVote/maplist.txt

# TODO
- Add minimum rounds to use commands.
- Add votemap.
- Translations support
- Add dont change option
- Nomination menu
- [X] ~~Add minimum rounds to use commands.~~
- [ ] Add votemap.
- [x] ~~Translations support~~
- [ ] Add dont change option
- [x] ~~Nomination menu~~
- [ ] Add end of map vote
- [ ] Add timeleft command
- [ ] Add currentmap command
- [ ] Add nextmap command
88 changes: 61 additions & 27 deletions RockTheVote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@ namespace cs2_rockthevote
public class RockTheVote : BasePlugin, IPluginConfig<Config>
{
public override string ModuleName => "RockTheVote";
public override string ModuleVersion => "0.0.5";
public override string ModuleVersion => "0.0.6";
public override string ModuleAuthor => "abnerfs";
public override string ModuleDescription => "You know what it is, rtv";

CCSGameRules? _gameRules = null;
ServerManager ServerManager = new();
NominationManager NominationManager = new();
AsyncVoteManager Rtv = null;
NominationManager? NominationManager = null;
AsyncVoteManager? Rtv = null;
List<string> Maps = new();
VoteManager? voteManager = null;

public Config? Config { get; set; }

public string Localize(string key, params object[] values)
{
return $"{Localizer["prefix"]}{Localizer[key, values]}";
}

public bool WarmupRunning
{
Expand All @@ -33,19 +38,33 @@ public bool WarmupRunning
}
}

public int RoundsPlayed
{
get
{
if (_gameRules is null)
SetGameRules();

return _gameRules?.TotalRoundsPlayed ?? 0;
}
}

void LoadMaps()
{
Maps = new List<string>();
string mapsFile = Path.Combine(ModuleDirectory, "maplist.txt");
if (!File.Exists(mapsFile))
throw new FileNotFoundException(mapsFile);


Maps = File.ReadAllText(mapsFile)
.Replace("\r\n", "\n")
.Split("\n")
.Select(x => x.Trim())
.Where(x => !x.StartsWith("//"))
.Where(x => !string.IsNullOrWhiteSpace(x) && !x.StartsWith("//"))
.ToList();

NominationManager = new(this, Maps.ToArray());
}

public override void Load(bool hotReload)
Expand All @@ -56,7 +75,6 @@ public override void Load(bool hotReload)

void Init()
{
NominationManager = new();
LoadMaps();
_gameRules = null;
AddTimer(1.0F, SetGameRules);
Expand All @@ -73,15 +91,21 @@ bool ValidateCommand(CCSPlayerController? player)
{
if (player is null || !player.IsValid) return false;

if(Config!.MinRounds > RoundsPlayed)
{
player!.PrintToChat(Localize("minimum-rounds", Config!.MinRounds));
return false;
}

if (WarmupRunning && Config!.DisableVotesInWarmup)
{
player.PrintToChat("[RockTheVote] Command disabled during warmup.");
player.PrintToChat(Localize("disabled-warmup"));
return false;
}

if (ServerManager.ValidPlayerCount < Config!.RtvMinPlayers)
{
player.PrintToChat($"[RockTheVote] Minimum players to use this command is {Config.RtvMinPlayers}");
player.PrintToChat(Localize("minimum-players", Config.RtvMinPlayers));
return false;
}

Expand All @@ -92,30 +116,24 @@ bool ValidateCommand(CCSPlayerController? player)
public HookResult EventPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo @eventInfo)
{
var userId = @event.Userid.UserId!.Value;
Rtv.RemoveVote(userId);
Rtv!.RemoveVote(userId);
NominationManager!.RemoveNominations(userId);
return HookResult.Continue;
}

void NominateHandler(CCSPlayerController? player, string map)
{
if (string.IsNullOrEmpty(map))
if(Rtv!.VotesAlreadyReached)
{
player!.PrintToChat($"[RockTheVote] Usage: nominate <map-name>");
player!.PrintToChat(Localize("nomination-votes-reached"));
}
else if (Maps.FirstOrDefault(x => x.ToLower() == map) is not null)
else if (string.IsNullOrEmpty(map))
{
if (map == Server.MapName)
{
player!.PrintToChat($"[RockTheVote] You can't nominate the current map");
return;
}

NominationManager.Nominate(player.UserId!.Value, map);
Server.PrintToChatAll($"[RockTheVote] Player {player.PlayerName} nominated map {map}");
NominationManager!.OpenNominationMenu(player!);
}
else
{
player!.PrintToChat($"[RockTheVote] Invalid map");
NominationManager!.Nominate(player, map);
}
}

Expand Down Expand Up @@ -149,26 +167,42 @@ public void OnRTV(CCSPlayerController? player, CommandInfo? command)
if (!ValidateCommand(player))
return;

VoteResult result = Rtv.AddVote(player!.UserId!.Value);
VoteResult result = Rtv!.AddVote(player!.UserId!.Value);
switch (result)
{
case VoteResult.Added:
Server.PrintToChatAll($"[RockTheVote] {player.PlayerName} wants to rock the vote ({Rtv.VoteCount} voted, {Rtv.RequiredVotes} needed)");
Server.PrintToChatAll(Localize("rocked-the-vote", player.PlayerName, Rtv.VoteCount, Rtv.RequiredVotes));
break;
case VoteResult.AlreadyAddedBefore:
player.PrintToChat($"[RockTheVote] You already rocked the vote ({Rtv.VoteCount} voted, {Rtv.RequiredVotes} needed)");
Server.PrintToChatAll(Localize("already-rocked-the-vote", Rtv.VoteCount, Rtv.RequiredVotes));
break;
case VoteResult.VotesReached:
Server.PrintToChatAll("[RockTheVote] Number of votes reached, the vote for the next map will start");
Server.PrintToChatAll(Localize("starting-vote",player.PlayerName, Rtv.VoteCount, Rtv.RequiredVotes));
var mapsScrambled = Shuffle(new Random(), Maps.Where(x => x != Server.MapName).ToList());
var maps = NominationManager.Votes().Concat(mapsScrambled).Distinct().ToList();
var maps = NominationManager!.NominationWinners().Concat(mapsScrambled).Distinct().ToList();
var mapsToShow = Config!.MapsToShowInVote == 0 ? 5 : Config!.MapsToShowInVote;
VoteManager manager = new(maps!, this, 30, ServerManager.ValidPlayerCount, mapsToShow);
manager.StartVote();
voteManager = new(maps!, this, 30, ServerManager.ValidPlayerCount, mapsToShow, Config.ChangeImmediatly);
voteManager.StartVote();
break;
}
}

[GameEventHandler(HookMode.Post)]
public HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info)
{
if(voteManager?.ChangeNextMap() ?? false)
voteManager = null;
return HookResult.Continue;
}

[GameEventHandler(HookMode.Post)]
public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info)
{
if (voteManager?.ChangeNextMap() ?? false)
voteManager = null;
return HookResult.Continue;
}

[GameEventHandler(HookMode.Post)]
public HookResult OnChat(EventPlayerChat @event, GameEventInfo info)
{
Expand Down
10 changes: 10 additions & 0 deletions RockTheVote.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="8.0.1" />
</ItemGroup>

<ItemGroup>
<Reference Include="CounterStrikeSharp.API">
<HintPath>..\..\..\..\..\CSSHARP\CounterStrikeSharp.API.dll</HintPath>
Expand All @@ -15,6 +19,12 @@
</ItemGroup>

<ItemGroup>
<None Update="lang\en.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="lang\pt-BR.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="maplist.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
Loading

0 comments on commit 72e0a64

Please sign in to comment.