using Content.Shared.EntityTable.Conditions; using Content.Shared.EntityTable.ValueSelector; using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Random; namespace Content.Shared.EntityTable.EntitySelectors; [ImplicitDataDefinitionForInheritors, UsedImplicitly(ImplicitUseTargetFlags.WithInheritors)] public abstract partial class EntityTableSelector { /// /// The number of times this selector is run /// [DataField] public NumberSelector Rolls = new ConstantNumberSelector(1); /// /// A weight used to pick between selectors. /// [DataField] public float Weight = 1; /// /// A simple chance that the selector will run. /// [DataField] public double Prob = 1; /// /// A list of conditions that must evaluate to 'true' for the selector to apply. /// [DataField] public List Conditions = new(); /// /// If true, all the conditions must be successful in order for the selector to process. /// Otherwise, only one of them must be. /// [DataField] public bool RequireAll = true; public IEnumerable GetSpawns(System.Random rand, IEntityManager entMan, IPrototypeManager proto) { if (!CheckConditions(entMan, proto)) yield break; var rolls = Rolls.Get(rand); for (var i = 0; i < rolls; i++) { if (!rand.Prob(Prob)) continue; foreach (var spawn in GetSpawnsImplementation(rand, entMan, proto)) { yield return spawn; } } } public bool CheckConditions(IEntityManager entMan, IPrototypeManager proto) { if (Conditions.Count == 0) return true; var success = false; foreach (var condition in Conditions) { var res = condition.Evaluate(entMan, proto); if (RequireAll && !res) return false; // intentional break out of loop and function success |= res; } if (RequireAll) return true; return success; } protected abstract IEnumerable GetSpawnsImplementation(System.Random rand, IEntityManager entMan, IPrototypeManager proto); }