Skip to content

Commit

Permalink
Merge pull request #14 from terminator-97/master
Browse files Browse the repository at this point in the history
2.5.0
  • Loading branch information
terminator-97 authored Apr 5, 2021
2 parents af01ac6 + 3943a33 commit 817e33a
Show file tree
Hide file tree
Showing 12 changed files with 301 additions and 33 deletions.
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ This is the list of SCPUtils features with a brief description, i recomend to re
- **Playtime statistics:** You can see each user playtime day per day or total playtime using a simple command!
- **ASNs Bans:** You can ban specific ASNs to avoid ban evaders and cheaters, you can whitelist legit users to bypass the ASNs bans using a simple command, to add an ASN to blacklist add it inside server config setting.
- **Team protection:** Editing configs you can set protection to the teams you want against the teams you want on specific zones or entire map.

- **SCP-096 Target:** Players gets notified via hint when they become a SCP-096 Target.
- **Last Player:** Players gets notified via hint when they are the last player of the Team.

**Database will get created inside Exiled/SCPUtils folder.**<br /><br />
**Each server must have it's own database, you cannot use one database on multiple servers!**<br /><br />
**You must add LiteDB.dll into Plugins/dependencies folder or plugin won't work**<br /><br />
**Minimum requirements: Exiled version: 2.1.29 and LiteDB 5.0.9**
**Minimum requirements: Exiled version: 2.8.0 and LiteDB 5.0.9**


### Configs:
Expand Down Expand Up @@ -58,6 +59,8 @@ You can see settings and edit them inside Exiled/port-config.yml file(example Ex
| scputils_player_unrestrict | <userid / id> | scputils.moderatecommands | Unban a previously command banned player |
| scputils_show_command_bans | <userid / id> | scputils.moderatecommands | Show command ban history of a specific player |
| scputils_remove_previous_badge | <userid / id> | scputils.handlebadges | Removes previous badge from database for that player |
| scputils_round_info | <userid / id> | See bellow | Show round info |
| scputils_online_list | <userid / id> | See bellow | Show online player list |

**Console commands**

Expand Down Expand Up @@ -95,6 +98,35 @@ Pro tip: use scputils_speak.* to allow someone to speak with all the SCPs, set p

Console commands must be executed like .scputils_help in game console (press ò to open it)

**Round Info**

This command allows to show advanced round info and users are able to use it by default to see informations about their own team (using user console), if you don't like that just edit configs.
It has also the following permissions (those bypass server config):

| Permisssion | Description |
| ------------- | ------------- |
| scputils.roundinfo.execute | Needed to simply executing the command, doesnt show any info |
| scputils.roundinfo.roundtime | Show roundtime |
| scputils.roundinfo.tickets | Show tickets of all teams |
| scputils.roundinfo.nextrespawnteam | Show which team respawn next and when |
| scputils.roundinfo.respawncount | Show how many times MTF/Chaos respawned |
| scputils.roundinfo.lastrespawn | Show when MTF/Chaos respawned |

**Online List**

This command show online player list, it's also usable by users on normal console, it uses advanced permissions like past command.


| Permisssion | Description |
| ------------- | ------------- |
| scputils.onlinelist.basic | Allows to execute the command, see total players online and player nicknames |
| scputils.onlinelist.userid | Show UserIDs |
| scputils.onlinelist.badge | Show badges (hidden or not) |
| scputils.onlinelist.role | Show roles |
| scputils.onlinelist.health | Show players health |
| scputils.onlinelist.flags | Show player flags (God, DNT, Muted etc...) |


**Config Example**

To edit your configs you must go into EXILED folder and edit port-config.yml file (example 7777-config.yml), and edit them<br />
Expand Down
68 changes: 68 additions & 0 deletions SCPUtils/Commands/OnlineList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System;
using System.Text;
using CommandSystem;
using Exiled.Permissions.Extensions;

namespace SCPUtils.Commands
{
[CommandHandler(typeof(RemoteAdminCommandHandler))]
[CommandHandler(typeof(GameConsoleCommandHandler))]
[CommandHandler(typeof(ClientCommandHandler))]
class OnlineList : ICommand
{
public string Command { get; } = "scputils_online_list";

public string[] Aliases { get; } = new[] { "ol", "onlinelist" };

public string Description { get; } = "Show online player list";


public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
{
if (!sender.CheckPermission("scputils.onlinelist.basic"))
{
response = "You need a higher administration level to use this command!";
return false;
}
StringBuilder message = new StringBuilder($"Online Players ({CountOnlineMembers()})");

foreach (var player in Exiled.API.Features.Player.List)
{
message.AppendLine();
message.Append($"({player.Id}) {player.Nickname}");
if (sender.CheckPermission("scputils.onlinelist.userid")) message.Append($" ({player.UserId})");
if (sender.CheckPermission("scputils.onlinelist.badge") && player.Group.BadgeText!=null) message.Append($" [{player.Group.BadgeText}]");
if (sender.CheckPermission("scputils.onlinelist.role")) message.Append($" [{player.Role}]");
if (sender.CheckPermission("scputils.onlinelist.health")) message.Append($" HP {player.Health} / {player.MaxHealth}");
if (sender.CheckPermission("scputils.onlinelist.flags"))
{
if (player.IsOverwatchEnabled) message.Append(" [OVERWATCH]");
if (player.NoClipEnabled) message.Append(" [NOCLIP]");
if (player.IsGodModeEnabled) message.Append(" [GODMODE]");
if (player.IsStaffBypassEnabled) message.Append(" [BYPASS MODE]");
if (player.IsIntercomMuted) message.Append(" [INTERCOM MUTED]");
if (player.IsMuted) message.Append(" [SERVER MUTED]");
if (player.DoNotTrack) message.Append(" [DO NOT TRACK]");
if (player.RemoteAdminAccess) message.Append(" [RA]");
}
}
if (CountOnlineMembers() == 0)
{
response = "No player online!";
return true;
}
response = $"{message}";
return true;
}

private static int CountOnlineMembers()
{
var value = 0;
foreach (var player in Exiled.API.Features.Player.List)
{
value++;
}
return value;
}
}
}
2 changes: 1 addition & 1 deletion SCPUtils/Commands/PlayerInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out s
return false;
}



