using System.Collections.Generic; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.FixedPoint; using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Random; using Robust.Shared.Serialization.Manager.Attributes; namespace Content.Shared.Chemistry.Reagent { /// /// Reagent effects describe behavior that occurs when a reagent is ingested and metabolized by some /// organ. They only trigger when all of are satisfied. /// [ImplicitDataDefinitionForInheritors] [MeansImplicitUse] public abstract class ReagentEffect { /// /// The list of conditions required for the effect to activate. Not required. /// [DataField("conditions")] public ReagentEffectCondition[]? Conditions; /// /// What's the chance, from 0 to 1, that this effect will occur? /// [DataField("probability")] public float Probability = 1.0f; public abstract void Metabolize(ReagentEffectArgs args); } public static class ReagentEffectExt { public static bool ShouldApply(this ReagentEffect effect, ReagentEffectArgs args, IRobustRandom? random = null) { if (random == null) random = IoCManager.Resolve(); // Make sure we still have enough reagent to go... if (args.Source != null && !args.Source.ContainsReagent(args.Reagent.ID)) return false; if (effect.Probability < 1.0f && !random.Prob(effect.Probability)) return false; if (effect.Conditions != null) { foreach (var cond in effect.Conditions) { if (!cond.Condition(args)) return false; } } return true; } } public enum ReactionMethod { Touch, Injection, Ingestion, } public readonly record struct ReagentEffectArgs( EntityUid SolutionEntity, EntityUid? OrganEntity, Solution? Source, ReagentPrototype Reagent, FixedPoint2 Metabolizing, IEntityManager EntityManager, ReactionMethod? Method ); }