Skip to content
Merged
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
19 changes: 16 additions & 3 deletions EXILED/Exiled.API/Features/Npc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ namespace Exiled.API.Features
using CommandSystem.Commands.RemoteAdmin.Dummies;
using Exiled.API.Enums;
using Exiled.API.Features.Components;
using Exiled.API.Features.CustomStats;
using Exiled.API.Features.Roles;
using Footprinting;
using GameCore;
using MEC;
using Mirror;
using PlayerRoles;
using PlayerStatsSystem;
using UnityEngine;

using Object = UnityEngine.Object;
Expand All @@ -33,6 +35,11 @@ namespace Exiled.API.Features
/// </summary>
public class Npc : Player
{
/// <summary>
/// The time it takes for the NPC to receive its <see cref="CustomHealthStat"/>, <see cref="CustomHumeShieldStat"/> and <see cref="Role"/>.
/// </summary>
public const float SpawnSetRoleDelay = 0.5f;

/// <inheritdoc cref="Player" />
public Npc(ReferenceHub referenceHub)
: base(referenceHub)
Expand Down Expand Up @@ -252,10 +259,13 @@ public static Npc Spawn(string name, RoleTypeId role, Vector3 position)
{
Npc npc = new(DummyUtils.SpawnDummy(name));

Timing.CallDelayed(0.5f, () =>
Timing.CallDelayed(SpawnSetRoleDelay, () =>
{
npc.Role.Set(role);
npc.Role.Set(role, SpawnReason.ForceClass);
npc.Position = position;
npc.ReferenceHub.playerStats._dictionarizedTypes[typeof(HealthStat)] = npc.ReferenceHub.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HealthStat))] = npc.CustomHealthStat = new CustomHealthStat { Hub = npc.ReferenceHub };
npc.Health = npc.MaxHealth; // otherwise the npc will spawn with 0 health
npc.ReferenceHub.playerStats._dictionarizedTypes[typeof(HumeShieldStat)] = npc.ReferenceHub.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HumeShieldStat))] = npc.CustomHumeShieldStat = new CustomHumeShieldStat { Hub = npc.ReferenceHub };
});

Dictionary.Add(npc.GameObject, npc);
Expand All @@ -274,9 +284,12 @@ public static Npc Spawn(string name, RoleTypeId role = RoleTypeId.None, bool ign
{
Npc npc = new(DummyUtils.SpawnDummy(name));

Timing.CallDelayed(0.5f, () =>
Timing.CallDelayed(SpawnSetRoleDelay, () =>
{
npc.Role.Set(role, SpawnReason.ForceClass, position is null ? RoleSpawnFlags.All : RoleSpawnFlags.AssignInventory);
npc.ReferenceHub.playerStats._dictionarizedTypes[typeof(HealthStat)] = npc.ReferenceHub.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HealthStat))] = npc.CustomHealthStat = new CustomHealthStat { Hub = npc.ReferenceHub };
npc.Health = npc.MaxHealth; // otherwise the npc will spawn with 0 health
npc.ReferenceHub.playerStats._dictionarizedTypes[typeof(HumeShieldStat)] = npc.ReferenceHub.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HumeShieldStat))] = npc.CustomHumeShieldStat = new CustomHumeShieldStat { Hub = npc.ReferenceHub };

if (position is not null)
npc.Position = position.Value;
Expand Down
41 changes: 24 additions & 17 deletions EXILED/Exiled.API/Features/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ namespace Exiled.API.Features
using PluginAPI.Core;
using RelativePositioning;
using RemoteAdmin;
using Respawning.NamingRules;
using RoundRestarting;
using UnityEngine;
using Utils;
Expand Down Expand Up @@ -96,8 +95,6 @@ public class Player : TypeCastObject<Player>, IEntity, IWorldSpace
private readonly HashSet<EActor> componentsInChildren = new();

private ReferenceHub referenceHub;
private CustomHealthStat healthStat;
private CustomHumeShieldStat humeShieldStat;
private Role role;

/// <summary>
Expand Down Expand Up @@ -145,6 +142,11 @@ public Player(GameObject gameObject)
/// </summary>
public static Dictionary<string, Player> UserIdsCache { get; } = new(20);

/// <summary>
/// Gets or sets a <see cref="CustomHumeShieldStat"/>.
/// </summary>
public CustomHumeShieldStat CustomHumeShieldStat { get; protected set; }

/// <inheritdoc/>
public IReadOnlyCollection<EActor> ComponentsInChildren => componentsInChildren;

Expand Down Expand Up @@ -178,8 +180,8 @@ private set
Inventory = value.inventory;
CameraTransform = value.PlayerCameraReference;