string text = $"<color=green>\n[{databasePlayer.Name} ({databasePlayer.Id}@{databasePlayer.Authentication})]\n\n" +
$"Total SCP Suicides/Quits: [ {databasePlayer.ScpSuicideCount} ]\n" +
Expand Down
86 changes: 86 additions & 0 deletions SCPUtils/Commands/RoundInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System;
using System.Text;
using CommandSystem;
using Exiled.Permissions.Extensions;

namespace SCPUtils.Commands
{
[CommandHandler(typeof(RemoteAdminCommandHandler))]
[CommandHandler(typeof(GameConsoleCommandHandler))]
[CommandHandler(typeof(ClientCommandHandler))]
class RoundInfo : ICommand
{
public string Command { get; } = "scputils_round_info";

public string[] Aliases { get; } = new[] { "ri", "roundinfo", "round_info" };
public string Description { get; } = "Show round info";

public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
{
var player = Exiled.API.Features.Player.Get(Exiled.API.Features.Player.Get(((CommandSender)sender).SenderId).ToString().Split(new string[] { " " }, StringSplitOptions.None)[2]);
if (!sender.CheckPermission("scputils.roundinfo.execute") && !ScpUtils.StaticInstance.Config.AllowedMtfInfoTeam.Contains(player.Team) && !ScpUtils.StaticInstance.Config.AllowedChaosInfoTeam.Contains(player.Team))
{
response = "You need a higher administration level to use this command!";
return false;
}

if (!Exiled.API.Features.Round.IsStarted)
{
response = "Round is not started yet!";
return true;
}
else
{
StringBuilder message = new StringBuilder($"Round Info:");
if (sender.CheckPermission("scputils.roundinfo.roundtime"))
{
message.AppendLine($"Round time: {Exiled.API.Features.Round.ElapsedTime.ToString(@"hh\:mm\:ss")}");
}
if (sender.CheckPermission("scputils.roundinfo.tickets") || ScpUtils.StaticInstance.Config.AllowedChaosInfoTeam.Contains(player.Team))
{
message.AppendLine($"Number of Chaos Tickets: {Exiled.API.Features.Respawn.ChaosTickets}");
}
if (sender.CheckPermission("scputils.roundinfo.tickets") || ScpUtils.StaticInstance.Config.AllowedMtfInfoTeam.Contains(player.Team))
{
message.AppendLine($"Number of MTF Tickets: {Exiled.API.Features.Respawn.NtfTickets}");
}

if (sender.CheckPermission("scputils.roundinfo.nextrespawnteam") || ScpUtils.StaticInstance.Config.AllowedChaosInfoTeam.Contains(player.Team) || ScpUtils.StaticInstance.Config.AllowedMtfInfoTeam.Contains(player.Team))
{
message.AppendLine($"Next known Respawn Team: {Exiled.API.Features.Respawn.NextKnownTeam}");
message.AppendLine($"Time until respawn: {TimeSpan.FromSeconds(Exiled.API.Features.Respawn.TimeUntilRespawn).ToString(@"hh\:mm\:ss")}");
}

if (sender.CheckPermission("scputils.roundinfo.respawncount") || ScpUtils.StaticInstance.Config.AllowedChaosInfoTeam.Contains(player.Team))
{
message.AppendLine($"Number of Chaos Respawn Waves: {ScpUtils.StaticInstance.EventHandlers.ChaosRespawnCount}");
}
if (sender.CheckPermission("scputils.roundinfo.respawncount") || ScpUtils.StaticInstance.Config.AllowedMtfInfoTeam.Contains(player.Team))
{
message.AppendLine($"Number of Mtf Respawn Waves: {ScpUtils.StaticInstance.EventHandlers.MtfRespawnCount}");
}
if (sender.CheckPermission("scputils.roundinfo.lastrespawn") || ScpUtils.StaticInstance.Config.AllowedChaosInfoTeam.Contains(player.Team))
{
if (ScpUtils.StaticInstance.EventHandlers.ChaosRespawnCount >= 1)
{
var timespan = (DateTime.Now - ScpUtils.StaticInstance.EventHandlers.LastChaosRespawn);
message.AppendLine($"Last Chaos wave respawn elapsed time: { timespan.ToString(@"hh\:mm\:ss")} ").AppendLine();

}
}
if (sender.CheckPermission("scputils.roundinfo.lastrespawn") || ScpUtils.StaticInstance.Config.AllowedMtfInfoTeam.Contains(player.Team))
{
if (ScpUtils.StaticInstance.EventHandlers.MtfRespawnCount >= 1)
{
var timespan = (DateTime.Now - ScpUtils.StaticInstance.EventHandlers.LastMtfRespawn);

message.AppendLine($"Last MTF wave respawn elapsed time: { timespan.ToString(@"hh\:mm\:ss")}");
}
}
response = $"{message}";

}
return true;
}
}
}
13 changes: 7 additions & 6 deletions SCPUtils/Commands/StaffList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ class StaffList : ICommand
public string[] Aliases { get; } = new[] { "sl", "stafflist" };

