2021-11-22 23:51:43 -07:00
using Content.Shared.Administration.Logs ;
2021-09-26 15:19:00 +02:00
using Content.Shared.Chemistry.Components ;
2021-06-09 22:19:39 +02:00
using Content.Shared.Chemistry.Reaction ;
using Content.Shared.Chemistry.Reagent ;
2021-11-28 14:56:53 +01:00
using Content.Shared.Database ;
2020-04-08 15:53:15 +05:00
using JetBrains.Annotations ;
2021-03-26 12:02:41 +01:00
using Robust.Shared.Prototypes ;
2021-11-20 16:47:53 -07:00
using Robust.Shared.Random ;
2020-04-08 15:53:15 +05:00
2021-06-09 22:19:39 +02:00
namespace Content.Shared.Chemistry
2020-04-08 15:53:15 +05:00
{
[UsedImplicitly]
2022-02-16 00:23:23 -07:00
public sealed class ReactiveSystem : EntitySystem
2020-04-08 15:53:15 +05:00
{
2021-03-26 12:02:41 +01:00
[Dependency] private readonly IPrototypeManager _prototypeManager = default ! ;
2021-11-20 16:47:53 -07:00
[Dependency] private readonly IRobustRandom _robustRandom = default ! ;
2022-05-28 23:41:17 -07:00
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default ! ;
2021-03-26 12:02:41 +01:00
2022-10-04 14:24:19 +11:00
public void DoEntityReaction ( EntityUid uid , Solution solution , ReactionMethod method )
{
2023-09-05 09:55:10 +12:00
foreach ( var reagent in solution . Contents . ToArray ( ) )
2022-10-04 14:24:19 +11:00
{
2023-09-05 09:55:10 +12:00
ReactionEntity ( uid , method , reagent , solution ) ;
2022-10-04 14:24:19 +11:00
}
}
2023-09-05 09:55:10 +12:00
public void ReactionEntity ( EntityUid uid , ReactionMethod method , ReagentQuantity reagentQuantity , Solution ? source )
2021-03-26 12:02:41 +01:00
{
// We throw if the reagent specified doesn't exist.
2023-09-05 09:55:10 +12:00
var proto = _prototypeManager . Index < ReagentPrototype > ( reagentQuantity . Reagent . Prototype ) ;
ReactionEntity ( uid , method , proto , reagentQuantity , source ) ;
2021-03-26 12:02:41 +01:00
}
2023-09-05 09:55:10 +12:00
public void ReactionEntity ( EntityUid uid , ReactionMethod method , ReagentPrototype proto ,
ReagentQuantity reagentQuantity , Solution ? source )
2021-03-26 12:02:41 +01:00
{
2023-09-05 09:55:10 +12:00
if ( ! TryComp ( uid , out ReactiveComponent ? reactive ) )
2021-03-26 12:02:41 +01:00
return ;
2021-11-10 03:11:28 -07:00
// If we have a source solution, use the reagent quantity we have left. Otherwise, use the reaction volume specified.
2023-09-05 09:55:10 +12:00
var args = new ReagentEffectArgs ( uid , null , source , proto ,
source ? . GetReagentQuantity ( reagentQuantity . Reagent ) ? ? reagentQuantity . Quantity , EntityManager , method , 1f ) ;
2021-11-10 03:11:28 -07:00
2021-11-22 02:17:35 -07:00
// First, check if the reagent wants to apply any effects.
2023-09-05 09:55:10 +12:00
if ( proto . ReactiveEffects ! = null & & reactive . ReactiveGroups ! = null )
2021-03-26 12:02:41 +01:00
{
2023-09-05 09:55:10 +12:00
foreach ( var ( key , val ) in proto . ReactiveEffects )
2021-11-22 02:17:35 -07:00
{
if ( ! val . Methods . Contains ( method ) )
continue ;
2021-11-10 03:11:28 -07:00
2021-11-22 02:17:35 -07:00
if ( ! reactive . ReactiveGroups . ContainsKey ( key ) )
continue ;
2021-11-10 03:11:28 -07:00
2021-11-22 02:17:35 -07:00
if ( ! reactive . ReactiveGroups [ key ] . Contains ( method ) )
continue ;
foreach ( var effect in val . Effects )
{
if ( ! effect . ShouldApply ( args , _robustRandom ) )
continue ;
2021-11-27 00:31:56 -07:00
if ( effect . ShouldLog )
{
2021-12-05 18:09:01 +01:00
var entity = args . SolutionEntity ;
2022-05-28 23:41:17 -07:00
_adminLogger . Add ( LogType . ReagentEffect , effect . LogImpact ,
2023-09-05 09:55:10 +12:00
$"Reactive effect {effect.GetType().Name:effect} of reagent {proto.ID:reagent} with method {method} applied on entity {ToPrettyString(entity):entity} at {Transform(entity).Coordinates:coordinates}" ) ;
2021-11-27 00:31:56 -07:00
}
2021-11-27 01:27:47 -07:00
effect . Effect ( args ) ;
2021-11-22 02:17:35 -07:00
}
}
}
// Then, check if the prototype has any effects it can apply as well.
if ( reactive . Reactions ! = null )
{
foreach ( var entry in reactive . Reactions )
2021-11-10 03:11:28 -07:00
{
2021-11-22 02:17:35 -07:00
if ( ! entry . Methods . Contains ( method ) )
2021-11-10 03:11:28 -07:00
continue ;
2023-09-05 09:55:10 +12:00
if ( entry . Reagents ! = null & & ! entry . Reagents . Contains ( proto . ID ) )
2021-11-22 02:17:35 -07:00
continue ;
foreach ( var effect in entry . Effects )
{
if ( ! effect . ShouldApply ( args , _robustRandom ) )
continue ;
2021-11-27 00:31:56 -07:00
if ( effect . ShouldLog )
{
2021-12-05 18:09:01 +01:00
var entity = args . SolutionEntity ;
2022-05-28 23:41:17 -07:00
_adminLogger . Add ( LogType . ReagentEffect , effect . LogImpact ,
2023-09-05 09:55:10 +12:00
$"Reactive effect {effect.GetType().Name:effect} of {ToPrettyString(entity):entity} using reagent {proto.ID:reagent} with method {method} at {Transform(entity).Coordinates:coordinates}" ) ;
2021-11-27 00:31:56 -07:00
}
2021-11-27 01:27:47 -07:00
effect . Effect ( args ) ;
2021-11-22 02:17:35 -07:00
}
2021-11-10 03:11:28 -07:00
}
2021-03-26 12:02:41 +01:00
}
}
2020-04-08 15:53:15 +05:00
}
}