value.playerStats._dictionarizedTypes[typeof(HealthStat)] = value.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HealthStat))] = healthStat = new CustomHealthStat { Hub = value };
value.playerStats._dictionarizedTypes[typeof(HumeShieldStat)] = value.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HumeShieldStat))] = humeShieldStat = new CustomHumeShieldStat { Hub = value };
value.playerStats._dictionarizedTypes[typeof(HealthStat)] = value.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HealthStat))] = CustomHealthStat = new CustomHealthStat { Hub = value };
value.playerStats._dictionarizedTypes[typeof(HumeShieldStat)] = value.playerStats.StatModules[Array.IndexOf(PlayerStats.DefinedModules, typeof(HumeShieldStat))] = CustomHumeShieldStat = new CustomHumeShieldStat { Hub = value };
}
}

Expand Down Expand Up @@ -867,13 +869,13 @@ public DangerStackBase[] Dangers
/// </summary>
public float Health
{
get => healthStat.CurValue;
get => CustomHealthStat.CurValue;
set
{
if (value > MaxHealth)
MaxHealth = value;

healthStat.CurValue = value;
CustomHealthStat.CurValue = value;
}
}

Expand All @@ -882,8 +884,8 @@ public float Health
/// </summary>
public float MaxHealth
{
get => healthStat.MaxValue;
set => healthStat.CustomMaxValue = value;
get => CustomHealthStat.MaxValue;
set => CustomHealthStat.CustomMaxValue = value;
}

/// <summary>
Expand Down Expand Up @@ -929,26 +931,26 @@ public float MaxArtificialHealth
/// <remarks>This value can bypass the role's hume shield maximum. However, this value will only be visible to the end-player as Hume Shield if <see cref="FpcRole.IsHumeShieldedRole"/> is <see langword="true"/>. Otherwise, the game will treat the player as though they have the amount of Hume Shield specified, even though they cannot see it.</remarks>
public float HumeShield
{
get => HumeShieldStat.CurValue;
set => HumeShieldStat.CurValue = value;
get => CustomHumeShieldStat.CurValue;
set => CustomHumeShieldStat.CurValue = value;
}

/// <summary>
/// Gets or sets the players maximum Hume Shield.
/// </summary>
public float MaxHumeShield
{
get => humeShieldStat.MaxValue;
set => humeShieldStat.CustomMaxValue = value;
get => CustomHumeShieldStat.MaxValue;
set => CustomHumeShieldStat.CustomMaxValue = value;
}

/// <summary>
/// Gets or sets the players multiplier for gaining HumeShield.
/// </summary>
public float HumeShieldRegenerationMultiplier
{
get => humeShieldStat.ShieldRegenerationMultiplier;
set => humeShieldStat.ShieldRegenerationMultiplier = value;
get => CustomHumeShieldStat.ShieldRegenerationMultiplier;
set => CustomHumeShieldStat.ShieldRegenerationMultiplier = value;
}

/// <summary>
Expand All @@ -958,9 +960,9 @@ public float HumeShieldRegenerationMultiplier

/// <summary>
/// Gets the player's <see cref="PlayerStatsSystem.HumeShieldStat"/>.
/// TODO: Change to <see cref="CustomHumeShieldStat"/>.
/// </summary>
public HumeShieldStat HumeShieldStat => humeShieldStat;
[Obsolete("Use " + nameof(CustomHumeShieldStat) + " instead.")]
public HumeShieldStat HumeShieldStat => CustomHumeShieldStat;

/// <summary>
/// Gets or sets the item in the player's hand. Value will be <see langword="null"/> if the player is not holding anything.
Expand Down Expand Up @@ -1184,6 +1186,11 @@ public bool IsSpawnProtected
/// </summary>
internal static ConditionalWeakTable<GameObject, Player> UnverifiedPlayers { get; } = new();

/// <summary>
/// Gets or sets a <see cref="CustomHealthStat"/>.
/// </summary>
protected CustomHealthStat CustomHealthStat { get; set; }

/// <summary>
/// Converts NwPluginAPI player to EXILED player.
/// </summary>
Expand Down
48 changes: 20 additions & 28 deletions EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@ namespace Exiled.CustomRoles.API.Features
using Exiled.Events.EventArgs.Player;
using Exiled.Loader;
using InventorySystem.Configs;

using MEC;

using PlayerRoles;

