]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Mindrole trigger condition (#40323)
authorslarticodefast <161409025+slarticodefast@users.noreply.github.com>
Fri, 10 Oct 2025 22:27:14 +0000 (00:27 +0200)
committerGitHub <noreply@github.com>
Fri, 10 Oct 2025 22:27:14 +0000 (22:27 +0000)
* mind role trigger condition

* fix

* nits

---------

Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Content.Shared/Roles/SharedRoleSystem.cs
Content.Shared/Trigger/Components/Conditions/MindRoleTriggerConditionComponent.cs [new file with mode: 0644]
Content.Shared/Trigger/Components/Conditions/WhitelistTriggerConditionComponent.cs
Content.Shared/Trigger/Systems/TriggerSystem.Condition.cs
Content.Shared/Trigger/Systems/TriggerSystem.cs

index eeab32966154de884e8f15c0d5ce1e9f9d05e82e..e85d4d86d84ca77f31849cfec1f1ed88c582146b 100644 (file)
@@ -23,7 +23,6 @@ public abstract class SharedRoleSystem : EntitySystem
     [Dependency] private readonly SharedAudioSystem _audio = default!;
     [Dependency] private readonly IConfigurationManager _cfg = default!;
     [Dependency] protected readonly ISharedPlayerManager Player = default!;
-    [Dependency] private readonly IEntityManager _entityManager = default!;
     [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
     [Dependency] private readonly SharedMindSystem _minds = default!;
     [Dependency] private readonly IPrototypeManager _prototypes = default!;
@@ -400,7 +399,7 @@ public abstract class SharedRoleSystem : EntitySystem
 
         foreach (var role in delete)
         {
-            _entityManager.DeleteEntity(role);
+            PredictedDel(role);
         }
 
         var update = MindRolesUpdate(mind);
diff --git a/Content.Shared/Trigger/Components/Conditions/MindRoleTriggerConditionComponent.cs b/Content.Shared/Trigger/Components/Conditions/MindRoleTriggerConditionComponent.cs
new file mode 100644 (file)
index 0000000..32fb4d7
--- /dev/null
@@ -0,0 +1,27 @@
+using Content.Shared.Whitelist;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Trigger.Components.Conditions;
+
+/// <summary>
+/// Checks if a triggered entity or the user of a trigger has a certain mindrole.
+/// Cancels the trigger otherwise.
+/// </summary>
+/// <remarks>
+/// Mind roles are only networked to their owner! So if you use this on any other entity than yourself it won't be predicted.
+/// </remarks>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class MindRoleTriggerConditionComponent : BaseTriggerConditionComponent
+{
+    /// <summary>
+    /// Whitelist for what mind role components on the owning entity allow this trigger.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public EntityWhitelist? EntityWhitelist;
+
+    /// <summary>
+    /// Whitelist for what mind role components on the User allow this trigger.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public EntityWhitelist? UserWhitelist;
+}
index a2779f79c6f9cd7a77074e60a56145c15d775516..7ec6188ee359c384180c5a9282386da760b31d11 100644 (file)
@@ -4,20 +4,20 @@ using Robust.Shared.GameStates;
 namespace Content.Shared.Trigger.Components.Conditions;
 
 /// <summary>
-/// Checks if the user of a trigger satisfies a whitelist and blacklist condition for the triggered entity or the one triggering it.
+/// Checks if the user of a trigger satisfies a whitelist and blacklist condition.
 /// Cancels the trigger otherwise.
 /// </summary>
 [RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
 public sealed partial class WhitelistTriggerConditionComponent : BaseTriggerConditionComponent
 {
     /// <summary>
-    /// Whitelist for what entites can cause this trigger.
+    /// Whitelist for what entities can cause this trigger.
     /// </summary>
     [DataField, AutoNetworkedField]
     public EntityWhitelist? UserWhitelist;
 
     /// <summary>
-    /// Blacklist for what entites can cause this trigger.
+    /// Blacklist for what entities can cause this trigger.
     /// </summary>
     [DataField, AutoNetworkedField]
     public EntityWhitelist? UserBlacklist;
index 2d0756556ad9bec2035bd69069ce76a4ec63a6c1..b039c8e9decaa515105fe13d8f153b6cf4a4f7df 100644 (file)
@@ -10,31 +10,36 @@ public sealed partial class TriggerSystem
     private void InitializeCondition()
     {
         SubscribeLocalEvent<WhitelistTriggerConditionComponent, AttemptTriggerEvent>(OnWhitelistTriggerAttempt);
-
         SubscribeLocalEvent<UseDelayTriggerConditionComponent, AttemptTriggerEvent>(OnUseDelayTriggerAttempt);
-
         SubscribeLocalEvent<ToggleTriggerConditionComponent, AttemptTriggerEvent>(OnToggleTriggerAttempt);
-        SubscribeLocalEvent<ToggleTriggerConditionComponent, GetVerbsEvent<AlternativeVerb>>(OnToggleGetAltVerbs);
-
         SubscribeLocalEvent<RandomChanceTriggerConditionComponent, AttemptTriggerEvent>(OnRandomChanceTriggerAttempt);
+        SubscribeLocalEvent<MindRoleTriggerConditionComponent, AttemptTriggerEvent>(OnMindRoleTriggerAttempt);
+
+        SubscribeLocalEvent<ToggleTriggerConditionComponent, GetVerbsEvent<AlternativeVerb>>(OnToggleGetAltVerbs);
     }
 
     private void OnWhitelistTriggerAttempt(Entity<WhitelistTriggerConditionComponent> ent, ref AttemptTriggerEvent args)
     {
-        if (args.Key == null || ent.Comp.Keys.Contains(args.Key))
-            args.Cancelled |= !_whitelist.CheckBoth(args.User, ent.Comp.UserBlacklist, ent.Comp.UserWhitelist);
+        if (args.Key != null && !ent.Comp.Keys.Contains(args.Key))
+            return;
+
+        args.Cancelled |= !_whitelist.CheckBoth(args.User, ent.Comp.UserBlacklist, ent.Comp.UserWhitelist);
     }
 
     private void OnUseDelayTriggerAttempt(Entity<UseDelayTriggerConditionComponent> ent, ref AttemptTriggerEvent args)
     {
-        if (args.Key == null || ent.Comp.Keys.Contains(args.Key))
-            args.Cancelled |= _useDelay.IsDelayed(ent.Owner, ent.Comp.UseDelayId);
+        if (args.Key != null && !ent.Comp.Keys.Contains(args.Key))
+            return;
+
+        args.Cancelled |= _useDelay.IsDelayed(ent.Owner, ent.Comp.UseDelayId);
     }
 
     private void OnToggleTriggerAttempt(Entity<ToggleTriggerConditionComponent> ent, ref AttemptTriggerEvent args)
     {
-        if (args.Key == null || ent.Comp.Keys.Contains(args.Key))
-            args.Cancelled |= !ent.Comp.Enabled;
+        if (args.Key != null && !ent.Comp.Keys.Contains(args.Key))
+            return;
+
+        args.Cancelled |= !ent.Comp.Enabled;
     }
 
     private void OnToggleGetAltVerbs(Entity<ToggleTriggerConditionComponent> ent, ref GetVerbsEvent<AlternativeVerb> args)
@@ -62,19 +67,51 @@ public sealed partial class TriggerSystem
     private void OnRandomChanceTriggerAttempt(Entity<RandomChanceTriggerConditionComponent> ent,
         ref AttemptTriggerEvent args)
     {
-        if (args.Key == null || ent.Comp.Keys.Contains(args.Key))
+        if (args.Key != null && !ent.Comp.Keys.Contains(args.Key))
+            return;
+
+        // TODO: Replace with RandomPredicted once the engine PR is merged
+        var hash = new List<int>
+        {
+            (int)_timing.CurTick.Value,
+            GetNetEntity(ent).Id,
+            args.User == null ? 0 : GetNetEntity(args.User.Value).Id,
+        };
+        var seed = SharedRandomExtensions.HashCodeCombine(hash);
+        var rand = new System.Random(seed);
+
+        args.Cancelled |= !rand.Prob(ent.Comp.SuccessChance); // When not successful, Cancelled = true
+    }
+    private void OnMindRoleTriggerAttempt(Entity<MindRoleTriggerConditionComponent> ent, ref AttemptTriggerEvent args)
+    {
+        if (args.Key != null && !ent.Comp.Keys.Contains(args.Key))
+            return;
+
+        if (ent.Comp.EntityWhitelist != null)
         {
-            // TODO: Replace with RandomPredicted once the engine PR is merged
-            var hash = new List<int>
+            if (!_mind.TryGetMind(ent.Owner, out var entMindId, out var entMindComp))
+            {
+                args.Cancelled = true; // the entity has no mind
+                return;
+            }
+            if (!_role.MindHasRole((entMindId, entMindComp), ent.Comp.EntityWhitelist))
+            {
+                args.Cancelled = true; // the entity does not have the required role
+                return;
+            }
+        }
+
+        if (ent.Comp.UserWhitelist != null)
+        {
+            if (args.User == null || !_mind.TryGetMind(args.User.Value, out var userMindId, out var userMindComp))
+            {
+                args.Cancelled = true; // no user or the user has no mind
+                return;
+            }
+            if (!_role.MindHasRole((userMindId, userMindComp), ent.Comp.UserWhitelist))
             {
-                (int)_timing.CurTick.Value,
-                GetNetEntity(ent).Id,
-                args.User == null ? 0 : GetNetEntity(args.User.Value).Id,
-            };
-            var seed = SharedRandomExtensions.HashCodeCombine(hash);
-            var rand = new System.Random(seed);
-
-            args.Cancelled |= !rand.Prob(ent.Comp.SuccessChance); // When not successful, Cancelled = true
+                args.Cancelled = true; // the user does not have the required role
+            }
         }
     }
 }
index 25f8d51e116b15d94d14d9d567d82786cbc37bd1..a5fb509eed63c7a0cb37946e674fe609ac59781d 100644 (file)
@@ -3,7 +3,9 @@ using Content.Shared.Database;
 using Content.Shared.DeviceLinking;
 using Content.Shared.EntityTable;
 using Content.Shared.Item.ItemToggle;
+using Content.Shared.Mind;
 using Content.Shared.Popups;
+using Content.Shared.Roles;
 using Content.Shared.Timing;
 using Content.Shared.Trigger.Components;
 using Content.Shared.Whitelist;
@@ -39,6 +41,8 @@ public sealed partial class TriggerSystem : EntitySystem
     [Dependency] private readonly EntityWhitelistSystem _whitelist = default!;
     [Dependency] private readonly ItemToggleSystem _itemToggle = default!;
     [Dependency] private readonly SharedDeviceLinkSystem _deviceLink = default!;
+    [Dependency] private readonly SharedRoleSystem _role = default!;
+    [Dependency] private readonly SharedMindSystem _mind = default!;
     [Dependency] private readonly EntityTableSystem _entityTable = default!;
 
     public const string DefaultTriggerKey = "trigger";