public string Description { get; } = "Show staff list";

public static int Count { get; private set; }


public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out string response)
{
Expand All @@ -24,7 +23,7 @@ public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out s
response = "You need a higher administration level to use this command!";
return false;
}
StringBuilder message = new StringBuilder($"Online Staffers( {CountStaffMembers()} )");
StringBuilder message = new StringBuilder($"Online Staffers ({CountStaffMembers()})");

foreach (var player in Exiled.API.Features.Player.List)
{
Expand All @@ -43,6 +42,7 @@ public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out s
if (player.IsOverwatchEnabled) message.Append(" [OVERWATCH]");
if (player.NoClipEnabled) message.Append(" [NOCLIP]");
if (player.IsGodModeEnabled) message.Append(" [GODMODE]");
if (player.IsStaffBypassEnabled) message.Append(" [BYPASS MODE]");
}
}
if (CountStaffMembers()==0)
Expand All @@ -55,12 +55,13 @@ public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out s
}

private static int CountStaffMembers()
{
{
var value = 0;
foreach (var player in Exiled.API.Features.Player.List)
{
if (player.ReferenceHub.serverRoles.RaEverywhere || player.ReferenceHub.serverRoles.Staff || player.RemoteAdminAccess) Count++;
if (player.ReferenceHub.serverRoles.RaEverywhere || player.ReferenceHub.serverRoles.Staff || player.RemoteAdminAccess) value++;
}
return Count;
return value;
}
}
}
23 changes: 23 additions & 0 deletions SCPUtils/Configs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ public class Configs : IConfig
[Description("Should the badge visibility gets resetted if the user when joins doesn't have the permission to execute the command? You can bypass it using scputils_preference_persist command")]
public bool KeepBadgeVisibilityWithoutPermission { get; private set; } = false;

[Description("Is 096 target feature enabled?")]
public bool Scp096TargetEnabled { get; private set; } = true;

[Description("Notify last player alive?")]
public bool NotifyLastPlayerAlive { get; private set; } = true;

[Description("Autowarn message for suiciding as SCP")]
public string SuicideWarnMessage { get; private set; } = "<color=red>WARN:\nAs per server rules SCP's suicide is an offence, doing it too much will result in a ban!</color>";

Expand Down Expand Up @@ -107,6 +113,12 @@ public class Configs : IConfig
[Description("Auto-warn message duration (if enabled)")]
public ushort AutoWarnMessageDuration { get; private set; } = 30;

