Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ public abstract class CustomRole
/// </summary>
public static HashSet<CustomRole> Registered { get; } = new();

/// <summary>
/// Gets or sets a value indicating whether the role is enabled.
/// </summary>
public virtual bool IsEnabled { get; set; } = true;

/// <summary>
/// Gets or sets the custom RoleID of the role.
/// </summary>
Expand Down Expand Up @@ -323,6 +328,41 @@ public static IEnumerable<CustomRole> RegisterRoles(bool byAttribute = false)
return roles;
}

/// <summary>
/// Registers all the <see cref="CustomRole"/>'s present in the current plugin's config.
/// </summary>
/// <param name="source">The source containing the custom roles.</param>
/// <param name="ignoredRoles">An optional collection of <see cref="CustomRole"/>s to ignore during registration.</param>
/// <returns>A <see cref="IEnumerable{T}"/> of <see cref="CustomRole"/> which contains all registered <see cref="CustomRole"/>'s.</returns>
public static IEnumerable<CustomRole> RegisterRolesFromSource(object source, IEnumerable<CustomRole>? ignoredRoles = null)
{
List<CustomRole> roles = new();

if (source == null)
return roles;

HashSet<Type>? ignoredTypes = ignoredRoles?.Select(x => x.GetType()).ToHashSet();

PropertyInfo[] properties = source.GetType().GetProperties();

foreach (PropertyInfo property in properties)
{
if (!typeof(CustomRole).IsAssignableFrom(property.PropertyType))
continue;

if (property.GetValue(source) is not CustomRole sourceRole)
continue;

if (ignoredTypes != null && ignoredTypes.Contains(sourceRole.GetType()))
continue;

if (sourceRole.TryRegister())
roles.Add(sourceRole);
}

return roles;
}

/// <summary>
/// Registers all the <see cref="CustomRole"/>'s present in the current assembly.
/// </summary>
Expand Down Expand Up @@ -486,6 +526,41 @@ public static IEnumerable<CustomRole> UnregisterRoles(IEnumerable<Type> targetTy
/// <returns>A <see cref="IEnumerable{T}"/> of <see cref="CustomRole"/> which contains all unregistered <see cref="CustomRole"/>'s.</returns>
public static IEnumerable<CustomRole> UnregisterRoles(IEnumerable<CustomRole> targetRoles, bool isIgnored = false) => UnregisterRoles(targetRoles.Select(x => x.GetType()), isIgnored);

/// <summary>
/// Unregisters all the <see cref="CustomRole"/>'s present in the current plugin's config.
/// </summary>
/// <param name="source">The source containing the target roles.</param>
/// <param name="ignoredRoles">An optional collection of <see cref="CustomRole"/>s to ignore during unregisteration.</param>
/// <returns>A <see cref="IEnumerable{T}"/> of <see cref="CustomRole"/> which contains all unregistered <see cref="CustomRole"/>'s.</returns>
public static IEnumerable<CustomRole> UnregisterFromSource(object source, IEnumerable<CustomRole>? ignoredRoles = null)
{
List<CustomRole> roles = new();

if (source == null)
return roles;

HashSet<Type>? ignoredTypes = ignoredRoles?.Select(x => x.GetType()).ToHashSet();

PropertyInfo[] properties = source.GetType().GetProperties();

foreach (PropertyInfo property in properties)
{
if (!typeof(CustomRole).IsAssignableFrom(property.PropertyType))
continue;

if (property.GetValue(source) is not CustomRole sourceRole)
continue;

if (ignoredTypes != null && ignoredTypes.Contains(sourceRole.GetType()))
continue;

if (sourceRole.TryUnregister())
roles.Add(sourceRole);
}

return roles;
}

/// <summary>
/// ResyncCustomRole Friendly Fire with Player (Append, or Overwrite).
/// </summary>
Expand Down Expand Up @@ -810,6 +885,12 @@ internal bool TryRegister()
if (!CustomRoles.Instance!.Config.IsEnabled)
return false;

if (!IsEnabled)
{
Log.Debug($"Custom role {Name} is not enabled and will not be registered.");
return false;
}

if (!Registered.Contains(this))
{
if (Registered.Any(r => r.Id == Id))
Expand Down
32 changes: 7 additions & 25 deletions EXILED/Exiled.CustomRoles/Events/PlayerHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace Exiled.CustomRoles.Events
using Exiled.CustomRoles.API.Features;
using Exiled.Events.EventArgs.Player;

using UnityEngine;

/// <summary>
/// Handles general events for players.
/// </summary>
Expand Down Expand Up @@ -66,34 +68,28 @@ internal void OnSpawningRagdoll(SpawningRagdollEventArgs ev)
internal void OnSpawned(SpawnedEventArgs ev)
{
if (!ValidSpawnReasons.Contains(ev.Reason) || ev.Player.HasAnyCustomRole())
{
return;
}

float totalChance = 0f;
List<CustomRole> eligibleRoles = new(8);

foreach (CustomRole role in CustomRole.Registered)
{
if (role.Role == ev.Player.Role.Type && !role.IgnoreSpawnSystem && role.SpawnChance > 0 && !role.Check(ev.Player) && (role.SpawnProperties is null || role.SpawnedPlayers < role.SpawnProperties.Limit) && (role.MinPlayers is 0 || Server.PlayerConnectedCount >= role.MinPlayers))
if (role.Role == ev.Player.Role.Type && !role.IgnoreSpawnSystem && role.SpawnChance > 0 && (role.SpawnProperties is null || role.SpawnedPlayers < role.SpawnProperties.Limit) && (role.MinPlayers is 0 || Server.PlayerConnectedCount >= role.MinPlayers))
{
eligibleRoles.Add(role);
totalChance += role.SpawnChance;
}
}

if (eligibleRoles.Count == 0)
{
return;
}

float lotterySize = Math.Max(100f, totalChance);
float lotterySize = Mathf.Max(100f, totalChance);
float randomRoll = (float)Loader.Loader.Random.NextDouble() * lotterySize;

if (randomRoll >= totalChance)
{
return;
}

foreach (CustomRole candidateRole in eligibleRoles)
{
Expand All @@ -103,23 +99,9 @@ internal void OnSpawned(SpawnedEventArgs ev)
continue;
}

if (candidateRole.SpawnProperties is null)
{
candidateRole.AddRole(ev.Player);
break;
}

int newSpawnCount = candidateRole.SpawnedPlayers++;
if (newSpawnCount <= candidateRole.SpawnProperties.Limit)
{
candidateRole.AddRole(ev.Player);
break;
}
else
{
candidateRole.SpawnedPlayers--;
randomRoll -= candidateRole.SpawnChance;
}
candidateRole.SpawnedPlayers++;
candidateRole.AddRole(ev.Player);
break;
Comment on lines -106 to +104

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this isn't a breaking change? I don't know myself, but it seems like you're just forcing the player to get a custom role, even if the role has no defined SpawnProperties as well as ignoring the SpawnProperties Limit

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this isn't a breaking change? I don't know myself, but it seems like you're just forcing the player to get a custom role, even if the role has no defined SpawnProperties as well as ignoring the SpawnProperties Limit

The same checks are already there on line 78. I accidentally reinserted them. Also, the increment was incorrect, meaning there was a bug.

}
}
}
Expand Down
Loading