using Content.Shared.Chemistry.Reagent;
using Content.Shared.Database;
using Content.Shared.EntityEffects;
using Content.Shared.FixedPoint;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Shared.Chemistry.Reaction
{
///
/// Prototype for chemical reaction definitions
///
[Prototype]
public sealed partial class ReactionPrototype : IPrototype, IComparable
{
[ViewVariables]
[IdDataField]
public string ID { get; private set; } = default!;
[DataField("name")]
public string Name { get; private set; } = string.Empty;
///
/// Reactants required for the reaction to occur.
///
[DataField("reactants", customTypeSerializer:typeof(PrototypeIdDictionarySerializer))]
public Dictionary Reactants = new();
///
/// The minimum temperature the reaction can occur at.
///
[DataField("minTemp")]
public float MinimumTemperature = 0.0f;
///
/// If true, this reaction will attempt to conserve thermal energy.
///
[DataField("conserveEnergy")]
public bool ConserveEnergy = true;
///
/// The maximum temperature the reaction can occur at.
///
[DataField("maxTemp")]
public float MaximumTemperature = float.PositiveInfinity;
///
/// The required mixing categories for an entity to mix the solution with for the reaction to occur
///
[DataField("requiredMixerCategories")]
public List>? MixingCategories;
///
/// Reagents created when the reaction occurs.
///
[DataField("products", customTypeSerializer:typeof(PrototypeIdDictionarySerializer))]
public Dictionary Products = new();
///
/// Effects to be triggered when the reaction occurs.
///
[DataField("effects", serverOnly: true)] public List Effects = new();
///
/// How dangerous is this effect? Stuff like bicaridine should be low, while things like methamphetamine
/// or potas/water should be high.
///
[DataField("impact", serverOnly: true)] public LogImpact Impact = LogImpact.Low;
// TODO SERV3: Empty on the client, (de)serialize on the server with module manager is server module
[DataField("sound", serverOnly: true)] public SoundSpecifier Sound { get; private set; } = new SoundPathSpecifier("/Audio/Effects/Chemistry/bubbles.ogg");
///
/// If true, this reaction will only consume only integer multiples of the reactant amounts. If there are not
/// enough reactants, the reaction does not occur. Useful for spawn-entity reactions (e.g. creating cheese).
///
[DataField("quantized")] public bool Quantized = false;
///
/// Determines the order in which reactions occur. This should used to ensure that (in general) descriptive /
/// pop-up generating and explosive reactions occur before things like foam/area effects.
///
[DataField("priority")]
public int Priority;
///
/// Determines whether or not this reaction creates a new chemical (false) or if it's a breakdown for existing chemicals (true)
/// Used in the chemistry guidebook to make divisions between recipes and reaction sources.
///
///
/// Mixing together two reagents to get a third -> false
/// Heating a reagent to break it down into 2 different ones -> true
///
[DataField]
public bool Source;
///
/// Comparison for creating a sorted set of reactions. Determines the order in which reactions occur.
///
public int CompareTo(ReactionPrototype? other)
{
if (other == null)
return -1;
if (Priority != other.Priority)
return other.Priority - Priority;
// Prioritize reagents that don't generate products. This should reduce instances where a solution
// temporarily overflows and discards products simply due to the order in which the reactions occurred.
// Basically: Make space in the beaker before adding new products.
if (Products.Count != other.Products.Count)
return Products.Count - other.Products.Count;
return string.Compare(ID, other.ID, StringComparison.Ordinal);
}
}
///
/// Prototype for chemical reaction reactants.
///
[DataDefinition]
public sealed partial class ReactantPrototype
{
[DataField("amount")]
private FixedPoint2 _amount = FixedPoint2.New(1);
[DataField("catalyst")]
private bool _catalyst;
///
/// Minimum amount of the reactant needed for the reaction to occur.
///
public FixedPoint2 Amount => _amount;
///
/// Whether or not the reactant is a catalyst. Catalysts aren't removed when a reaction occurs.
///
public bool Catalyst => _catalyst;
}
}