protected virtual void OnReaction(ReactionPrototype reaction, IEntity owner, ReagentUnit unitReactions) { foreach (var effect in reaction.Effects) { effect.React(owner, unitReactions.Double()); } }
/// <summary> /// Perform a reaction on a solution. This assumes all reaction criteria are met. /// Removes the reactants from the solution, then returns a solution with all products. /// </summary> private Solution PerformReaction(Solution solution, EntityUid owner, ReactionPrototype reaction, FixedPoint2 unitReactions) { // We do this so that ReagentEffect can have something to work with, even if it's // a little meaningless. var randomReagent = _prototypeManager.Index <ReagentPrototype>(_random.Pick(reaction.Reactants).Key); //Remove reactants foreach (var reactant in reaction.Reactants) { if (!reactant.Value.Catalyst) { var amountToRemove = unitReactions * reactant.Value.Amount; solution.RemoveReagent(reactant.Key, amountToRemove); } } //Create products var products = new Solution(); foreach (var product in reaction.Products) { products.AddReagent(product.Key, product.Value * unitReactions); } // Trigger reaction effects OnReaction(solution, reaction, randomReagent, owner, unitReactions); return(products); }
/// <summary> /// Perform a reaction on a solution. This assumes all reaction criteria are met. /// Removes the reactants from the solution, then returns a solution with all products. /// </summary> private Solution PerformReaction(Solution solution, IEntity owner, ReactionPrototype reaction, ReagentUnit unitReactions) { //Remove reactants foreach (var reactant in reaction.Reactants) { if (!reactant.Value.Catalyst) { var amountToRemove = unitReactions * reactant.Value.Amount; solution.RemoveReagent(reactant.Key, amountToRemove); } } //Create products var products = new Solution(); foreach (var product in reaction.Products) { products.AddReagent(product.Key, product.Value * unitReactions); } // Trigger reaction effects OnReaction(solution, reaction, owner, unitReactions); return(products); }
/// <summary> /// Checks if a solution can undergo a specified reaction. /// </summary> /// <param name="solution">The solution to check.</param> /// <param name="reaction">The reaction to check.</param> /// <param name="lowestUnitReactions">How many times this reaction can occur.</param> /// <returns></returns> private static bool CanReact(Solution solution, ReactionPrototype reaction, out FixedPoint2 lowestUnitReactions) { lowestUnitReactions = FixedPoint2.MaxValue; if (solution.Temperature < reaction.MinimumTemperature) { lowestUnitReactions = FixedPoint2.Zero; return(false); } else if (solution.Temperature > reaction.MaximumTemperature) { lowestUnitReactions = FixedPoint2.Zero; return(false); } foreach (var reactantData in reaction.Reactants) { var reactantName = reactantData.Key; var reactantCoefficient = reactantData.Value.Amount; if (!solution.ContainsReagent(reactantName, out var reactantQuantity)) { return(false); } if (reactantData.Value.Catalyst) { // catalyst is not consumed, so will not limit the reaction. But it still needs to be present, and // for quantized reactions we need to have a minimum amount if (reactantQuantity == FixedPoint2.Zero || reaction.Quantized && reactantQuantity < reactantCoefficient) { return(false); } continue; } var unitReactions = reactantQuantity / reactantCoefficient; if (unitReactions < lowestUnitReactions) { lowestUnitReactions = unitReactions; } } if (reaction.Quantized) { lowestUnitReactions = (int)lowestUnitReactions; } return(lowestUnitReactions > 0); }
/// <summary> /// Caches a reaction by its first required reagent. /// Used to build the reaction cache. /// </summary> /// <param name="reaction">A reaction prototype to cache.</param> private void CacheReaction(ReactionPrototype reaction) { var reagents = reaction.Reactants.Keys; foreach (var reagent in reagents) { if (!_reactions.TryGetValue(reagent, out var cache)) { cache = new List <ReactionPrototype>(); _reactions.Add(reagent, cache); } cache.Add(reaction); return; // Only need to cache based on the first reagent. } }
/// <summary> /// Checks if a solution can undergo a specified reaction. /// </summary> /// <param name="solution">The solution to check.</param> /// <param name="reaction">The reaction to check.</param> /// <param name="lowestUnitReactions">How many times this reaction can occur.</param> /// <returns></returns> private static bool CanReact(Solution.Solution solution, ReactionPrototype reaction, out ReagentUnit lowestUnitReactions) { lowestUnitReactions = ReagentUnit.MaxValue; foreach (var reactantData in reaction.Reactants) { var reactantName = reactantData.Key; var reactantCoefficient = reactantData.Value.Amount; if (!solution.ContainsReagent(reactantName, out var reactantQuantity)) { return(false); } var unitReactions = reactantQuantity / reactantCoefficient; if (unitReactions < lowestUnitReactions) { lowestUnitReactions = unitReactions; } } return(true); }
protected virtual void OnReaction(Solution solution, ReactionPrototype reaction, ReagentPrototype randomReagent, EntityUid owner, FixedPoint2 unitReactions) { var args = new ReagentEffectArgs(owner, null, solution, randomReagent, unitReactions, EntityManager, null); foreach (var effect in reaction.Effects) { if (!effect.ShouldApply(args)) { continue; } if (effect.ShouldLog) { var entity = args.SolutionEntity; _logSystem.Add(LogType.ReagentEffect, effect.LogImpact, $"Reaction effect {effect.GetType().Name:effect} of reaction ${reaction.ID:reaction} applied on entity {ToPrettyString(entity):entity} at {Transform(entity).Coordinates:coordinates}"); } effect.Effect(args); } }
public ReactionAttemptEvent(ReactionPrototype reaction, Solution solution) { Reaction = reaction; Solution = solution; }