diff --git a/Content.Shared/EntityConditions/Conditions/NestedCondition.cs b/Content.Shared/EntityConditions/Conditions/NestedCondition.cs new file mode 100644 index 00000000000..2af0d0d0e73 --- /dev/null +++ b/Content.Shared/EntityConditions/Conditions/NestedCondition.cs @@ -0,0 +1,31 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityConditions.Conditions; + +/// +/// Uses the conditions of an . +/// +public sealed partial class NestedCondition : EntityConditionBase +{ + /// + /// The condition prototype to use. + /// + [DataField(required: true)] + public ProtoId Proto; + + public override string EntityConditionGuidebookText(IPrototypeManager prototype) + => prototype.Index(Proto).Condition.EntityConditionGuidebookText(prototype); +} + +/// +/// Handles . +/// +public sealed class NestedConditionSystem : EntityConditionSystem +{ + [Dependency] private readonly SharedEntityConditionsSystem _conditions = default!; + + protected override void Condition(Entity ent, ref EntityConditionEvent args) + { + args.Result = _conditions.TryCondition(ent, args.Condition.Proto); + } +} diff --git a/Content.Shared/EntityConditions/EntityConditionPrototype.cs b/Content.Shared/EntityConditions/EntityConditionPrototype.cs new file mode 100644 index 00000000000..dc130d03df7 --- /dev/null +++ b/Content.Shared/EntityConditions/EntityConditionPrototype.cs @@ -0,0 +1,20 @@ +using Content.Shared.EntityConditions.Conditions; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityConditions; + +/// +/// A prototype for entity conditions which can be reused via . +/// +[Prototype] +public sealed partial class EntityConditionPrototype : IPrototype +{ + [IdDataField] + public string ID { get; private set; } = string.Empty; + + /// + /// The condition of this prototype. + /// + [DataField(required: true)] + public EntityCondition Condition = default!; +} diff --git a/Content.Shared/EntityConditions/SharedEntityConditionsSystem.Nested.cs b/Content.Shared/EntityConditions/SharedEntityConditionsSystem.Nested.cs new file mode 100644 index 00000000000..72f84881b0d --- /dev/null +++ b/Content.Shared/EntityConditions/SharedEntityConditionsSystem.Nested.cs @@ -0,0 +1,20 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityConditions; + +/// +/// Entity condition API counterpart using instead of . +/// +public sealed partial class SharedEntityConditionsSystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + + /// + /// TryCondition overload that uses a instead of . + /// + public bool TryCondition(EntityUid target, [ForbidLiteral] ProtoId id) + { + var proto = _proto.Index(id); + return TryCondition(target, proto.Condition); + } +} diff --git a/Content.Shared/EntityConditions/SharedEntityConditionsSystem.cs b/Content.Shared/EntityConditions/SharedEntityConditionsSystem.cs index 090a4226418..f15b5acb4d4 100644 --- a/Content.Shared/EntityConditions/SharedEntityConditionsSystem.cs +++ b/Content.Shared/EntityConditions/SharedEntityConditionsSystem.cs @@ -1,4 +1,4 @@ -using Robust.Shared.Prototypes; +using Robust.Shared.Prototypes; namespace Content.Shared.EntityConditions; diff --git a/Content.Shared/EntityEffects/Effects/NestedEffect.cs b/Content.Shared/EntityEffects/Effects/NestedEffect.cs new file mode 100644 index 00000000000..86b09a068e4 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/NestedEffect.cs @@ -0,0 +1,65 @@ +using Content.Shared.Localizations; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Applies the effect of an . +/// +public sealed partial class NestedEffect : EntityEffectBase +{ + /// + /// The effect prototype to use. + /// + [DataField(required: true)] + public ProtoId Proto; + + private List _conditions = new(); + private List _effects = new(); + + public override string? EntityEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + var proto = prototype.Index(Proto); + if (proto.GuidebookText is {} key) + return Loc.GetString(key, ("chance", Probability)); + + _effects.Clear(); + foreach (var effect in proto.Effects) + { + if (effect.EntityEffectGuidebookText(prototype, entSys) is not {} text) + continue; + + // basically GuidebookReagentEffectDescription but independent of reagents and no linq + _conditions.Clear(); + if (effect.Conditions is {} conditions) + { + foreach (var condition in conditions) + { + _conditions.Add(condition.EntityConditionGuidebookText(prototype)); + } + } + + var desc = Loc.GetString("guidebook-nested-effect-description", + ("effect", text), + ("chance", effect.Probability), + ("conditionCount", _conditions.Count), + ("conditions", ContentLocalizationManager.FormatList(_conditions))); + _effects.Add(desc); + } + + return _effects.Count == 0 ? null : string.Join("\n", _effects); + } +} + +/// +/// Handles . +/// +public sealed class NestedEffectSystem : EntityEffectSystem +{ + [Dependency] private readonly SharedEntityEffectsSystem _effects = default!; + + protected override void Effect(Entity ent, ref EntityEffectEvent args) + { + _effects.TryApplyEffect(ent, args.Effect.Proto, args.Scale, args.User); + } +} diff --git a/Content.Shared/EntityEffects/EntityEffectPrototype.cs b/Content.Shared/EntityEffects/EntityEffectPrototype.cs new file mode 100644 index 00000000000..8fa5e29707d --- /dev/null +++ b/Content.Shared/EntityEffects/EntityEffectPrototype.cs @@ -0,0 +1,35 @@ +using Content.Shared.EntityConditions; +using Content.Shared.EntityEffects.Effects; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects; + +/// +/// A prototype for entity effects which can be reused via . +/// +[Prototype] +public sealed partial class EntityEffectPrototype: IPrototype +{ + [IdDataField] + public string ID { get; private set; } = string.Empty; + + /// + /// The effects of this prototype. + /// + [DataField(required: true)] + public EntityEffect[] Effects = default!; + + /// + /// Conditions checked for this effect, regardless of the using it. + /// Currently not included in the guidebook text! + /// + [DataField] + public EntityCondition[]? Conditions; + + /// + /// An override for the effect guidebook text, has "chance" passed from 0 to 1. + /// By default one is generated from each effect. + /// + [DataField] + public LocId? GuidebookText; +} diff --git a/Content.Shared/EntityEffects/SharedEntityEffectsSystem.Nested.cs b/Content.Shared/EntityEffects/SharedEntityEffectsSystem.Nested.cs new file mode 100644 index 00000000000..4c0a8d14b02 --- /dev/null +++ b/Content.Shared/EntityEffects/SharedEntityEffectsSystem.Nested.cs @@ -0,0 +1,21 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects; + +/// +/// Entity effects API counterparts using instead of . +// +public sealed partial class SharedEntityEffectsSystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + + /// + /// TryApplyEffect overload using a instead of . + /// + public void TryApplyEffect(EntityUid target, [ForbidLiteral] ProtoId id, float scale = 1f, EntityUid? user = null) + { + var proto = _proto.Index(id); + if (_condition.TryConditions(target, proto.Conditions)) + ApplyEffects(target, proto.Effects, scale, user); + } +}