Turn ReagentEffects into generic EntityEffects (#28168)
* Oh the possibilities * Merge fixes * Forgot to remote LavaSystem oops * Changed EntityEffectArgs to EntityEffectBaseArgs and EntityEffectReagentArgs * Throw exception for unimplemented effectargs * Remove Json and overrideable datafields * Fix test issues * Actually fix the compiling issue * Fix comments and remove EntityEffectArgs (no longer used, replaced with EntityEffectBaseArgs)
This commit is contained in:
@@ -2,6 +2,7 @@ using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.EntityEffects;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -197,9 +198,7 @@ namespace Content.Shared.Chemistry.Reaction
|
||||
|
||||
private void OnReaction(Entity<SolutionComponent> soln, ReactionPrototype reaction, ReagentPrototype? reagent, FixedPoint2 unitReactions)
|
||||
{
|
||||
var args = new ReagentEffectArgs(soln, null, soln.Comp.Solution,
|
||||
reagent,
|
||||
unitReactions, EntityManager, null, 1f);
|
||||
var args = new EntityEffectReagentArgs(soln, EntityManager, null, soln.Comp.Solution, unitReactions, reagent, null, 1f);
|
||||
|
||||
var posFound = _transformSystem.TryGetMapOrGridCoordinates(soln, out var gridPos);
|
||||
|
||||
@@ -213,7 +212,7 @@ namespace Content.Shared.Chemistry.Reaction
|
||||
|
||||
if (effect.ShouldLog)
|
||||
{
|
||||
var entity = args.SolutionEntity;
|
||||
var entity = args.TargetEntity;
|
||||
_adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
|
||||
$"Reaction effect {effect.GetType().Name:effect} of reaction {reaction.ID:reaction} applied on entity {ToPrettyString(entity):entity} at Pos:{(posFound ? $"{gridPos:coordinates}" : "[Grid or Map not Found")}");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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;
|
||||
@@ -59,7 +60,7 @@ namespace Content.Shared.Chemistry.Reaction
|
||||
/// <summary>
|
||||
/// Effects to be triggered when the reaction occurs.
|
||||
/// </summary>
|
||||
[DataField("effects", serverOnly: true)] public List<ReagentEffect> Effects = new();
|
||||
[DataField("effects", serverOnly: true)] public List<EntityEffect> Effects = new();
|
||||
|
||||
/// <summary>
|
||||
/// How dangerous is this effect? Stuff like bicaridine should be low, while things like methamphetamine
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.EntityEffects;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||
|
||||
@@ -33,7 +34,7 @@ public sealed partial class ReactiveReagentEffectEntry
|
||||
public HashSet<string>? Reagents = null;
|
||||
|
||||
[DataField("effects", required: true)]
|
||||
public List<ReagentEffect> Effects = default!;
|
||||
public List<EntityEffect> Effects = default!;
|
||||
|
||||
[DataField("groups", readOnly: true, serverOnly: true,
|
||||
customTypeSerializer:typeof(PrototypeIdDictionarySerializer<HashSet<ReactionMethod>, ReactiveGroupPrototype>))]
|
||||
|
||||
@@ -3,102 +3,107 @@ using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.EntityEffects;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared.Chemistry
|
||||
namespace Content.Shared.Chemistry;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class ReactiveSystem : EntitySystem
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class ReactiveSystem : EntitySystem
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
|
||||
public void DoEntityReaction(EntityUid uid, Solution solution, ReactionMethod method)
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _robustRandom = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
|
||||
public void DoEntityReaction(EntityUid uid, Solution solution, ReactionMethod method)
|
||||
foreach (var reagent in solution.Contents.ToArray())
|
||||
{
|
||||
foreach (var reagent in solution.Contents.ToArray())
|
||||
{
|
||||
ReactionEntity(uid, method, reagent, solution);
|
||||
}
|
||||
ReactionEntity(uid, method, reagent, solution);
|
||||
}
|
||||
}
|
||||
|
||||
public void ReactionEntity(EntityUid uid, ReactionMethod method, ReagentQuantity reagentQuantity, Solution? source)
|
||||
public void ReactionEntity(EntityUid uid, ReactionMethod method, ReagentQuantity reagentQuantity, Solution? source)
|
||||
{
|
||||
// We throw if the reagent specified doesn't exist.
|
||||
var proto = _prototypeManager.Index<ReagentPrototype>(reagentQuantity.Reagent.Prototype);
|
||||
ReactionEntity(uid, method, proto, reagentQuantity, source);
|
||||
}
|
||||
|
||||
public void ReactionEntity(EntityUid uid, ReactionMethod method, ReagentPrototype proto,
|
||||
ReagentQuantity reagentQuantity, Solution? source)
|
||||
{
|
||||
if (!TryComp(uid, out ReactiveComponent? reactive))
|
||||
return;
|
||||
|
||||
// If we have a source solution, use the reagent quantity we have left. Otherwise, use the reaction volume specified.
|
||||
var args = new EntityEffectReagentArgs(uid, EntityManager, null, source, source?.GetReagentQuantity(reagentQuantity.Reagent) ?? reagentQuantity.Quantity, proto, method, 1f);
|
||||
|
||||
// First, check if the reagent wants to apply any effects.
|
||||
if (proto.ReactiveEffects != null && reactive.ReactiveGroups != null)
|
||||
{
|
||||
// We throw if the reagent specified doesn't exist.
|
||||
var proto = _prototypeManager.Index<ReagentPrototype>(reagentQuantity.Reagent.Prototype);
|
||||
ReactionEntity(uid, method, proto, reagentQuantity, source);
|
||||
}
|
||||
|
||||
public void ReactionEntity(EntityUid uid, ReactionMethod method, ReagentPrototype proto,
|
||||
ReagentQuantity reagentQuantity, Solution? source)
|
||||
{
|
||||
if (!TryComp(uid, out ReactiveComponent? reactive))
|
||||
return;
|
||||
|
||||
// If we have a source solution, use the reagent quantity we have left. Otherwise, use the reaction volume specified.
|
||||
var args = new ReagentEffectArgs(uid, null, source, proto,
|
||||
source?.GetReagentQuantity(reagentQuantity.Reagent) ?? reagentQuantity.Quantity, EntityManager, method, 1f);
|
||||
|
||||
// First, check if the reagent wants to apply any effects.
|
||||
if (proto.ReactiveEffects != null && reactive.ReactiveGroups != null)
|
||||
foreach (var (key, val) in proto.ReactiveEffects)
|
||||
{
|
||||
foreach (var (key, val) in proto.ReactiveEffects)
|
||||
if (!val.Methods.Contains(method))
|
||||
continue;
|
||||
|
||||
if (!reactive.ReactiveGroups.ContainsKey(key))
|
||||
continue;
|
||||
|
||||
if (!reactive.ReactiveGroups[key].Contains(method))
|
||||
continue;
|
||||
|
||||
foreach (var effect in val.Effects)
|
||||
{
|
||||
if (!val.Methods.Contains(method))
|
||||
if (!effect.ShouldApply(args, _robustRandom))
|
||||
continue;
|
||||
|
||||
if (!reactive.ReactiveGroups.ContainsKey(key))
|
||||
continue;
|
||||
|
||||
if (!reactive.ReactiveGroups[key].Contains(method))
|
||||
continue;
|
||||
|
||||
foreach (var effect in val.Effects)
|
||||
if (effect.ShouldLog)
|
||||
{
|
||||
if (!effect.ShouldApply(args, _robustRandom))
|
||||
continue;
|
||||
|
||||
if (effect.ShouldLog)
|
||||
{
|
||||
var entity = args.SolutionEntity;
|
||||
_adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
|
||||
$"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}");
|
||||
}
|
||||
|
||||
effect.Effect(args);
|
||||
var entity = args.TargetEntity;
|
||||
_adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
|
||||
$"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}");
|
||||
}
|
||||
|
||||
effect.Effect(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then, check if the prototype has any effects it can apply as well.
|
||||
if (reactive.Reactions != null)
|
||||
// Then, check if the prototype has any effects it can apply as well.
|
||||
if (reactive.Reactions != null)
|
||||
{
|
||||
foreach (var entry in reactive.Reactions)
|
||||
{
|
||||
foreach (var entry in reactive.Reactions)
|
||||
if (!entry.Methods.Contains(method))
|
||||
continue;
|
||||
|
||||
if (entry.Reagents != null && !entry.Reagents.Contains(proto.ID))
|
||||
continue;
|
||||
|
||||
foreach (var effect in entry.Effects)
|
||||
{
|
||||
if (!entry.Methods.Contains(method))
|
||||
if (!effect.ShouldApply(args, _robustRandom))
|
||||
continue;
|
||||
|
||||
if (entry.Reagents != null && !entry.Reagents.Contains(proto.ID))
|
||||
continue;
|
||||
|
||||
foreach (var effect in entry.Effects)
|
||||
if (effect.ShouldLog)
|
||||
{
|
||||
if (!effect.ShouldApply(args, _robustRandom))
|
||||
continue;
|
||||
|
||||
if (effect.ShouldLog)
|
||||
{
|
||||
var entity = args.SolutionEntity;
|
||||
_adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
|
||||
$"Reactive effect {effect.GetType().Name:effect} of {ToPrettyString(entity):entity} using reagent {proto.ID:reagent} with method {method} at {Transform(entity).Coordinates:coordinates}");
|
||||
}
|
||||
|
||||
effect.Effect(args);
|
||||
var entity = args.TargetEntity;
|
||||
_adminLogger.Add(LogType.ReagentEffect, effect.LogImpact,
|
||||
$"Reactive effect {effect.GetType().Name:effect} of {ToPrettyString(entity):entity} using reagent {proto.ID:reagent} with method {method} at {Transform(entity).Coordinates:coordinates}");
|
||||
}
|
||||
|
||||
effect.Effect(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public enum ReactionMethod
|
||||
{
|
||||
Touch,
|
||||
Injection,
|
||||
Ingestion,
|
||||
}
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Localizations;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Shared.Chemistry.Reagent
|
||||
{
|
||||
/// <summary>
|
||||
/// Reagent effects describe behavior that occurs when a reagent is ingested and metabolized by some
|
||||
/// organ. They only trigger when all of <see cref="Conditions"/> are satisfied.
|
||||
/// </summary>
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class ReagentEffect
|
||||
{
|
||||
[JsonPropertyName("id")] private protected string _id => this.GetType().Name;
|
||||
/// <summary>
|
||||
/// The list of conditions required for the effect to activate. Not required.
|
||||
/// </summary>
|
||||
[JsonPropertyName("conditions")]
|
||||
[DataField("conditions")]
|
||||
public ReagentEffectCondition[]? Conditions;
|
||||
|
||||
public virtual string ReagentEffectFormat => "guidebook-reagent-effect-description";
|
||||
|
||||
protected abstract string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys);
|
||||
|
||||
/// <summary>
|
||||
/// What's the chance, from 0 to 1, that this effect will occur?
|
||||
/// </summary>
|
||||
[JsonPropertyName("probability")]
|
||||
[DataField("probability")]
|
||||
public float Probability = 1.0f;
|
||||
|
||||
[JsonIgnore]
|
||||
[DataField("logImpact")]
|
||||
public virtual LogImpact LogImpact { get; private set; } = LogImpact.Low;
|
||||
|
||||
/// <summary>
|
||||
/// Should this reagent effect log at all?
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
[DataField("shouldLog")]
|
||||
public virtual bool ShouldLog { get; private set; } = false;
|
||||
|
||||
public abstract void Effect(ReagentEffectArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Produces a localized, bbcode'd guidebook description for this effect.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string? GuidebookEffectDescription(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
var effect = ReagentEffectGuidebookText(prototype, entSys);
|
||||
if (effect is null)
|
||||
return null;
|
||||
|
||||
return Loc.GetString(ReagentEffectFormat, ("effect", effect), ("chance", Probability),
|
||||
("conditionCount", Conditions?.Length ?? 0),
|
||||
("conditions",
|
||||
ContentLocalizationManager.FormatList(Conditions?.Select(x => x.GuidebookExplanation(prototype)).ToList() ??
|
||||
new List<string>())));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReagentEffectExt
|
||||
{
|
||||
public static bool ShouldApply(this ReagentEffect effect, ReagentEffectArgs args,
|
||||
IRobustRandom? random = null)
|
||||
{
|
||||
if (random == null)
|
||||
random = IoCManager.Resolve<IRobustRandom>();
|
||||
|
||||
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 Quantity,
|
||||
IEntityManager EntityManager,
|
||||
ReactionMethod? Method,
|
||||
float Scale
|
||||
);
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.Chemistry.Reagent
|
||||
{
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class ReagentEffectCondition
|
||||
{
|
||||
[JsonPropertyName("id")] private protected string _id => this.GetType().Name;
|
||||
|
||||
public abstract bool Condition(ReagentEffectArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Effect explanations are of the form "[chance to] [action] when [condition] and [condition]"
|
||||
/// </summary>
|
||||
/// <param name="prototype"></param>
|
||||
/// <returns></returns>
|
||||
public abstract string GuidebookExplanation(IPrototypeManager prototype);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Frozen;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Body.Prototypes;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.EntityEffects;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Nutrition;
|
||||
@@ -134,7 +135,7 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
public List<ITileReaction> TileReactions = new(0);
|
||||
|
||||
[DataField("plantMetabolism", serverOnly: true)]
|
||||
public List<ReagentEffect> PlantMetabolisms = new(0);
|
||||
public List<EntityEffect> PlantMetabolisms = new(0);
|
||||
|
||||
[DataField]
|
||||
public float PricePerUnit;
|
||||
@@ -170,7 +171,7 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
|
||||
var entMan = IoCManager.Resolve<IEntityManager>();
|
||||
var random = IoCManager.Resolve<IRobustRandom>();
|
||||
var args = new ReagentEffectArgs(plantHolder.Value, null, solution, this, amount.Quantity, entMan, null, 1f);
|
||||
var args = new EntityEffectReagentArgs(plantHolder.Value, entMan, null, solution, amount.Quantity, this, null, 1f);
|
||||
foreach (var plantMetabolizable in PlantMetabolisms)
|
||||
{
|
||||
if (!plantMetabolizable.ShouldApply(args, random))
|
||||
@@ -178,7 +179,7 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
|
||||
if (plantMetabolizable.ShouldLog)
|
||||
{
|
||||
var entity = args.SolutionEntity;
|
||||
var entity = args.TargetEntity;
|
||||
entMan.System<SharedAdminLogSystem>().Add(LogType.ReagentEffect, plantMetabolizable.LogImpact,
|
||||
$"Plant metabolism effect {plantMetabolizable.GetType().Name:effect} of reagent {ID:reagent} applied on entity {entMan.ToPrettyString(entity):entity} at {entMan.GetComponent<TransformComponent>(entity).Coordinates:coordinates}");
|
||||
}
|
||||
@@ -230,7 +231,7 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
/// </summary>
|
||||
[JsonPropertyName("effects")]
|
||||
[DataField("effects", required: true)]
|
||||
public ReagentEffect[] Effects = default!;
|
||||
public EntityEffect[] Effects = default!;
|
||||
|
||||
public ReagentEffectsGuideEntry MakeGuideEntry(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
@@ -264,6 +265,6 @@ namespace Content.Shared.Chemistry.Reagent
|
||||
public HashSet<ReactionMethod> Methods = default!;
|
||||
|
||||
[DataField("effects", required: true)]
|
||||
public ReagentEffect[] Effects = default!;
|
||||
public EntityEffect[] Effects = default!;
|
||||
}
|
||||
}
|
||||
|
||||
132
Content.Shared/EntityEffects/EntityEffect.cs
Normal file
132
Content.Shared/EntityEffects/EntityEffect.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Localizations;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Toolshed.TypeParsers;
|
||||
|
||||
namespace Content.Shared.EntityEffects;
|
||||
|
||||
/// <summary>
|
||||
/// Entity effects describe behavior that occurs on different kinds of triggers, e.g. when a reagent is ingested and metabolized by some
|
||||
/// organ. They only trigger when all of <see cref="Conditions"/> are satisfied.
|
||||
/// </summary>
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class EntityEffect
|
||||
{
|
||||
private protected string _id => this.GetType().Name;
|
||||
/// <summary>
|
||||
/// The list of conditions required for the effect to activate. Not required.
|
||||
/// </summary>
|
||||
[DataField("conditions")]
|
||||
public EntityEffectCondition[]? Conditions;
|
||||
|
||||
public virtual string ReagentEffectFormat => "guidebook-reagent-effect-description";
|
||||
|
||||
protected abstract string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys);
|
||||
|
||||
/// <summary>
|
||||
/// What's the chance, from 0 to 1, that this effect will occur?
|
||||
/// </summary>
|
||||
[DataField("probability")]
|
||||
public float Probability = 1.0f;
|
||||
|
||||
public virtual LogImpact LogImpact { get; private set; } = LogImpact.Low;
|
||||
|
||||
/// <summary>
|
||||
/// Should this entity effect log at all?
|
||||
/// </summary>
|
||||
public virtual bool ShouldLog { get; private set; } = false;
|
||||
|
||||
public abstract void Effect(EntityEffectBaseArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Produces a localized, bbcode'd guidebook description for this effect.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string? GuidebookEffectDescription(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
{
|
||||
var effect = ReagentEffectGuidebookText(prototype, entSys);
|
||||
if (effect is null)
|
||||
return null;
|
||||
|
||||
return Loc.GetString(ReagentEffectFormat, ("effect", effect), ("chance", Probability),
|
||||
("conditionCount", Conditions?.Length ?? 0),
|
||||
("conditions",
|
||||
ContentLocalizationManager.FormatList(Conditions?.Select(x => x.GuidebookExplanation(prototype)).ToList() ??
|
||||
new List<string>())));
|
||||
}
|
||||
}
|
||||
|
||||
public static class EntityEffectExt
|
||||
{
|
||||
public static bool ShouldApply(this EntityEffect effect, EntityEffectBaseArgs args,
|
||||
IRobustRandom? random = null)
|
||||
{
|
||||
if (random == null)
|
||||
random = IoCManager.Resolve<IRobustRandom>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EntityEffectBaseArgs only contains the target of an effect.
|
||||
/// If a trigger wants to include more info (e.g. the quantity of the chemical triggering the effect), it can be extended (see EntityEffectReagentArgs).
|
||||
/// </summary>
|
||||
public record class EntityEffectBaseArgs
|
||||
{
|
||||
public EntityUid TargetEntity;
|
||||
|
||||
public IEntityManager EntityManager = default!;
|
||||
|
||||
public EntityEffectBaseArgs(EntityUid targetEntity, IEntityManager entityManager)
|
||||
{
|
||||
TargetEntity = targetEntity;
|
||||
EntityManager = entityManager;
|
||||
}
|
||||
}
|
||||
|
||||
public record class EntityEffectReagentArgs : EntityEffectBaseArgs
|
||||
{
|
||||
public EntityUid? OrganEntity;
|
||||
|
||||
public Solution? Source;
|
||||
|
||||
public FixedPoint2 Quantity;
|
||||
|
||||
public ReagentPrototype? Reagent;
|
||||
|
||||
public ReactionMethod? Method;
|
||||
|
||||
public FixedPoint2 Scale;
|
||||
|
||||
public EntityEffectReagentArgs(EntityUid targetEntity, IEntityManager entityManager, EntityUid? organEntity, Solution? source, FixedPoint2 quantity, ReagentPrototype? reagent, ReactionMethod? method, FixedPoint2 scale) : base(targetEntity, entityManager)
|
||||
{
|
||||
OrganEntity = organEntity;
|
||||
Source = source;
|
||||
Quantity = quantity;
|
||||
Reagent = reagent;
|
||||
Method = method;
|
||||
Scale = scale;
|
||||
}
|
||||
}
|
||||
22
Content.Shared/EntityEffects/EntityEffectCondition.cs
Normal file
22
Content.Shared/EntityEffects/EntityEffectCondition.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Shared.EntityEffects;
|
||||
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
[MeansImplicitUse]
|
||||
public abstract partial class EntityEffectCondition
|
||||
{
|
||||
[JsonPropertyName("id")] private protected string _id => this.GetType().Name;
|
||||
|
||||
public abstract bool Condition(EntityEffectBaseArgs args);
|
||||
|
||||
/// <summary>
|
||||
/// Effect explanations are of the form "[chance to] [action] when [condition] and [condition]"
|
||||
/// </summary>
|
||||
/// <param name="prototype"></param>
|
||||
/// <returns></returns>
|
||||
public abstract string GuidebookExplanation(IPrototypeManager prototype);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user