using UnityEngine;
Expand All @@ -38,6 +36,8 @@ namespace Exiled.CustomRoles.API.Features
/// </summary>
public abstract class CustomRole
{
private const float AddRoleDelay = 0.25f;

private static Dictionary<Type, CustomRole?> typeLookupTable = new();

private static Dictionary<string, CustomRole?> stringLookupTable = new();
Expand Down Expand Up @@ -499,31 +499,31 @@ public virtual void Destroy()
public virtual void AddRole(Player player)
{
Log.Debug($"{Name}: Adding role to {player.Nickname}.");
TrackedPlayers.Add(player);
player.UniqueRole = Name;

if (Role != RoleTypeId.None)
{
switch (KeepPositionOnSpawn)
if (KeepPositionOnSpawn)
{
case true when KeepInventoryOnSpawn:
if (KeepInventoryOnSpawn)
player.Role.Set(Role, SpawnReason.ForceClass, RoleSpawnFlags.None);
break;
case true:
else
player.Role.Set(Role, SpawnReason.ForceClass, RoleSpawnFlags.AssignInventory);
break;
default:
{
if (KeepInventoryOnSpawn && player.IsAlive)
player.Role.Set(Role, SpawnReason.ForceClass, RoleSpawnFlags.UseSpawnpoint);
else
player.Role.Set(Role, SpawnReason.ForceClass, RoleSpawnFlags.All);
break;
}
}
else
{
if (KeepInventoryOnSpawn && player.IsAlive)
player.Role.Set(Role, SpawnReason.ForceClass, RoleSpawnFlags.UseSpawnpoint);
else
player.Role.Set(Role, SpawnReason.ForceClass, RoleSpawnFlags.All);
}
}

player.UniqueRole = Name;
TrackedPlayers.Add(player);

Timing.CallDelayed(
0.25f,
AddRoleDelay,
() =>
{
if (!KeepInventoryOnSpawn)
Expand Down Expand Up @@ -574,7 +574,6 @@ public virtual void AddRole(Player player)
ShowMessage(player);
ShowBroadcast(player);
RoleAdded(player);
player.UniqueRole = Name;
player.TryAddCustomRoleFriendlyFire(Name, CustomRoleFFMultiplier);

if (!string.IsNullOrEmpty(ConsoleMessage))
Expand Down Expand Up @@ -912,10 +911,8 @@ protected virtual void RoleRemoved(Player player)

private void OnInternalChangingNickname(ChangingNicknameEventArgs ev)
{
if (!Check(ev.Player))
return;

ev.Player.CustomInfo = $"{ev.NewName}\n{CustomInfo}";
if (Check(ev.Player))
ev.Player.CustomInfo = $"{ev.NewName}\n{CustomInfo}";
}

private void OnInternalSpawned(SpawnedEventArgs ev)
Expand All @@ -926,13 +923,8 @@ private void OnInternalSpawned(SpawnedEventArgs ev)

private void OnInternalChangingRole(ChangingRoleEventArgs ev)
{
if(ev.Reason == SpawnReason.Destroyed)
return;

if (Check(ev.Player) && ((ev.NewRole == RoleTypeId.Spectator && !KeepRoleOnDeath) || (ev.NewRole != RoleTypeId.Spectator && ev.NewRole != Role && !KeepRoleOnChangingRole)))
{
if (ev.IsAllowed && ev.Reason != SpawnReason.Destroyed && Check(ev.Player) && ((ev.NewRole == RoleTypeId.Spectator && !KeepRoleOnDeath) || (ev.NewRole != RoleTypeId.Spectator && !KeepRoleOnChangingRole)))
RemoveRole(ev.Player);
}
}

private void OnSpawningRagdoll(SpawningRagdollEventArgs ev)
Expand Down
3 changes: 0 additions & 3 deletions EXILED/Exiled.CustomRoles/Commands/Give.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ namespace Exiled.CustomRoles.Commands
using Exiled.Permissions.Extensions;

using RemoteAdmin;
using Utils;

/// <summary>
/// The command to give a role to player(s).
Expand Down Expand Up @@ -108,9 +107,7 @@ public bool Execute(ArraySegment<string> arguments, ICommandSender sender, out s
}

foreach (Player player in list)
{
role.AddRole(player);
}

response = $"Customrole {role.Name} given to {list.Count()} players!";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ namespace Exiled.Events.Patches.Events.Map
using Exiled.API.Extensions;
using Exiled.Events.EventArgs.Map;
using Exiled.Events.Patches.Generic;
using Footprinting;
using HarmonyLib;
using InventorySystem.Items.ThrowableProjectiles;
using UnityEngine;
Expand Down Expand Up @@ -67,12 +66,15 @@ private static void ProcessEvent(FlashbangGrenade instance, float distance)
HashSet<Player> targetToAffect = HashSetPool<Player>.Pool.Get();
foreach (Player player in ReferenceHub.AllHubs.Select(Player.Get))
{
if ((instance.transform.position - player.Position).sqrMagnitude >= distance)
if ((instance.transform.position - player.Position).sqrMagnitude > distance)
continue;

if (!ExiledEvents.Instance.Config.CanFlashbangsAffectThrower && instance.PreviousOwner.CompareLife(player.ReferenceHub))
continue;

if (!IndividualFriendlyFire.CheckFriendlyFirePlayer(instance.PreviousOwner, player.ReferenceHub) && !instance.PreviousOwner.CompareLife(player.ReferenceHub))
continue;

if (Physics.Linecast(instance.transform.position, player.CameraTransform.position, instance._blindingMask))
continue;

Expand Down