using System.Linq; using Content.Shared.Actions.Components; using Content.Shared.Actions.Events; using Content.Shared.EntityConditions; using Content.Shared.EntityEffects; using Content.Shared.IdentityManagement; namespace Content.Shared.Actions; /// public sealed partial class ActionRequirementsSystem : EntitySystem { [Dependency] private SharedEntityConditionsSystem _conditions = default!; [Dependency] private SharedEntityEffectsSystem _effects = default!; [SubscribeLocalEvent] private void OnActionAttempt(Entity ent, ref ActionAttemptEvent args) { var performerConditions = GetConditions(ent, ActionRequirementTarget.Performer); var user = args.User; // We always need to pass in some target to the Loc, it is probably safe to assume if there is no target we can just pass in the user. // Its just popup stuff anyway. var target = args.Target ?? args.User; if (!_conditions.TryConditions(args.User, performerConditions)) { DoCancel(ent, target, user, ref args); return; } var targetConditions = GetConditions(ent, ActionRequirementTarget.Target); if (args.Target != null && !_conditions.TryConditions(args.Target.Value, targetConditions)) { DoCancel(ent, target, user, ref args); } } [SubscribeLocalEvent] private void OnActionPerformed(Entity ent, ref ActionPerformedEvent args) { var performerEffects = GetEffects(ent, ActionRequirementTarget.Performer); var user = args.Performer; var target = args.Target; _effects.TryApplyEffects(user, performerEffects, user: user); if (target == null) return; var targetEffects = GetEffects(ent, ActionRequirementTarget.Target); _effects.TryApplyEffects(target.Value, targetEffects, user: user); } private EntityCondition[] GetConditions(Entity ent, ActionRequirementTarget target) { var conditions = ent.Comp.Conditions .Where(x => x.Key.HasFlag(target)) .SelectMany(x => x.Value); return conditions.ToArray(); } private EntityEffect[] GetEffects(Entity ent, ActionRequirementTarget target) { var conditions = ent.Comp.Effects .Where(x => x.Key.HasFlag(target)) .SelectMany(x => x.Value); return conditions.ToArray(); } private void DoCancel(Entity ent, EntityUid target, EntityUid user, ref ActionAttemptEvent args) { if (ent.Comp.FailPopup != null) { args.Reason = Loc.GetString( ent.Comp.FailPopup, ("target", Identity.Name(target, EntityManager)), ("performer", Identity.Name(user, EntityManager)), ("action", ent) ); } args.Type = ent.Comp.FailPopupType; args.Cancelled = true; } }