private void TryMetabolize(MetabolizerComponent comp)
        {
            var owner = comp.Owner;
            IReadOnlyList <Solution.ReagentQuantity> reagentList = new List <Solution.ReagentQuantity>();
            Solution?           solution = null;
            SharedBodyComponent?body     = null;
            var solutionsSys             = Get <SolutionContainerSystem>();

            // if this field is passed we should try and take from the bloodstream over anything else
            if (owner.TryGetComponent <SharedMechanismComponent>(out var mech))
            {
                body = mech.Body;
                if (body != null)
                {
                    if (body.Owner.HasComponent <BloodstreamComponent>() &&
                        solutionsSys.TryGetSolution(body.Owner, comp.SolutionName, out solution) &&
                        solution.CurrentVolume >= ReagentUnit.Zero)
                    {
                        reagentList = solution.Contents;
                    }
                }
            }

            if (solution == null || reagentList.Count == 0)
            {
                // We're all outta ideas on where to metabolize from
                return;
            }

            List <Solution.ReagentQuantity> removeReagents = new(5);

            // Run metabolism for each reagent, remove metabolized reagents
            foreach (var reagent in reagentList)
            {
                if (!comp.Metabolisms.ContainsKey(reagent.ReagentId))
                {
                    continue;
                }

                var metabolism = comp.Metabolisms[reagent.ReagentId];
                // Run metabolism code for each reagent
                foreach (var effect in metabolism.Effects)
                {
                    var ent           = body != null ? body.Owner : owner;
                    var conditionsMet = true;
                    if (effect.Conditions != null)
                    {
                        // yes this is 3 nested for loops, but all of these lists are
                        // basically guaranteed to be small or empty
                        foreach (var condition in effect.Conditions)
                        {
                            if (!condition.Condition(ent, reagent))
                            {
                                conditionsMet = false;
                                break;
                            }
                        }
                    }

                    if (!conditionsMet)
                    {
                        return;
                    }

                    // If we're part of a body, pass that entity to Metabolize
                    // Otherwise, just pass our owner entity, maybe we're a plant or something
                    effect.Metabolize(ent, reagent);
                }

                removeReagents.Add(new Solution.ReagentQuantity(reagent.ReagentId, metabolism.MetabolismRate));
            }

            solutionsSys.TryRemoveAllReagents(solution, removeReagents);
        }
Ejemplo n.º 2
0
        private void TryMetabolize(MetabolizerComponent comp)
        {
            var owner       = comp.Owner;
            var reagentList = new List <Solution.ReagentQuantity>();
            SolutionContainerComponent?solution = null;
            SharedBodyComponent?       body     = null;

            // if this field is passed we should try and take from the bloodstream over anything else
            if (comp.TakeFromBloodstream && owner.TryGetComponent <SharedMechanismComponent>(out var mech))
            {
                body = mech.Body;
                if (body != null)
                {
                    if (body.Owner.TryGetComponent <BloodstreamComponent>(out var bloodstream) &&
                        bloodstream.Solution.CurrentVolume >= ReagentUnit.Zero)
                    {
                        solution    = bloodstream.Solution;
                        reagentList = bloodstream.Solution.ReagentList.ToList();
                    }
                }
            }
            else if (owner.TryGetComponent <SolutionContainerComponent>(out var sol))
            {
                // if we have no mechanism/body but a solution container instead,
                // we'll just use that to metabolize from
                solution    = sol;
                reagentList = sol.ReagentList.ToList();
            }
            if (solution == null || reagentList.Count == 0)
            {
                // We're all outta ideas on where to metabolize from
                return;
            }

            // Run metabolism for each reagent, remove metabolized reagents
            foreach (var reagent in reagentList)
            {
                if (!comp.Metabolisms.ContainsKey(reagent.ReagentId))
                {
                    continue;
                }

                var metabolism = comp.Metabolisms[reagent.ReagentId];
                // Run metabolism code for each reagent
                foreach (var effect in metabolism.Effects)
                {
                    var ent           = body != null ? body.Owner : owner;
                    var conditionsMet = true;
                    if (effect.Conditions != null)
                    {
                        // yes this is 3 nested for loops, but all of these lists are
                        // basically guaranteed to be small or empty
                        foreach (var condition in effect.Conditions)
                        {
                            if (!condition.Condition(ent, reagent))
                            {
                                conditionsMet = false;
                                break;
                            }
                        }
                    }

                    if (!conditionsMet)
                    {
                        return;
                    }

                    // If we're part of a body, pass that entity to Metabolize
                    // Otherwise, just pass our owner entity, maybe we're a plant or something
                    effect.Metabolize(ent, reagent);
                }

                solution.TryRemoveReagent(reagent.ReagentId, metabolism.MetabolismRate);
            }
        }
 private void OnMetabolizerInit(EntityUid uid, MetabolizerComponent component, ComponentInit args)
 {
     _solutionContainerSystem.EnsureSolution(EntityManager.GetEntity(uid), component.SolutionName);
 }