diff --git a/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs b/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs index f2dd9bc8d8..add0d807d1 100644 --- a/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs +++ b/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs @@ -54,6 +54,11 @@ public abstract class CustomRole /// public static HashSet Registered { get; } = new(); + /// + /// Gets or sets a value indicating whether the role is enabled. + /// + public virtual bool IsEnabled { get; set; } = true; + /// /// Gets or sets the custom RoleID of the role. /// @@ -323,6 +328,41 @@ public static IEnumerable RegisterRoles(bool byAttribute = false) return roles; } + /// + /// Registers all the 's present in the current plugin's config. + /// + /// The source containing the custom roles. + /// An optional collection of s to ignore during registration. + /// A of which contains all registered 's. + public static IEnumerable RegisterRolesFromSource(object source, IEnumerable? ignoredRoles = null) + { + List roles = new(); + + if (source == null) + return roles; + + HashSet? 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; + } + /// /// Registers all the 's present in the current assembly. /// @@ -486,6 +526,41 @@ public static IEnumerable UnregisterRoles(IEnumerable targetTy /// A of which contains all unregistered 's. public static IEnumerable UnregisterRoles(IEnumerable targetRoles, bool isIgnored = false) => UnregisterRoles(targetRoles.Select(x => x.GetType()), isIgnored); + /// + /// Unregisters all the 's present in the current plugin's config. + /// + /// The source containing the target roles. + /// An optional collection of s to ignore during unregisteration. + /// A of which contains all unregistered 's. + public static IEnumerable UnregisterFromSource(object source, IEnumerable? ignoredRoles = null) + { + List roles = new(); + + if (source == null) + return roles; + + HashSet? 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; + } + /// /// ResyncCustomRole Friendly Fire with Player (Append, or Overwrite). /// @@ -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)) diff --git a/EXILED/Exiled.CustomRoles/Events/PlayerHandlers.cs b/EXILED/Exiled.CustomRoles/Events/PlayerHandlers.cs index 47a153221d..38ed195d64 100644 --- a/EXILED/Exiled.CustomRoles/Events/PlayerHandlers.cs +++ b/EXILED/Exiled.CustomRoles/Events/PlayerHandlers.cs @@ -17,6 +17,8 @@ namespace Exiled.CustomRoles.Events using Exiled.CustomRoles.API.Features; using Exiled.Events.EventArgs.Player; + using UnityEngine; + /// /// Handles general events for players. /// @@ -66,16 +68,14 @@ internal void OnSpawningRagdoll(SpawningRagdollEventArgs ev) internal void OnSpawned(SpawnedEventArgs ev) { if (!ValidSpawnReasons.Contains(ev.Reason) || ev.Player.HasAnyCustomRole()) - { return; - } float totalChance = 0f; List 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; @@ -83,17 +83,13 @@ internal void OnSpawned(SpawnedEventArgs ev) } 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) { @@ -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; } } }