[Description("SCP-096 target message duration (if enabled)")]
public ushort Scp096TargetMessageDuration { get; private set; } = 12;

[Description("Last player alive message duration (if enabled)")]
public ushort LastPlayerAliveMessageDuration { get; private set; } = 12;

[Description("Which is the minimun number of suicides before the player may not receive any kick o ban ignoring the SCP suicides / quit percentage? (if enabled)")]
public int ScpSuicideTollerance { get; private set; } = 5;

Expand Down Expand Up @@ -138,6 +150,17 @@ public class Configs : IConfig
[Description("Which message non-whitelisted players should get while connecting from blacklisted ASN?")]
public string AsnKickMessage { get; private set; } = "The ASN you are connecting from is blacklisted from this server, please contact server staff to request to being whitelisted";

[Description("Which message should be shown to who become SCP-096 target?")]
public string Scp096TargetText { get; private set; } = "<color=red>Attention:</color>\n<color=purple>You became a target of SCP-096!</color>";

[Description("Which message should be shown to last player alive of a team?")]
public string LastPlayerAliveNotificationText { get; private set; } = "<color=red>Attention:</color>\n<color=purple>You are the last player alive of your team!</color>";

[Description("Allowed classes to see MTF and Next respawn info")]
public List<Team> AllowedMtfInfoTeam { get; private set; } = new List<Team>() { Team.MTF, Team.RSC, Team.RIP };

[Description("Allowed classes to see Chaos info and Next respawn info")]
public List<Team> AllowedChaosInfoTeam { get; private set; } = new List<Team>() { Team.CDP, Team.CHI, Team.RIP };

/*
Expand Down
44 changes: 44 additions & 0 deletions SCPUtils/Functions/EventHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Round = Exiled.API.Features.Round;
using System.Collections.Generic;
using System.Linq;
using Exiled.API.Extensions;

namespace SCPUtils
{
Expand All @@ -17,8 +18,17 @@ public class EventHandlers

public static bool TemporarilyDisabledWarns;

public int ChaosRespawnCount { get; set; }

public int MtfRespawnCount { get; set; }

public DateTime LastChaosRespawn { get; set; }

public DateTime LastMtfRespawn { get; set; }

public EventHandlers(ScpUtils pluginInstance) => this.pluginInstance = pluginInstance;



internal void OnPlayerDeath(DyingEventArgs ev)
{
Expand All @@ -30,6 +40,18 @@ internal void OnPlayerDeath(DyingEventArgs ev)
else if ((ev.HitInformation.GetDamageType() == DamageTypes.Wall && ev.HitInformation.Amount == -1f) && ev.Killer == ev.Target && pluginInstance.Config.QuitEqualsSuicide) pluginInstance.Functions.OnQuitOrSuicide(ev.Target);
}
}

if(pluginInstance.Config.NotifyLastPlayerAlive)
{
var team = Exiled.API.Features.Player.Get(ev.Target.Team).ToList();
if (team.Count - 1 == 1)
{
if (team[0] == ev.Target)
team[1].ShowHint(pluginInstance.Config.LastPlayerAliveNotificationText, pluginInstance.Config.LastPlayerAliveMessageDuration);
else
team[0].ShowHint(pluginInstance.Config.LastPlayerAliveNotificationText, pluginInstance.Config.LastPlayerAliveMessageDuration);
}
}
}

internal void OnRoundEnded(RoundEndedEventArgs _)
Expand All @@ -41,11 +63,33 @@ internal void OnRoundEnded(RoundEndedEventArgs _)
TemporarilyDisabledWarns = true;
}

internal void OnTeamRespawn(RespawningTeamEventArgs ev)
{

if (ev.NextKnownTeam.ToString() == "ChaosInsurgency")
{
ChaosRespawnCount++;
LastChaosRespawn = DateTime.Now;
}

else if (ev.NextKnownTeam.ToString() == "NineTailedFox")
{
MtfRespawnCount++;
LastMtfRespawn = DateTime.Now;
}

}

internal void OnPlayerDestroy(DestroyingEventArgs ev)
{
pluginInstance.Functions.SaveData(ev.Player);
}

internal void On096AddTarget(AddingTargetEventArgs ev)
{
if (pluginInstance.Config.Scp096TargetEnabled) ev.Target.ShowHint(pluginInstance.Config.Scp096TargetText, pluginInstance.Config.Scp096TargetMessageDuration);
}

internal void OnWaitingForPlayers()
{
TemporarilyDisabledWarns = false;
Expand Down
Loading

0 comments on commit 817e33a

Please sign in to comment.