From bf41de18aa07dca253975e15c1722a1813742f5b Mon Sep 17 00:00:00 2001 From: pathetic meowmeow Date: Fri, 23 May 2025 12:32:22 -0400 Subject: [PATCH] Move entity effects definitions to shared (#35614) * Move entity effects to shared * relocate spawning to server * Generic version of EntityEffect for just raising event. * genericise everything * oops forgot to push you * some condensation * finish rebas * unwhite the space * oops forgot nuke * bad rebase fix * useless annotations begone --------- Co-authored-by: EmoGarbage404 --- .../Body/Systems/BloodstreamSystem.cs | 2 +- .../Body/Systems/RespiratorSystem.cs | 8 +- Content.Server/Botany/SeedPrototype.cs | 4 +- .../EffectConditions/BreathingCondition.cs | 33 - .../EffectConditions/OrganType.cs | 53 - .../Effects/AdjustTemperature.cs | 35 - .../Effects/AreaReactionEffect.cs | 95 -- .../Effects/CauseZombieInfection.cs | 21 - .../Effects/ChemCleanBloodstream.cs | 40 - .../EntityEffects/Effects/ChemVomit.cs | 35 - .../Effects/CreateEntityReactionEffect.cs | 50 - .../EntityEffects/Effects/CreateGas.cs | 52 - .../Effects/CureZombieInfection.cs | 37 - .../Effects/EmpReactionEffect.cs | 58 -- .../Effects/FlammableReaction.cs | 48 - .../Effects/FlashReactionEffect.cs | 82 -- .../EntityEffects/Effects/Ignite.cs | 36 - .../EntityEffects/Effects/MakeSentient.cs | 44 - .../Effects/ModifyBleedAmount.cs | 35 - .../EntityEffects/Effects/ModifyBloodLevel.cs | 37 - .../EntityEffects/Effects/ModifyLungGas.cs | 48 - .../EntityEffects/Effects/Oxygenate.cs | 32 - .../EntityEffects/Effects/PlantChangeStat.cs | 142 --- .../PlantMetabolism/PlantAdjustHealth.cs | 21 - .../PlantAdjustMutationLevel.cs | 16 - .../PlantMetabolism/PlantAdjustMutationMod.cs | 19 - .../PlantMetabolism/PlantAdjustNutrition.cs | 21 - .../PlantMetabolism/PlantAdjustPests.cs | 20 - .../PlantMetabolism/PlantAdjustPotency.cs | 28 - .../PlantMetabolism/PlantAdjustToxins.cs | 20 - .../PlantMetabolism/PlantAdjustWater.cs | 22 - .../PlantMetabolism/PlantAdjustWeeds.cs | 19 - .../PlantMetabolism/PlantAffectGrowth.cs | 22 - .../PlantMetabolism/PlantCryoxadone.cs | 33 - .../PlantMetabolism/PlantDestroySeeds.cs | 42 - .../PlantMetabolism/PlantDiethylamine.cs | 41 - .../PlantMetabolism/PlantPhalanximine.cs | 23 - .../PlantMetabolism/PlantRestoreSeeds.cs | 38 - .../Effects/PlantMetabolism/RobustHarvest.cs | 53 - .../Effects/PlantMutateChemicals.cs | 55 - .../EntityEffects/Effects/PlantMutateGases.cs | 87 -- .../Effects/PlantMutateHarvest.cs | 30 - .../Effects/PlantSpeciesChange.cs | 43 - .../EntityEffects/Effects/ReduceRotting.cs | 35 - .../EntityEffects/Effects/ResetNarcolepsy.cs | 32 - .../EntityEffects/Effects/SatiateHunger.cs | 43 - .../EntityEffects/EntityEffectSystem.cs | 975 ++++++++++++++++++ .../Fluids/EntitySystems/SmokeSystem.cs | 2 +- .../Nutrition/EntitySystems/DrinkSystem.cs | 2 +- .../Chemistry/Reaction/ReactionPrototype.cs | 2 +- .../Chemistry/Reagent/ReagentPrototype.cs | 6 +- .../EffectConditions/BodyTemperature.cs | 16 +- .../EffectConditions/BreathingCondition.cs | 21 + .../EffectConditions/HasTagCondition.cs | 5 +- .../EffectConditions/InternalsCondition.cs | 0 .../EffectConditions/JobCondition.cs | 3 +- .../EffectConditions/MobStateCondition.cs | 3 +- .../EffectConditions/OrganType.cs | 28 + .../EffectConditions/ReagentThreshold.cs | 3 +- .../EffectConditions/SolutionTemperature.cs | 3 +- .../EffectConditions/TotalDamage.cs | 2 +- .../EffectConditions/TotalHunger.cs | 2 +- .../Effects/AddToSolutionReaction.cs | 5 +- .../EntityEffects/Effects/AdjustAlert.cs | 3 +- .../EntityEffects/Effects/AdjustReagent.cs | 6 +- .../Effects/AdjustTemperature.cs | 15 + .../Effects/AreaReactionEffect.cs | 43 + .../EntityEffects/Effects/ArtifactUnlock.cs | 11 +- .../Effects/CauseZombieInfection.cs | 9 + .../Effects/ChemCleanBloodstream.cs | 15 + .../Effects/ChemHealEyeDamage.cs | 5 +- .../EntityEffects/Effects/ChemVomit.cs | 19 + .../Effects/CreateEntityReactionEffect.cs | 26 + .../EntityEffects/Effects/CreateGas.cs | 32 + .../Effects/CureZombieInfection.cs | 18 + .../EntityEffects/Effects/Drunk.cs | 5 +- .../EntityEffects/Effects/Electrocute.cs | 9 +- .../EntityEffects/Effects/Emote.cs | 17 +- .../Effects/EmpReactionEffect.cs | 34 + .../EntityEffects/Effects/EvenHealthChange.cs | 4 +- .../Effects/ExplosionReactionEffect.cs | 27 +- .../Effects/ExtinguishReaction.cs | 5 +- .../Effects/FlammableReaction.cs | 21 + .../Effects/FlashReactionEffect.cs | 48 + .../EntityEffects/Effects/Glow.cs | 2 +- .../EntityEffects/Effects/HealthChange.cs | 4 +- .../EntityEffects/Effects/Ignite.cs | 18 + .../EntityEffects/Effects/MakeSentient.cs | 10 + .../Effects/ModifyBleedAmount.cs | 16 + .../EntityEffects/Effects/ModifyBloodLevel.cs | 17 + .../EntityEffects/Effects/ModifyLungGas.cs | 14 + .../Effects/MovespeedModifier.cs | 3 +- .../EntityEffects/Effects/Oxygenate.cs | 13 + .../EntityEffects/Effects/Paralyze.cs | 6 +- .../PlantMetabolism/PlantAdjustAttribute.cs | 26 +- .../PlantMetabolism/PlantAdjustHealth.cs | 7 + .../PlantAdjustMutationLevel.cs | 6 + .../PlantMetabolism/PlantAdjustMutationMod.cs | 6 + .../PlantMetabolism/PlantAdjustNutrition.cs | 6 + .../PlantMetabolism/PlantAdjustPests.cs | 7 + .../PlantMetabolism/PlantAdjustPotency.cs | 12 + .../PlantMetabolism/PlantAdjustToxins.cs | 8 + .../PlantMetabolism/PlantAdjustWater.cs | 7 + .../PlantMetabolism/PlantAdjustWeeds.cs | 7 + .../PlantMetabolism/PlantAffectGrowth.cs | 7 + .../PlantMetabolism/PlantChangeStat.cs | 24 + .../PlantMetabolism/PlantCryoxadone.cs | 8 + .../PlantMetabolism/PlantDestroySeeds.cs | 13 + .../PlantMetabolism/PlantDiethylamine.cs | 9 + .../PlantMetabolism/PlantPhalanximine.cs | 8 + .../PlantMetabolism/PlantRestoreSeeds.cs | 12 + .../Effects/PlantMetabolism/RobustHarvest.cs | 18 + .../Effects/PlantMutateChemicals.cs | 16 + .../EntityEffects/Effects/PlantMutateGases.cs | 39 + .../Effects/PlantMutateHarvest.cs | 14 + .../Effects/PlantSpeciesChange.cs | 14 + .../EntityEffects/Effects/Polymorph.cs | 18 +- .../EntityEffects/Effects/PopupMessage.cs | 3 +- .../EntityEffects/Effects/ReduceRotting.cs | 32 + .../EntityEffects/Effects/ResetNarcolepsy.cs | 19 + .../EntityEffects/Effects/SatiateHunger.cs | 40 + .../EntityEffects/Effects/SatiateThirst.cs | 3 +- .../EntityEffects/Effects/Slipify.cs | 3 +- .../Effects/SolutionTemperatureEffects.cs | 3 +- .../StatusEffects/GenericStatusEffect.cs | 5 +- .../Effects/StatusEffects/Jitter.cs | 3 +- .../Effects/WashCreamPieReaction.cs | 9 +- .../EntityEffects/Effects/WearableReaction.cs | 3 +- Content.Shared/EntityEffects/EntityEffect.cs | 13 + .../EntityEffects/EntityEffectCondition.cs | 7 + .../EntityEffects/EventEntityEffect.cs | 12 + .../EventEntityEffectCondition.cs | 14 + 132 files changed, 1843 insertions(+), 1961 deletions(-) delete mode 100644 Content.Server/EntityEffects/EffectConditions/BreathingCondition.cs delete mode 100644 Content.Server/EntityEffects/EffectConditions/OrganType.cs delete mode 100644 Content.Server/EntityEffects/Effects/AdjustTemperature.cs delete mode 100644 Content.Server/EntityEffects/Effects/AreaReactionEffect.cs delete mode 100644 Content.Server/EntityEffects/Effects/CauseZombieInfection.cs delete mode 100644 Content.Server/EntityEffects/Effects/ChemCleanBloodstream.cs delete mode 100644 Content.Server/EntityEffects/Effects/ChemVomit.cs delete mode 100644 Content.Server/EntityEffects/Effects/CreateEntityReactionEffect.cs delete mode 100644 Content.Server/EntityEffects/Effects/CreateGas.cs delete mode 100644 Content.Server/EntityEffects/Effects/CureZombieInfection.cs delete mode 100644 Content.Server/EntityEffects/Effects/EmpReactionEffect.cs delete mode 100644 Content.Server/EntityEffects/Effects/FlammableReaction.cs delete mode 100644 Content.Server/EntityEffects/Effects/FlashReactionEffect.cs delete mode 100644 Content.Server/EntityEffects/Effects/Ignite.cs delete mode 100644 Content.Server/EntityEffects/Effects/MakeSentient.cs delete mode 100644 Content.Server/EntityEffects/Effects/ModifyBleedAmount.cs delete mode 100644 Content.Server/EntityEffects/Effects/ModifyBloodLevel.cs delete mode 100644 Content.Server/EntityEffects/Effects/ModifyLungGas.cs delete mode 100644 Content.Server/EntityEffects/Effects/Oxygenate.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantChangeStat.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustHealth.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationLevel.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationMod.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustNutrition.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPotency.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWater.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAffectGrowth.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantCryoxadone.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantDestroySeeds.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantDiethylamine.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantPhalanximine.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/PlantRestoreSeeds.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMetabolism/RobustHarvest.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMutateGases.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMutateHarvest.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs delete mode 100644 Content.Server/EntityEffects/Effects/ReduceRotting.cs delete mode 100644 Content.Server/EntityEffects/Effects/ResetNarcolepsy.cs delete mode 100644 Content.Server/EntityEffects/Effects/SatiateHunger.cs create mode 100644 Content.Server/EntityEffects/EntityEffectSystem.cs rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/BodyTemperature.cs (52%) create mode 100644 Content.Shared/EntityEffects/EffectConditions/BreathingCondition.cs rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/HasTagCondition.cs (86%) rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/InternalsCondition.cs (100%) rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/JobCondition.cs (95%) rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/MobStateCondition.cs (88%) create mode 100644 Content.Shared/EntityEffects/EffectConditions/OrganType.cs rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/ReagentThreshold.cs (95%) rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/SolutionTemperature.cs (92%) rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/TotalDamage.cs (94%) rename {Content.Server => Content.Shared}/EntityEffects/EffectConditions/TotalHunger.cs (94%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/AddToSolutionReaction.cs (91%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/AdjustAlert.cs (95%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/AdjustReagent.cs (96%) create mode 100644 Content.Shared/EntityEffects/Effects/AdjustTemperature.cs create mode 100644 Content.Shared/EntityEffects/Effects/AreaReactionEffect.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/ArtifactUnlock.cs (84%) create mode 100644 Content.Shared/EntityEffects/Effects/CauseZombieInfection.cs create mode 100644 Content.Shared/EntityEffects/Effects/ChemCleanBloodstream.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/ChemHealEyeDamage.cs (87%) create mode 100644 Content.Shared/EntityEffects/Effects/ChemVomit.cs create mode 100644 Content.Shared/EntityEffects/Effects/CreateEntityReactionEffect.cs create mode 100644 Content.Shared/EntityEffects/Effects/CreateGas.cs create mode 100644 Content.Shared/EntityEffects/Effects/CureZombieInfection.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/Drunk.cs (91%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/Electrocute.cs (78%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/Emote.cs (70%) create mode 100644 Content.Shared/EntityEffects/Effects/EmpReactionEffect.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/EvenHealthChange.cs (98%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/ExplosionReactionEffect.cs (74%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/ExtinguishReaction.cs (88%) create mode 100644 Content.Shared/EntityEffects/Effects/FlammableReaction.cs create mode 100644 Content.Shared/EntityEffects/Effects/FlashReactionEffect.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/Glow.cs (96%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/HealthChange.cs (98%) create mode 100644 Content.Shared/EntityEffects/Effects/Ignite.cs create mode 100644 Content.Shared/EntityEffects/Effects/MakeSentient.cs create mode 100644 Content.Shared/EntityEffects/Effects/ModifyBleedAmount.cs create mode 100644 Content.Shared/EntityEffects/Effects/ModifyBloodLevel.cs create mode 100644 Content.Shared/EntityEffects/Effects/ModifyLungGas.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/MovespeedModifier.cs (97%) create mode 100644 Content.Shared/EntityEffects/Effects/Oxygenate.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/Paralyze.cs (79%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/PlantMetabolism/PlantAdjustAttribute.cs (51%) create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustHealth.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationLevel.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationMod.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustNutrition.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustPotency.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustWater.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAffectGrowth.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantChangeStat.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantCryoxadone.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantDestroySeeds.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantDiethylamine.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantPhalanximine.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantRestoreSeeds.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMetabolism/RobustHarvest.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMutateChemicals.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMutateGases.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantMutateHarvest.cs create mode 100644 Content.Shared/EntityEffects/Effects/PlantSpeciesChange.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/Polymorph.cs (55%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/PopupMessage.cs (95%) create mode 100644 Content.Shared/EntityEffects/Effects/ReduceRotting.cs create mode 100644 Content.Shared/EntityEffects/Effects/ResetNarcolepsy.cs create mode 100644 Content.Shared/EntityEffects/Effects/SatiateHunger.cs rename {Content.Server => Content.Shared}/EntityEffects/Effects/SatiateThirst.cs (93%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/Slipify.cs (95%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/SolutionTemperatureEffects.cs (98%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/StatusEffects/GenericStatusEffect.cs (94%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/StatusEffects/Jitter.cs (92%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/WashCreamPieReaction.cs (67%) rename {Content.Server => Content.Shared}/EntityEffects/Effects/WearableReaction.cs (94%) create mode 100644 Content.Shared/EntityEffects/EventEntityEffect.cs create mode 100644 Content.Shared/EntityEffects/EventEntityEffectCondition.cs diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index 6dc03fed74..1072997151 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -1,5 +1,5 @@ using Content.Server.Body.Components; -using Content.Server.EntityEffects.Effects; +using Content.Shared.EntityEffects.Effects; using Content.Server.Fluids.EntitySystems; using Content.Server.Popups; using Content.Shared.Alert; diff --git a/Content.Server/Body/Systems/RespiratorSystem.cs b/Content.Server/Body/Systems/RespiratorSystem.cs index bebf92f977..e068aa9c7a 100644 --- a/Content.Server/Body/Systems/RespiratorSystem.cs +++ b/Content.Server/Body/Systems/RespiratorSystem.cs @@ -2,8 +2,9 @@ using Content.Server.Administration.Logs; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; using Content.Server.Chat.Systems; -using Content.Server.EntityEffects.EffectConditions; -using Content.Server.EntityEffects.Effects; +using Content.Server.EntityEffects; +using Content.Shared.EntityEffects.EffectConditions; +using Content.Shared.EntityEffects.Effects; using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Alert; using Content.Shared.Atmos; @@ -35,6 +36,7 @@ public sealed class RespiratorSystem : EntitySystem [Dependency] private readonly IPrototypeManager _protoMan = default!; [Dependency] private readonly SharedSolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly EntityEffectSystem _entityEffect = default!; private static readonly ProtoId GasId = new("Gas"); @@ -283,7 +285,7 @@ public sealed class RespiratorSystem : EntitySystem foreach (var cond in effect.Conditions) { - if (cond is OrganType organ && !organ.Condition(lung, EntityManager)) + if (cond is OrganType organ && !_entityEffect.OrganCondition(organ, lung)) return false; } diff --git a/Content.Server/Botany/SeedPrototype.cs b/Content.Server/Botany/SeedPrototype.cs index 22021f1fab..ae182cbe7e 100644 --- a/Content.Server/Botany/SeedPrototype.cs +++ b/Content.Server/Botany/SeedPrototype.cs @@ -10,6 +10,8 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.Utility; +using Content.Server.EntityEffects; + namespace Content.Server.Botany; [Prototype] @@ -82,7 +84,7 @@ public partial struct SeedChemQuantity // TODO reduce the number of friends to a reasonable level. Requires ECS-ing things like plant holder component. [Virtual, DataDefinition] -[Access(typeof(BotanySystem), typeof(PlantHolderSystem), typeof(SeedExtractorSystem), typeof(PlantHolderComponent), typeof(EntityEffect), typeof(MutationSystem))] +[Access(typeof(BotanySystem), typeof(PlantHolderSystem), typeof(SeedExtractorSystem), typeof(PlantHolderComponent), typeof(EntityEffectSystem), typeof(MutationSystem))] public partial class SeedData { #region Tracking diff --git a/Content.Server/EntityEffects/EffectConditions/BreathingCondition.cs b/Content.Server/EntityEffects/EffectConditions/BreathingCondition.cs deleted file mode 100644 index d87e686f2b..0000000000 --- a/Content.Server/EntityEffects/EffectConditions/BreathingCondition.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Content.Server.Body.Components; -using Content.Server.Body.Systems; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.EffectConditions; - -/// -/// Condition for if the entity is successfully breathing. -/// -public sealed partial class Breathing : EntityEffectCondition -{ - /// - /// If true, the entity must not have trouble breathing to pass. - /// - [DataField] - public bool IsBreathing = true; - - public override bool Condition(EntityEffectBaseArgs args) - { - if (!args.EntityManager.TryGetComponent(args.TargetEntity, out RespiratorComponent? respiratorComp)) - return !IsBreathing; // They do not breathe. - - var breathingState = args.EntityManager.System().IsBreathing((args.TargetEntity, respiratorComp)); - return IsBreathing == breathingState; - } - - public override string GuidebookExplanation(IPrototypeManager prototype) - { - return Loc.GetString("reagent-effect-condition-guidebook-breathing", - ("isBreathing", IsBreathing)); - } -} diff --git a/Content.Server/EntityEffects/EffectConditions/OrganType.cs b/Content.Server/EntityEffects/EffectConditions/OrganType.cs deleted file mode 100644 index fc52608fab..0000000000 --- a/Content.Server/EntityEffects/EffectConditions/OrganType.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Content.Server.Body.Components; -using Content.Shared.Body.Prototypes; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; - -namespace Content.Server.EntityEffects.EffectConditions; - -/// -/// Requires that the metabolizing organ is or is not tagged with a certain MetabolizerType -/// -public sealed partial class OrganType : EntityEffectCondition -{ - [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Type = default!; - - /// - /// Does this condition pass when the organ has the type, or when it doesn't have the type? - /// - [DataField] - public bool ShouldHave = true; - - public override bool Condition(EntityEffectBaseArgs args) - { - if (args is EntityEffectReagentArgs reagentArgs) - { - if (reagentArgs.OrganEntity == null) - return false; - - return Condition(reagentArgs.OrganEntity.Value, reagentArgs.EntityManager); - } - - // TODO: Someone needs to figure out how to do this for non-reagent effects. - throw new NotImplementedException(); - } - - public bool Condition(Entity metabolizer, IEntityManager entMan) - { - metabolizer.Comp ??= entMan.GetComponentOrNull(metabolizer.Owner); - if (metabolizer.Comp != null - && metabolizer.Comp.MetabolizerTypes != null - && metabolizer.Comp.MetabolizerTypes.Contains(Type)) - return ShouldHave; - return !ShouldHave; - } - - public override string GuidebookExplanation(IPrototypeManager prototype) - { - return Loc.GetString("reagent-effect-condition-guidebook-organ-type", - ("name", prototype.Index(Type).LocalizedName), - ("shouldhave", ShouldHave)); - } -} diff --git a/Content.Server/EntityEffects/Effects/AdjustTemperature.cs b/Content.Server/EntityEffects/Effects/AdjustTemperature.cs deleted file mode 100644 index 3c5c77c309..0000000000 --- a/Content.Server/EntityEffects/Effects/AdjustTemperature.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Content.Server.Temperature.Components; -using Content.Server.Temperature.Systems; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects -{ - public sealed partial class AdjustTemperature : EntityEffect - { - [DataField] - public float Amount; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-adjust-temperature", - ("chance", Probability), - ("deltasign", MathF.Sign(Amount)), - ("amount", MathF.Abs(Amount))); - - public override void Effect(EntityEffectBaseArgs args) - { - if (args.EntityManager.TryGetComponent(args.TargetEntity, out TemperatureComponent? temp)) - { - var sys = args.EntityManager.EntitySysManager.GetEntitySystem(); - var amount = Amount; - - if (args is EntityEffectReagentArgs reagentArgs) - { - amount *= reagentArgs.Scale.Float(); - } - - sys.ChangeHeat(args.TargetEntity, amount, true, temp); - } - } - } -} diff --git a/Content.Server/EntityEffects/Effects/AreaReactionEffect.cs b/Content.Server/EntityEffects/Effects/AreaReactionEffect.cs deleted file mode 100644 index ce06705b2b..0000000000 --- a/Content.Server/EntityEffects/Effects/AreaReactionEffect.cs +++ /dev/null @@ -1,95 +0,0 @@ -using Content.Server.Fluids.EntitySystems; -using Content.Server.Spreader; -using Content.Shared.Audio; -using Content.Shared.Coordinates.Helpers; -using Content.Shared.Database; -using Content.Shared.EntityEffects; -using Content.Shared.FixedPoint; -using Content.Shared.Maps; -using JetBrains.Annotations; -using Robust.Server.GameObjects; -using Robust.Shared.Audio; -using Robust.Shared.Audio.Systems; -using Robust.Shared.Map; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Basically smoke and foam reactions. -/// -[UsedImplicitly] -[DataDefinition] -public sealed partial class AreaReactionEffect : EntityEffect -{ - /// - /// How many seconds will the effect stay, counting after fully spreading. - /// - [DataField("duration")] private float _duration = 10; - - /// - /// How many units of reaction for 1 smoke entity. - /// - [DataField] public FixedPoint2 OverflowThreshold = FixedPoint2.New(2.5); - - /// - /// The entity prototype that will be spawned as the effect. - /// - [DataField("prototypeId", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] - private string _prototypeId = default!; - - /// - /// Sound that will get played when this reaction effect occurs. - /// - [DataField("sound", required: true)] private SoundSpecifier _sound = default!; - - public override bool ShouldLog => true; - - protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-area-reaction", - ("duration", _duration) - ); - - public override LogImpact LogImpact => LogImpact.High; - - public override void Effect(EntityEffectBaseArgs args) - { - if (args is EntityEffectReagentArgs reagentArgs) - { - if (reagentArgs.Source == null) - return; - - var spreadAmount = (int) Math.Max(0, Math.Ceiling((reagentArgs.Quantity / OverflowThreshold).Float())); - var splitSolution = reagentArgs.Source.SplitSolution(reagentArgs.Source.Volume); - var transform = reagentArgs.EntityManager.GetComponent(reagentArgs.TargetEntity); - var mapManager = IoCManager.Resolve(); - var mapSys = reagentArgs.EntityManager.System(); - var spreaderSys = args.EntityManager.System(); - var sys = args.EntityManager.System(); - var mapCoords = sys.GetMapCoordinates(reagentArgs.TargetEntity, xform: transform); - - if (!mapManager.TryFindGridAt(mapCoords, out var gridUid, out var grid) || - !mapSys.TryGetTileRef(gridUid, grid, transform.Coordinates, out var tileRef)) - { - return; - } - - if (spreaderSys.RequiresFloorToSpread(_prototypeId) && tileRef.Tile.IsSpace()) - return; - - var coords = mapSys.MapToGrid(gridUid, mapCoords); - var ent = reagentArgs.EntityManager.SpawnEntity(_prototypeId, coords.SnapToGrid()); - - var smoke = reagentArgs.EntityManager.System(); - smoke.StartSmoke(ent, splitSolution, _duration, spreadAmount); - - var audio = reagentArgs.EntityManager.System(); - audio.PlayPvs(_sound, reagentArgs.TargetEntity, AudioParams.Default.WithVariation(0.25f)); - return; - } - - // TODO: Someone needs to figure out how to do this for non-reagent effects. - throw new NotImplementedException(); - } -} diff --git a/Content.Server/EntityEffects/Effects/CauseZombieInfection.cs b/Content.Server/EntityEffects/Effects/CauseZombieInfection.cs deleted file mode 100644 index b71e6a30e0..0000000000 --- a/Content.Server/EntityEffects/Effects/CauseZombieInfection.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Content.Server.Zombies; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; -using Content.Shared.Zombies; - -namespace Content.Server.EntityEffects.Effects; - -public sealed partial class CauseZombieInfection : EntityEffect -{ - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-cause-zombie-infection", ("chance", Probability)); - - // Adds the Zombie Infection Components - public override void Effect(EntityEffectBaseArgs args) - { - var entityManager = args.EntityManager; - entityManager.EnsureComponent(args.TargetEntity); - entityManager.EnsureComponent(args.TargetEntity); - } -} - diff --git a/Content.Server/EntityEffects/Effects/ChemCleanBloodstream.cs b/Content.Server/EntityEffects/Effects/ChemCleanBloodstream.cs deleted file mode 100644 index b7f6f0dc88..0000000000 --- a/Content.Server/EntityEffects/Effects/ChemCleanBloodstream.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Content.Server.Body.Systems; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Basically smoke and foam reactions. -/// -[UsedImplicitly] -public sealed partial class ChemCleanBloodstream : EntityEffect -{ - [DataField] - public float CleanseRate = 3.0f; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-chem-clean-bloodstream", ("chance", Probability)); - - public override void Effect(EntityEffectBaseArgs args) - { - - var cleanseRate = CleanseRate; - - var bloodstreamSys = args.EntityManager.System(); - - if (args is EntityEffectReagentArgs reagentArgs) - { - if (reagentArgs.Source == null || reagentArgs.Reagent == null) - return; - - cleanseRate *= reagentArgs.Scale.Float(); - bloodstreamSys.FlushChemicals(args.TargetEntity, reagentArgs.Reagent.ID, cleanseRate); - } - else - { - bloodstreamSys.FlushChemicals(args.TargetEntity, "", cleanseRate); - } - } -} diff --git a/Content.Server/EntityEffects/Effects/ChemVomit.cs b/Content.Server/EntityEffects/Effects/ChemVomit.cs deleted file mode 100644 index 0d1bac87d1..0000000000 --- a/Content.Server/EntityEffects/Effects/ChemVomit.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Content.Server.Medical; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects -{ - /// - /// Forces you to vomit. - /// - [UsedImplicitly] - public sealed partial class ChemVomit : EntityEffect - { - /// How many units of thirst to add each time we vomit - [DataField] - public float ThirstAmount = -8f; - /// How many units of hunger to add each time we vomit - [DataField] - public float HungerAmount = -8f; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-chem-vomit", ("chance", Probability)); - - public override void Effect(EntityEffectBaseArgs args) - { - if (args is EntityEffectReagentArgs reagentArgs) - if (reagentArgs.Scale != 1f) - return; - - var vomitSys = args.EntityManager.EntitySysManager.GetEntitySystem(); - - vomitSys.Vomit(args.TargetEntity, ThirstAmount, HungerAmount); - } - } -} diff --git a/Content.Server/EntityEffects/Effects/CreateEntityReactionEffect.cs b/Content.Server/EntityEffects/Effects/CreateEntityReactionEffect.cs deleted file mode 100644 index 5288cb587d..0000000000 --- a/Content.Server/EntityEffects/Effects/CreateEntityReactionEffect.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; - -namespace Content.Server.EntityEffects.Effects; - -[DataDefinition] -public sealed partial class CreateEntityReactionEffect : EntityEffect -{ - /// - /// What entity to create. - /// - [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] - public string Entity = default!; - - /// - /// How many entities to create per unit reaction. - /// - [DataField] - public uint Number = 1; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-create-entity-reaction-effect", - ("chance", Probability), - ("entname", IoCManager.Resolve().Index(Entity).Name), - ("amount", Number)); - - public override void Effect(EntityEffectBaseArgs args) - { - var transform = args.EntityManager.GetComponent(args.TargetEntity); - var transformSystem = args.EntityManager.System(); - var quantity = (int)Number; - if (args is EntityEffectReagentArgs reagentArgs) - quantity *= reagentArgs.Quantity.Int(); - - for (var i = 0; i < quantity; i++) - { - var uid = args.EntityManager.SpawnEntity(Entity, transformSystem.GetMapCoordinates(args.TargetEntity, xform: transform)); - transformSystem.AttachToGridOrMap(uid); - - // TODO figure out how to properly spawn inside of containers - // e.g. cheese: - // if the user is holding a bowl milk & enzyme, should drop to floor, not attached to the user. - // if reaction happens in a backpack, should insert cheese into backpack. - // --> if it doesn't fit, iterate through parent storage until it attaches to the grid (again, DON'T attach to players). - // if the reaction happens INSIDE a stomach? the bloodstream? I have no idea how to handle that. - // presumably having cheese materialize inside of your blood would have "disadvantages". - } - } -} diff --git a/Content.Server/EntityEffects/Effects/CreateGas.cs b/Content.Server/EntityEffects/Effects/CreateGas.cs deleted file mode 100644 index fb57a43c48..0000000000 --- a/Content.Server/EntityEffects/Effects/CreateGas.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Atmos; -using Content.Shared.Database; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -public sealed partial class CreateGas : EntityEffect -{ - [DataField(required: true)] - public Gas Gas = default!; - - /// - /// For each unit consumed, how many moles of gas should be created? - /// - [DataField] - public float Multiplier = 3f; - - public override bool ShouldLog => true; - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - var atmos = entSys.GetEntitySystem(); - var gasProto = atmos.GetGas(Gas); - - return Loc.GetString("reagent-effect-guidebook-create-gas", - ("chance", Probability), - ("moles", Multiplier), - ("gas", gasProto.Name)); - } - - public override LogImpact LogImpact => LogImpact.High; - - public override void Effect(EntityEffectBaseArgs args) - { - var atmosSys = args.EntityManager.EntitySysManager.GetEntitySystem(); - - var tileMix = atmosSys.GetContainingMixture(args.TargetEntity, false, true); - - if (tileMix != null) - { - if (args is EntityEffectReagentArgs reagentArgs) - { - tileMix.AdjustMoles(Gas, reagentArgs.Quantity.Float() * Multiplier); - } - else - { - tileMix.AdjustMoles(Gas, Multiplier); - } - } - } -} diff --git a/Content.Server/EntityEffects/Effects/CureZombieInfection.cs b/Content.Server/EntityEffects/Effects/CureZombieInfection.cs deleted file mode 100644 index 8dfc2de055..0000000000 --- a/Content.Server/EntityEffects/Effects/CureZombieInfection.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Content.Server.Zombies; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; -using Content.Shared.Zombies; - -namespace Content.Server.EntityEffects.Effects; - -public sealed partial class CureZombieInfection : EntityEffect -{ - [DataField] - public bool Innoculate; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - if(Innoculate) - return Loc.GetString("reagent-effect-guidebook-innoculate-zombie-infection", ("chance", Probability)); - - return Loc.GetString("reagent-effect-guidebook-cure-zombie-infection", ("chance", Probability)); - } - - // Removes the Zombie Infection Components - public override void Effect(EntityEffectBaseArgs args) - { - var entityManager = args.EntityManager; - if (entityManager.HasComponent(args.TargetEntity)) - return; - - entityManager.RemoveComponent(args.TargetEntity); - entityManager.RemoveComponent(args.TargetEntity); - - if (Innoculate) - { - entityManager.EnsureComponent(args.TargetEntity); - } - } -} - diff --git a/Content.Server/EntityEffects/Effects/EmpReactionEffect.cs b/Content.Server/EntityEffects/Effects/EmpReactionEffect.cs deleted file mode 100644 index ec7801f083..0000000000 --- a/Content.Server/EntityEffects/Effects/EmpReactionEffect.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Content.Server.Emp; -using Content.Shared.EntityEffects; -using Content.Shared.Chemistry.Reagent; -using Robust.Server.GameObjects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - - -[DataDefinition] -public sealed partial class EmpReactionEffect : EntityEffect -{ - /// - /// Impulse range per unit of quantity - /// - [DataField("rangePerUnit")] - public float EmpRangePerUnit = 0.5f; - - /// - /// Maximum impulse range - /// - [DataField("maxRange")] - public float EmpMaxRange = 10; - - /// - /// How much energy will be drain from sources - /// - [DataField] - public float EnergyConsumption = 12500; - - /// - /// Amount of time entities will be disabled - /// - [DataField("duration")] - public float DisableDuration = 15; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-emp-reaction-effect", ("chance", Probability)); - - public override void Effect(EntityEffectBaseArgs args) - { - var tSys = args.EntityManager.System(); - var transform = args.EntityManager.GetComponent(args.TargetEntity); - - var range = EmpRangePerUnit; - - if (args is EntityEffectReagentArgs reagentArgs) - { - range = MathF.Min((float) (reagentArgs.Quantity * EmpRangePerUnit), EmpMaxRange); - } - - args.EntityManager.System() - .EmpPulse(tSys.GetMapCoordinates(args.TargetEntity, xform: transform), - range, - EnergyConsumption, - DisableDuration); - } -} diff --git a/Content.Server/EntityEffects/Effects/FlammableReaction.cs b/Content.Server/EntityEffects/Effects/FlammableReaction.cs deleted file mode 100644 index 8e1f6d81e1..0000000000 --- a/Content.Server/EntityEffects/Effects/FlammableReaction.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Content.Server.Atmos.Components; -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Database; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects -{ - [UsedImplicitly] - public sealed partial class FlammableReaction : EntityEffect - { - [DataField] - public float Multiplier = 0.05f; - - // The fire stack multiplier if fire stacks already exist on target, only works if 0 or greater - [DataField] - public float MultiplierOnExisting = -1f; - - public override bool ShouldLog => true; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-flammable-reaction", ("chance", Probability)); - - public override LogImpact LogImpact => LogImpact.Medium; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!args.EntityManager.TryGetComponent(args.TargetEntity, out FlammableComponent? flammable)) - return; - - // Sets the multiplier for FireStacks to MultiplierOnExisting is 0 or greater and target already has FireStacks - var multiplier = flammable.FireStacks != 0f && MultiplierOnExisting >= 0 ? MultiplierOnExisting : Multiplier; - var quantity = 1f; - if (args is EntityEffectReagentArgs reagentArgs) - { - quantity = reagentArgs.Quantity.Float(); - reagentArgs.EntityManager.System().AdjustFireStacks(args.TargetEntity, quantity * multiplier, flammable); - if (reagentArgs.Reagent != null) - reagentArgs.Source?.RemoveReagent(reagentArgs.Reagent.ID, reagentArgs.Quantity); - } - else - { - args.EntityManager.System().AdjustFireStacks(args.TargetEntity, multiplier, flammable); - } - } - } -} diff --git a/Content.Server/EntityEffects/Effects/FlashReactionEffect.cs b/Content.Server/EntityEffects/Effects/FlashReactionEffect.cs deleted file mode 100644 index fbf99e902d..0000000000 --- a/Content.Server/EntityEffects/Effects/FlashReactionEffect.cs +++ /dev/null @@ -1,82 +0,0 @@ -using Content.Shared.EntityEffects; -using Content.Server.Flash; -using Robust.Server.GameObjects; -using Robust.Shared.Audio; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -[DataDefinition] -public sealed partial class FlashReactionEffect : EntityEffect -{ - /// - /// Flash range per unit of reagent. - /// - [DataField] - public float RangePerUnit = 0.2f; - - /// - /// Maximum flash range. - /// - [DataField] - public float MaxRange = 10f; - - /// - /// How much to entities are slowed down. - /// - [DataField] - public float SlowTo = 0.5f; - - /// - /// The time entities will be flashed in seconds. - /// The default is chosen to be better than the hand flash so it is worth using it for grenades etc. - /// - [DataField] - public float Duration = 4f; - - /// - /// The prototype ID used for the visual effect. - /// - [DataField] - public EntProtoId? FlashEffectPrototype = "ReactionFlash"; - - /// - /// The sound the flash creates. - /// - [DataField] - public SoundSpecifier? Sound = new SoundPathSpecifier("/Audio/Weapons/flash.ogg"); - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-flash-reaction-effect", ("chance", Probability)); - - public override void Effect(EntityEffectBaseArgs args) - { - var transform = args.EntityManager.GetComponent(args.TargetEntity); - var transformSystem = args.EntityManager.System(); - - var range = 1f; - - if (args is EntityEffectReagentArgs reagentArgs) - range = MathF.Min((float)(reagentArgs.Quantity * RangePerUnit), MaxRange); - - args.EntityManager.System().FlashArea( - args.TargetEntity, - null, - range, - Duration * 1000, - slowTo: SlowTo, - sound: Sound); - - if (FlashEffectPrototype == null) - return; - - var uid = args.EntityManager.SpawnEntity(FlashEffectPrototype, transformSystem.GetMapCoordinates(transform)); - transformSystem.AttachToGridOrMap(uid); - - if (!args.EntityManager.TryGetComponent(uid, out var pointLightComp)) - return; - var pointLightSystem = args.EntityManager.System(); - // PointLights with a radius lower than 1.1 are too small to be visible, so this is hardcoded - pointLightSystem.SetRadius(uid, MathF.Max(1.1f, range), pointLightComp); - } -} diff --git a/Content.Server/EntityEffects/Effects/Ignite.cs b/Content.Server/EntityEffects/Effects/Ignite.cs deleted file mode 100644 index 85d7f09145..0000000000 --- a/Content.Server/EntityEffects/Effects/Ignite.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Content.Server.Atmos.Components; -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Database; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Ignites a mob. -/// -public sealed partial class Ignite : EntityEffect -{ - public override bool ShouldLog => true; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-ignite", ("chance", Probability)); - - public override LogImpact LogImpact => LogImpact.Medium; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!args.EntityManager.TryGetComponent(args.TargetEntity, out FlammableComponent? flammable)) - return; - - var flamSys = args.EntityManager.System(); - if (args is EntityEffectReagentArgs reagentArgs) - { - flamSys.Ignite(reagentArgs.TargetEntity, reagentArgs.OrganEntity ?? reagentArgs.TargetEntity, flammable: flammable); - } - else - { - flamSys.Ignite(args.TargetEntity, args.TargetEntity, flammable: flammable); - } - } -} diff --git a/Content.Server/EntityEffects/Effects/MakeSentient.cs b/Content.Server/EntityEffects/Effects/MakeSentient.cs deleted file mode 100644 index c487043848..0000000000 --- a/Content.Server/EntityEffects/Effects/MakeSentient.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Content.Server.Ghost.Roles.Components; -using Content.Server.Speech.Components; -using Content.Shared.EntityEffects; -using Content.Shared.Mind.Components; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -public sealed partial class MakeSentient : EntityEffect -{ - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-make-sentient", ("chance", Probability)); - - public override void Effect(EntityEffectBaseArgs args) - { - var entityManager = args.EntityManager; - var uid = args.TargetEntity; - - // Let affected entities speak normally to make this effect different from, say, the "random sentience" event - // This also works on entities that already have a mind - // We call this before the mind check to allow things like player-controlled mice to be able to benefit from the effect - entityManager.RemoveComponent(uid); - entityManager.RemoveComponent(uid); - - // Stops from adding a ghost role to things like people who already have a mind - if (entityManager.TryGetComponent(uid, out var mindContainer) && mindContainer.HasMind) - { - return; - } - - // Don't add a ghost role to things that already have ghost roles - if (entityManager.TryGetComponent(uid, out GhostRoleComponent? ghostRole)) - { - return; - } - - ghostRole = entityManager.AddComponent(uid); - entityManager.EnsureComponent(uid); - - var entityData = entityManager.GetComponent(uid); - ghostRole.RoleName = entityData.EntityName; - ghostRole.RoleDescription = Loc.GetString("ghost-role-information-cognizine-description"); - } -} diff --git a/Content.Server/EntityEffects/Effects/ModifyBleedAmount.cs b/Content.Server/EntityEffects/Effects/ModifyBleedAmount.cs deleted file mode 100644 index 58bc304f5e..0000000000 --- a/Content.Server/EntityEffects/Effects/ModifyBleedAmount.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Content.Server.Body.Components; -using Content.Server.Body.Systems; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -public sealed partial class ModifyBleedAmount : EntityEffect -{ - [DataField] - public bool Scaled = false; - - [DataField] - public float Amount = -1.0f; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-modify-bleed-amount", ("chance", Probability), - ("deltasign", MathF.Sign(Amount))); - - public override void Effect(EntityEffectBaseArgs args) - { - if (args.EntityManager.TryGetComponent(args.TargetEntity, out var blood)) - { - var sys = args.EntityManager.System(); - var amt = Amount; - if (args is EntityEffectReagentArgs reagentArgs) { - if (Scaled) - amt *= reagentArgs.Quantity.Float(); - amt *= reagentArgs.Scale.Float(); - } - - sys.TryModifyBleedAmount(args.TargetEntity, amt, blood); - } - } -} diff --git a/Content.Server/EntityEffects/Effects/ModifyBloodLevel.cs b/Content.Server/EntityEffects/Effects/ModifyBloodLevel.cs deleted file mode 100644 index d8aca7d284..0000000000 --- a/Content.Server/EntityEffects/Effects/ModifyBloodLevel.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Content.Server.Body.Components; -using Content.Server.Body.Systems; -using Content.Shared.EntityEffects; -using Content.Shared.FixedPoint; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -public sealed partial class ModifyBloodLevel : EntityEffect -{ - [DataField] - public bool Scaled = false; - - [DataField] - public FixedPoint2 Amount = 1.0f; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-modify-blood-level", ("chance", Probability), - ("deltasign", MathF.Sign(Amount.Float()))); - - public override void Effect(EntityEffectBaseArgs args) - { - if (args.EntityManager.TryGetComponent(args.TargetEntity, out var blood)) - { - var sys = args.EntityManager.System(); - var amt = Amount; - if (args is EntityEffectReagentArgs reagentArgs) - { - if (Scaled) - amt *= reagentArgs.Quantity; - amt *= reagentArgs.Scale; - } - - sys.TryModifyBloodLevel(args.TargetEntity, amt, blood); - } - } -} diff --git a/Content.Server/EntityEffects/Effects/ModifyLungGas.cs b/Content.Server/EntityEffects/Effects/ModifyLungGas.cs deleted file mode 100644 index b752cd93b8..0000000000 --- a/Content.Server/EntityEffects/Effects/ModifyLungGas.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Content.Server.Body.Components; -using Content.Shared.Atmos; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -public sealed partial class ModifyLungGas : EntityEffect -{ - [DataField("ratios", required: true)] - private Dictionary _ratios = default!; - - // JUSTIFICATION: This is internal magic that players never directly interact with. - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => null; - - public override void Effect(EntityEffectBaseArgs args) - { - - LungComponent? lung; - float amount = 1f; - - if (args is EntityEffectReagentArgs reagentArgs) - { - if (!args.EntityManager.TryGetComponent(reagentArgs.OrganEntity, out var organLung)) - return; - lung = organLung; - amount = reagentArgs.Quantity.Float(); - } - else - { - if (!args.EntityManager.TryGetComponent(args.TargetEntity, out var organLung)) //Likely needs to be modified to ensure it works correctly - return; - lung = organLung; - } - - if (lung != null) - { - foreach (var (gas, ratio) in _ratios) - { - var quantity = ratio * amount / Atmospherics.BreathMolesToReagentMultiplier; - if (quantity < 0) - quantity = Math.Max(quantity, -lung.Air[(int) gas]); - lung.Air.AdjustMoles(gas, quantity); - } - } - } -} diff --git a/Content.Server/EntityEffects/Effects/Oxygenate.cs b/Content.Server/EntityEffects/Effects/Oxygenate.cs deleted file mode 100644 index 60383188c9..0000000000 --- a/Content.Server/EntityEffects/Effects/Oxygenate.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Content.Server.Body.Components; -using Content.Server.Body.Systems; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -public sealed partial class Oxygenate : EntityEffect -{ - [DataField] - public float Factor = 1f; - - // JUSTIFICATION: This is internal magic that players never directly interact with. - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => null; - - public override void Effect(EntityEffectBaseArgs args) - { - - var multiplier = 1f; - if (args is EntityEffectReagentArgs reagentArgs) - { - multiplier = reagentArgs.Quantity.Float(); - } - - if (args.EntityManager.TryGetComponent(args.TargetEntity, out var resp)) - { - var respSys = args.EntityManager.System(); - respSys.UpdateSaturation(args.TargetEntity, multiplier * Factor, resp); - } - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantChangeStat.cs b/Content.Server/EntityEffects/Effects/PlantChangeStat.cs deleted file mode 100644 index 9592ff779d..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantChangeStat.cs +++ /dev/null @@ -1,142 +0,0 @@ -using Content.Server.Botany; -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -public sealed partial class PlantChangeStat : EntityEffect -{ - [DataField] - public string TargetValue; - - [DataField] - public float MinValue; - - [DataField] - public float MaxValue; - - [DataField] - public int Steps; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantHolder = args.EntityManager.GetComponent(args.TargetEntity); - if (plantHolder == null || plantHolder.Seed == null) - return; - - var member = plantHolder.Seed.GetType().GetField(TargetValue); - var mutationSys = args.EntityManager.System(); - - if (member == null) - { - mutationSys.Log.Error(this.GetType().Name + " Error: Member " + TargetValue + " not found on " + plantHolder.GetType().Name + ". Did you misspell it?"); - return; - } - - var currentValObj = member.GetValue(plantHolder.Seed); - if (currentValObj == null) - return; - - if (member.FieldType == typeof(float)) - { - var floatVal = (float)currentValObj; - MutateFloat(ref floatVal, MinValue, MaxValue, Steps); - member.SetValue(plantHolder.Seed, floatVal); - } - else if (member.FieldType == typeof(int)) - { - var intVal = (int)currentValObj; - MutateInt(ref intVal, (int)MinValue, (int)MaxValue, Steps); - member.SetValue(plantHolder.Seed, intVal); - } - else if (member.FieldType == typeof(bool)) - { - var boolVal = (bool)currentValObj; - boolVal = !boolVal; - member.SetValue(plantHolder.Seed, boolVal); - } - } - - // Mutate reference 'val' between 'min' and 'max' by pretending the value - // is representable by a thermometer code with 'bits' number of bits and - // randomly flipping some of them. - private void MutateFloat(ref float val, float min, float max, int bits) - { - if (min == max) - { - val = min; - return; - } - - // Starting number of bits that are high, between 0 and bits. - // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. - int valInt = (int)MathF.Round((val - min) / (max - min) * bits); - // val may be outside the range of min/max due to starting prototype values, so clamp. - valInt = Math.Clamp(valInt, 0, bits); - - // Probability that the bit flip increases n. - // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasive it it. - // In other words, it tends to go to the middle. - float probIncrease = 1 - (float)valInt / bits; - int valIntMutated; - if (Random(probIncrease)) - { - valIntMutated = valInt + 1; - } - else - { - valIntMutated = valInt - 1; - } - - // Set value based on mutated thermometer code. - float valMutated = Math.Clamp((float)valIntMutated / bits * (max - min) + min, min, max); - val = valMutated; - } - - private void MutateInt(ref int val, int min, int max, int bits) - { - if (min == max) - { - val = min; - return; - } - - // Starting number of bits that are high, between 0 and bits. - // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. - int valInt = (int)MathF.Round((val - min) / (max - min) * bits); - // val may be outside the range of min/max due to starting prototype values, so clamp. - valInt = Math.Clamp(valInt, 0, bits); - - // Probability that the bit flip increases n. - // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasing it. - // In other words, it tends to go to the middle. - float probIncrease = 1 - (float)valInt / bits; - int valMutated; - if (Random(probIncrease)) - { - valMutated = val + 1; - } - else - { - valMutated = val - 1; - } - - valMutated = Math.Clamp(valMutated, min, max); - val = valMutated; - } - - private bool Random(float odds) - { - var random = IoCManager.Resolve(); - return random.Prob(odds); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - throw new NotImplementedException(); - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustHealth.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustHealth.cs deleted file mode 100644 index 774f6ec48c..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustHealth.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -public sealed partial class PlantAdjustHealth : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-health"; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager)) - return; - - var plantHolder = args.EntityManager.System(); - - plantHolderComp.Health += Amount; - plantHolder.CheckHealth(args.TargetEntity, plantHolderComp); - } -} - diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationLevel.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationLevel.cs deleted file mode 100644 index bf41a21bcb..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationLevel.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Shared.EntityEffects; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -public sealed partial class PlantAdjustMutationLevel : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-mutation-level"; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager)) - return; - - plantHolderComp.MutationLevel += Amount * plantHolderComp.MutationMod; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationMod.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationMod.cs deleted file mode 100644 index 6ed793e614..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationMod.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Content.Shared.EntityEffects; -using JetBrains.Annotations; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -public sealed partial class PlantAdjustMutationMod : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-mutation-mod"; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager)) - return; - - plantHolderComp.MutationMod += Amount; - } -} - diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustNutrition.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustNutrition.cs deleted file mode 100644 index b9389afacd..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustNutrition.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -public sealed partial class PlantAdjustNutrition : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-nutrition"; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager, mustHaveAlivePlant: false)) - return; - - var plantHolder = args.EntityManager.System(); - - plantHolder.AdjustNutrient(args.TargetEntity, Amount, plantHolderComp); - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs deleted file mode 100644 index 219529bfc4..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Content.Shared.EntityEffects; -using JetBrains.Annotations; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -public sealed partial class PlantAdjustPests : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-pests"; - public override bool GuidebookIsAttributePositive { get; protected set; } = false; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager)) - return; - - plantHolderComp.PestLevel += Amount; - } -} - diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPotency.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPotency.cs deleted file mode 100644 index 5776463ce7..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustPotency.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -/// -/// Handles increase or decrease of plant potency. -/// - -public sealed partial class PlantAdjustPotency : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-potency"; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager)) - return; - - if (plantHolderComp.Seed == null) - return; - - var plantHolder = args.EntityManager.System(); - - plantHolder.EnsureUniqueSeed(args.TargetEntity, plantHolderComp); - - plantHolderComp.Seed.Potency = Math.Max(plantHolderComp.Seed.Potency + Amount, 1); - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs deleted file mode 100644 index ab1baa4285..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Content.Shared.EntityEffects; -using JetBrains.Annotations; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -public sealed partial class PlantAdjustToxins : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-toxins"; - public override bool GuidebookIsAttributePositive { get; protected set; } = false; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager)) - return; - - plantHolderComp.Toxins += Amount; - } -} - diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWater.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWater.cs deleted file mode 100644 index 41774977d5..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWater.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -public sealed partial class PlantAdjustWater : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-water"; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager, mustHaveAlivePlant: false)) - return; - - var plantHolder = args.EntityManager.System(); - - plantHolder.AdjustWater(args.TargetEntity, Amount, plantHolderComp); - } -} - diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs deleted file mode 100644 index 421e31998d..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Content.Shared.EntityEffects; -using JetBrains.Annotations; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -public sealed partial class PlantAdjustWeeds : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-weeds"; - public override bool GuidebookIsAttributePositive { get; protected set; } = false; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager)) - return; - - plantHolderComp.WeedLevel += Amount; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAffectGrowth.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAffectGrowth.cs deleted file mode 100644 index 397eace399..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAffectGrowth.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -public sealed partial class PlantAffectGrowth : PlantAdjustAttribute -{ - public override string GuidebookAttributeName { get; set; } = "plant-attribute-growth"; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!CanMetabolize(args.TargetEntity, out var plantHolderComp, args.EntityManager)) - return; - - var plantHolder = args.EntityManager.System(); - - plantHolder.AffectGrowth(args.TargetEntity, (int) Amount, plantHolderComp); - } -} - diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantCryoxadone.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantCryoxadone.cs deleted file mode 100644 index 8a143ea5d5..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantCryoxadone.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -[DataDefinition] -public sealed partial class PlantCryoxadone : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - if (!args.EntityManager.TryGetComponent(args.TargetEntity, out PlantHolderComponent? plantHolderComp) - || plantHolderComp.Seed == null || plantHolderComp.Dead) - return; - - var deviation = 0; - var seed = plantHolderComp.Seed; - var random = IoCManager.Resolve(); - if (plantHolderComp.Age > seed.Maturation) - deviation = (int) Math.Max(seed.Maturation - 1, plantHolderComp.Age - random.Next(7, 10)); - else - deviation = (int) (seed.Maturation / seed.GrowthStages); - plantHolderComp.Age -= deviation; - plantHolderComp.LastProduce = plantHolderComp.Age; - plantHolderComp.SkipAging++; - plantHolderComp.ForceUpdate = true; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-plant-cryoxadone", ("chance", Probability)); -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantDestroySeeds.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantDestroySeeds.cs deleted file mode 100644 index 2929bb6ee9..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantDestroySeeds.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; -using Content.Shared.Popups; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -/// -/// Handles removal of seeds on a plant. -/// - -public sealed partial class PlantDestroySeeds : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - if ( - !args.EntityManager.TryGetComponent(args.TargetEntity, out PlantHolderComponent? plantHolderComp) - || plantHolderComp.Seed == null - || plantHolderComp.Dead - || plantHolderComp.Seed.Immutable - ) - return; - - var plantHolder = args.EntityManager.System(); - var popupSystem = args.EntityManager.System(); - - if (plantHolderComp.Seed.Seedless == false) - { - plantHolder.EnsureUniqueSeed(args.TargetEntity, plantHolderComp); - popupSystem.PopupEntity( - Loc.GetString("botany-plant-seedsdestroyed"), - args.TargetEntity, - PopupType.SmallCaution - ); - plantHolderComp.Seed.Seedless = true; - } - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => - Loc.GetString("reagent-effect-guidebook-plant-seeds-remove", ("chance", Probability)); -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantDiethylamine.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantDiethylamine.cs deleted file mode 100644 index 36b6a83342..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantDiethylamine.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -[DataDefinition] -public sealed partial class PlantDiethylamine : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - if (!args.EntityManager.TryGetComponent(args.TargetEntity, out PlantHolderComponent? plantHolderComp) - || plantHolderComp.Seed == null || plantHolderComp.Dead || - plantHolderComp.Seed.Immutable) - return; - - - var plantHolder = args.EntityManager.System(); - - var random = IoCManager.Resolve(); - - if (random.Prob(0.1f)) - { - plantHolder.EnsureUniqueSeed(args.TargetEntity, plantHolderComp); - plantHolderComp.Seed.Lifespan++; - } - - if (random.Prob(0.1f)) - { - plantHolder.EnsureUniqueSeed(args.TargetEntity, plantHolderComp); - plantHolderComp.Seed.Endurance++; - } - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-plant-diethylamine", ("chance", Probability)); -} - diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantPhalanximine.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantPhalanximine.cs deleted file mode 100644 index 96d98bfbf2..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantPhalanximine.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -[DataDefinition] -public sealed partial class PlantPhalanximine : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - if (!args.EntityManager.TryGetComponent(args.TargetEntity, out PlantHolderComponent? plantHolderComp) - || plantHolderComp.Seed == null || plantHolderComp.Dead || - plantHolderComp.Seed.Immutable) - return; - - plantHolderComp.Seed.Viable = true; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-plant-phalanximine", ("chance", Probability)); -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantRestoreSeeds.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantRestoreSeeds.cs deleted file mode 100644 index 11af8d511f..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantRestoreSeeds.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; -using Content.Shared.Popups; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -/// -/// Handles restoral of seeds on a plant. -/// - -public sealed partial class PlantRestoreSeeds : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - if ( - !args.EntityManager.TryGetComponent(args.TargetEntity, out PlantHolderComponent? plantHolderComp) - || plantHolderComp.Seed == null - || plantHolderComp.Dead - || plantHolderComp.Seed.Immutable - ) - return; - - var plantHolder = args.EntityManager.System(); - var popupSystem = args.EntityManager.System(); - - if (plantHolderComp.Seed.Seedless) - { - plantHolder.EnsureUniqueSeed(args.TargetEntity, plantHolderComp); - popupSystem.PopupEntity(Loc.GetString("botany-plant-seedsrestored"), args.TargetEntity); - plantHolderComp.Seed.Seedless = false; - } - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => - Loc.GetString("reagent-effect-guidebook-plant-seeds-add", ("chance", Probability)); -} diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/RobustHarvest.cs b/Content.Server/EntityEffects/Effects/PlantMetabolism/RobustHarvest.cs deleted file mode 100644 index 695cb96675..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/RobustHarvest.cs +++ /dev/null @@ -1,53 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Server.Botany.Systems; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; - -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; - -[UsedImplicitly] -[DataDefinition] -public sealed partial class RobustHarvest : EntityEffect -{ - [DataField] - public int PotencyLimit = 50; - - [DataField] - public int PotencyIncrease = 3; - - [DataField] - public int PotencySeedlessThreshold = 30; - - public override void Effect(EntityEffectBaseArgs args) - { - if (!args.EntityManager.TryGetComponent(args.TargetEntity, out PlantHolderComponent? plantHolderComp) - || plantHolderComp.Seed == null || plantHolderComp.Dead || - plantHolderComp.Seed.Immutable) - return; - - - var plantHolder = args.EntityManager.System(); - var random = IoCManager.Resolve(); - - if (plantHolderComp.Seed.Potency < PotencyLimit) - { - plantHolder.EnsureUniqueSeed(args.TargetEntity, plantHolderComp); - plantHolderComp.Seed.Potency = Math.Min(plantHolderComp.Seed.Potency + PotencyIncrease, PotencyLimit); - - if (plantHolderComp.Seed.Potency > PotencySeedlessThreshold) - { - plantHolderComp.Seed.Seedless = true; - } - } - else if (plantHolderComp.Seed.Yield > 1 && random.Prob(0.1f)) - { - // Too much of a good thing reduces yield - plantHolder.EnsureUniqueSeed(args.TargetEntity, plantHolderComp); - plantHolderComp.Seed.Yield--; - } - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-plant-robust-harvest", ("seedlesstreshold", PotencySeedlessThreshold), ("limit", PotencyLimit), ("increase", PotencyIncrease), ("chance", Probability)); -} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs b/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs deleted file mode 100644 index 7ee6cd13d7..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Content.Server.Botany; -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Content.Shared.Random; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// changes the chemicals available in a plant's produce -/// -public sealed partial class PlantMutateChemicals : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - var prototypeManager = IoCManager.Resolve(); - var chemicals = plantholder.Seed.Chemicals; - var randomChems = prototypeManager.Index("RandomPickBotanyReagent").Fills; - - // Add a random amount of a random chemical to this set of chemicals - if (randomChems != null) - { - var pick = random.Pick(randomChems); - var chemicalId = random.Pick(pick.Reagents); - var amount = random.Next(1, (int)pick.Quantity); - var seedChemQuantity = new SeedChemQuantity(); - if (chemicals.ContainsKey(chemicalId)) - { - seedChemQuantity.Min = chemicals[chemicalId].Min; - seedChemQuantity.Max = chemicals[chemicalId].Max + amount; - } - else - { - seedChemQuantity.Min = 1; - seedChemQuantity.Max = 1 + amount; - seedChemQuantity.Inherent = false; - } - var potencyDivisor = (int)Math.Ceiling(100.0f / seedChemQuantity.Max); - seedChemQuantity.PotencyDivisor = potencyDivisor; - chemicals[chemicalId] = seedChemQuantity; - } - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs deleted file mode 100644 index 52b9da3a85..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs +++ /dev/null @@ -1,87 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Shared.Atmos; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; -using System.Linq; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// changes the gases that a plant or produce create. -/// -public sealed partial class PlantMutateExudeGasses : EntityEffect -{ - [DataField] - public float MinValue = 0.01f; - - [DataField] - public float MaxValue = 0.5f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - var gasses = plantholder.Seed.ExudeGasses; - - // Add a random amount of a random gas to this gas dictionary - float amount = random.NextFloat(MinValue, MaxValue); - Gas gas = random.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); - if (gasses.ContainsKey(gas)) - { - gasses[gas] += amount; - } - else - { - gasses.Add(gas, amount); - } - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// changes the gases that a plant or produce consumes. -/// -public sealed partial class PlantMutateConsumeGasses : EntityEffect -{ - [DataField] - public float MinValue = 0.01f; - - [DataField] - public float MaxValue = 0.5f; - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - var gasses = plantholder.Seed.ConsumeGasses; - - // Add a random amount of a random gas to this gas dictionary - float amount = random.NextFloat(MinValue, MaxValue); - Gas gas = random.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); - if (gasses.ContainsKey(gas)) - { - gasses[gas] += amount; - } - else - { - gasses.Add(gas, amount); - } - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateHarvest.cs b/Content.Server/EntityEffects/Effects/PlantMutateHarvest.cs deleted file mode 100644 index e67176ee16..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantMutateHarvest.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Content.Server.Botany; -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Upgrades a plant's harvest type. -/// -public sealed partial class PlantMutateHarvest : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - if (plantholder.Seed.HarvestRepeat == HarvestType.NoRepeat) - plantholder.Seed.HarvestRepeat = HarvestType.Repeat; - else if (plantholder.Seed.HarvestRepeat == HarvestType.Repeat) - plantholder.Seed.HarvestRepeat = HarvestType.SelfHarvest; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs b/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs deleted file mode 100644 index 65bd59daa3..0000000000 --- a/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Content.Server.Botany; -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; -using Serilog; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Changes a plant into one of the species its able to mutate into. -/// -public sealed partial class PlantSpeciesChange : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var prototypeManager = IoCManager.Resolve(); - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - if (plantholder.Seed.MutationPrototypes.Count == 0) - return; - - var random = IoCManager.Resolve(); - var targetProto = random.Pick(plantholder.Seed.MutationPrototypes); - prototypeManager.TryIndex(targetProto, out SeedPrototype? protoSeed); - - if (protoSeed == null) - { - Log.Error($"Seed prototype could not be found: {targetProto}!"); - return; - } - - plantholder.Seed = plantholder.Seed.SpeciesChange(protoSeed); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Server/EntityEffects/Effects/ReduceRotting.cs b/Content.Server/EntityEffects/Effects/ReduceRotting.cs deleted file mode 100644 index 5c00492744..0000000000 --- a/Content.Server/EntityEffects/Effects/ReduceRotting.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; -using Content.Server.Atmos.Rotting; - -namespace Content.Server.EntityEffects.Effects -{ - /// - /// Reduces the rotting accumulator on the patient, making them revivable. - /// - [UsedImplicitly] - public sealed partial class ReduceRotting : EntityEffect - { - [DataField("seconds")] - public double RottingAmount = 10; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-reduce-rotting", - ("chance", Probability), - ("time", RottingAmount)); - public override void Effect(EntityEffectBaseArgs args) - { - if (args is EntityEffectReagentArgs reagentArgs) - { - if (reagentArgs.Scale != 1f) - return; - } - - var rottingSys = args.EntityManager.EntitySysManager.GetEntitySystem(); - - rottingSys.ReduceAccumulator(args.TargetEntity, TimeSpan.FromSeconds(RottingAmount)); - } - } -} diff --git a/Content.Server/EntityEffects/Effects/ResetNarcolepsy.cs b/Content.Server/EntityEffects/Effects/ResetNarcolepsy.cs deleted file mode 100644 index f9564712ad..0000000000 --- a/Content.Server/EntityEffects/Effects/ResetNarcolepsy.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Content.Server.Traits.Assorted; -using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Reset narcolepsy timer -/// -[UsedImplicitly] -public sealed partial class ResetNarcolepsy : EntityEffect -{ - /// - /// The # of seconds the effect resets the narcolepsy timer to - /// - [DataField("TimerReset")] - public int TimerReset = 600; - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-reset-narcolepsy", ("chance", Probability)); - - public override void Effect(EntityEffectBaseArgs args) - { - if (args is EntityEffectReagentArgs reagentArgs) - if (reagentArgs.Scale != 1f) - return; - - args.EntityManager.EntitySysManager.GetEntitySystem().AdjustNarcolepsyTimer(args.TargetEntity, TimerReset); - } -} diff --git a/Content.Server/EntityEffects/Effects/SatiateHunger.cs b/Content.Server/EntityEffects/Effects/SatiateHunger.cs deleted file mode 100644 index dd58654dff..0000000000 --- a/Content.Server/EntityEffects/Effects/SatiateHunger.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Content.Server.Nutrition.Components; -using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; -using Content.Shared.Nutrition.Components; -using Content.Shared.Nutrition.EntitySystems; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects -{ - /// - /// Attempts to find a HungerComponent on the target, - /// and to update it's hunger values. - /// - public sealed partial class SatiateHunger : EntityEffect - { - private const float DefaultNutritionFactor = 3.0f; - - /// - /// How much hunger is satiated. - /// Is multiplied by quantity if used with EntityEffectReagentArgs. - /// - [DataField("factor")] public float NutritionFactor { get; set; } = DefaultNutritionFactor; - - //Remove reagent at set rate, satiate hunger if a HungerComponent can be found - public override void Effect(EntityEffectBaseArgs args) - { - var entman = args.EntityManager; - if (!entman.TryGetComponent(args.TargetEntity, out HungerComponent? hunger)) - return; - if (args is EntityEffectReagentArgs reagentArgs) - { - entman.System().ModifyHunger(reagentArgs.TargetEntity, NutritionFactor * (float) reagentArgs.Quantity, hunger); - } - else - { - entman.System().ModifyHunger(args.TargetEntity, NutritionFactor, hunger); - } - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - => Loc.GetString("reagent-effect-guidebook-satiate-hunger", ("chance", Probability), ("relative", NutritionFactor / DefaultNutritionFactor)); - } -} diff --git a/Content.Server/EntityEffects/EntityEffectSystem.cs b/Content.Server/EntityEffects/EntityEffectSystem.cs new file mode 100644 index 0000000000..5d5e81a27f --- /dev/null +++ b/Content.Server/EntityEffects/EntityEffectSystem.cs @@ -0,0 +1,975 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Server.Atmos.Components; +using Content.Server.Atmos.EntitySystems; +using Content.Server.Body.Components; +using Content.Server.Body.Systems; +using Content.Server.Botany.Components; +using Content.Server.Botany.Systems; +using Content.Server.Botany; +using Content.Server.Chat.Systems; +using Content.Server.Emp; +using Content.Server.Explosion.EntitySystems; +using Content.Server.Flash; +using Content.Server.Fluids.EntitySystems; +using Content.Server.Ghost.Roles.Components; +using Content.Server.Medical; +using Content.Server.Polymorph.Components; +using Content.Server.Polymorph.Systems; +using Content.Server.Speech.Components; +using Content.Server.Spreader; +using Content.Server.Temperature.Components; +using Content.Server.Temperature.Systems; +using Content.Server.Traits.Assorted; +using Content.Server.Zombies; +using Content.Shared.Atmos; +using Content.Shared.Audio; +using Content.Shared.Coordinates.Helpers; +using Content.Shared.EntityEffects.EffectConditions; +using Content.Shared.EntityEffects.Effects.PlantMetabolism; +using Content.Shared.EntityEffects.Effects.StatusEffects; +using Content.Shared.EntityEffects.Effects; +using Content.Shared.EntityEffects; +using Content.Shared.Maps; +using Content.Shared.Mind.Components; +using Content.Shared.Popups; +using Content.Shared.Random; +using Content.Shared.Zombies; +using Robust.Server.GameObjects; +using Robust.Shared.Audio; +using Robust.Shared.Audio.Systems; +using Robust.Shared.GameObjects; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +using TemperatureCondition = Content.Shared.EntityEffects.EffectConditions.Temperature; // disambiguate the namespace +using PolymorphEffect = Content.Shared.EntityEffects.Effects.Polymorph; + +namespace Content.Server.EntityEffects; + +public sealed class EntityEffectSystem : EntitySystem +{ + [Dependency] private readonly AtmosphereSystem _atmosphere = default!; + [Dependency] private readonly BloodstreamSystem _bloodstream = default!; + [Dependency] private readonly ChatSystem _chat = default!; + [Dependency] private readonly EmpSystem _emp = default!; + [Dependency] private readonly ExplosionSystem _explosion = default!; + [Dependency] private readonly FlammableSystem _flammable = default!; + [Dependency] private readonly FlashSystem _flash = default!; + [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] private readonly IPrototypeManager _protoManager = default!; + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedMapSystem _map = default!; + [Dependency] private readonly MutationSystem _mutation = default!; + [Dependency] private readonly NarcolepsySystem _narcolepsy = default!; + [Dependency] private readonly PlantHolderSystem _plantHolder = default!; + [Dependency] private readonly PolymorphSystem _polymorph = default!; + [Dependency] private readonly RespiratorSystem _respirator = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPointLightSystem _pointLight = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly SmokeSystem _smoke = default!; + [Dependency] private readonly SpreaderSystem _spreader = default!; + [Dependency] private readonly TemperatureSystem _temperature = default!; + [Dependency] private readonly SharedTransformSystem _xform = default!; + [Dependency] private readonly VomitSystem _vomit = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(OnCheckTemperature); + SubscribeLocalEvent>(OnCheckBreathing); + SubscribeLocalEvent>(OnCheckOrganType); + SubscribeLocalEvent>(OnExecutePlantAdjustHealth); + SubscribeLocalEvent>(OnExecutePlantAdjustMutationLevel); + SubscribeLocalEvent>(OnExecutePlantAdjustMutationMod); + SubscribeLocalEvent>(OnExecutePlantAdjustPests); + SubscribeLocalEvent>(OnExecutePlantAdjustPotency); + SubscribeLocalEvent>(OnExecutePlantAdjustToxins); + SubscribeLocalEvent>(OnExecutePlantAdjustWater); + SubscribeLocalEvent>(OnExecutePlantAdjustWeeds); + SubscribeLocalEvent>(OnExecutePlantAffectGrowth); + SubscribeLocalEvent>(OnExecutePlantChangeStat); + SubscribeLocalEvent>(OnExecutePlantCryoxadone); + SubscribeLocalEvent>(OnExecutePlantDestroySeeds); + SubscribeLocalEvent>(OnExecutePlantDiethylamine); + SubscribeLocalEvent>(OnExecutePlantPhalanximine); + SubscribeLocalEvent>(OnExecutePlantRestoreSeeds); + SubscribeLocalEvent>(OnExecuteAdjustTemperature); + SubscribeLocalEvent>(OnExecuteAreaReactionEffect); + SubscribeLocalEvent>(OnExecuteCauseZombieInfection); + SubscribeLocalEvent>(OnExecuteChemCleanBloodstream); + SubscribeLocalEvent>(OnExecuteChemVomit); + SubscribeLocalEvent>(OnExecuteCreateEntityReactionEffect); + SubscribeLocalEvent>(OnExecuteCreateGas); + SubscribeLocalEvent>(OnExecuteCureZombieInfection); + SubscribeLocalEvent>(OnExecuteEmote); + SubscribeLocalEvent>(OnExecuteEmpReactionEffect); + SubscribeLocalEvent>(OnExecuteExplosionReactionEffect); + SubscribeLocalEvent>(OnExecuteFlammableReaction); + SubscribeLocalEvent>(OnExecuteFlashReactionEffect); + SubscribeLocalEvent>(OnExecuteIgnite); + SubscribeLocalEvent>(OnExecuteMakeSentient); + SubscribeLocalEvent>(OnExecuteModifyBleedAmount); + SubscribeLocalEvent>(OnExecuteModifyBloodLevel); + SubscribeLocalEvent>(OnExecuteModifyLungGas); + SubscribeLocalEvent>(OnExecuteOxygenate); + SubscribeLocalEvent>(OnExecutePlantMutateChemicals); + SubscribeLocalEvent>(OnExecutePlantMutateConsumeGasses); + SubscribeLocalEvent>(OnExecutePlantMutateExudeGasses); + SubscribeLocalEvent>(OnExecutePlantMutateHarvest); + SubscribeLocalEvent>(OnExecutePlantSpeciesChange); + SubscribeLocalEvent>(OnExecutePolymorph); + SubscribeLocalEvent>(OnExecuteResetNarcolepsy); + } + + private void OnCheckTemperature(ref CheckEntityEffectConditionEvent args) + { + args.Result = false; + if (TryComp(args.Args.TargetEntity, out TemperatureComponent? temp)) + { + if (temp.CurrentTemperature > args.Condition.Min && temp.CurrentTemperature < args.Condition.Max) + args.Result = true; + } + } + + private void OnCheckBreathing(ref CheckEntityEffectConditionEvent args) + { + if (!TryComp(args.Args.TargetEntity, out RespiratorComponent? respiratorComp)) + { + args.Result = !args.Condition.IsBreathing; + return; + } + + var breathingState = _respirator.IsBreathing((args.Args.TargetEntity, respiratorComp)); + args.Result = args.Condition.IsBreathing == breathingState; + } + + private void OnCheckOrganType(ref CheckEntityEffectConditionEvent args) + { + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + if (reagentArgs.OrganEntity == null) + { + args.Result = false; + return; + } + + args.Result = OrganCondition(args.Condition, reagentArgs.OrganEntity.Value); + return; + } + + // TODO: Someone needs to figure out how to do this for non-reagent effects. + throw new NotImplementedException(); + } + + public bool OrganCondition(OrganType condition, Entity metabolizer) + { + metabolizer.Comp ??= EntityManager.GetComponentOrNull(metabolizer.Owner); + if (metabolizer.Comp != null + && metabolizer.Comp.MetabolizerTypes != null + && metabolizer.Comp.MetabolizerTypes.Contains(condition.Type)) + return condition.ShouldHave; + return !condition.ShouldHave; + } + + /// + /// Checks if the plant holder can metabolize the reagent or not. Checks if it has an alive plant by default. + /// + /// The entity holding the plant + /// The plant holder component + /// The entity manager + /// Whether to check if it has an alive plant or not + /// + private bool CanMetabolizePlant(EntityUid plantHolder, [NotNullWhen(true)] out PlantHolderComponent? plantHolderComponent, + bool mustHaveAlivePlant = true, bool mustHaveMutableSeed = false) + { + plantHolderComponent = null; + + if (!TryComp(plantHolder, out plantHolderComponent)) + return false; + + if (mustHaveAlivePlant && (plantHolderComponent.Seed == null || plantHolderComponent.Dead)) + return false; + + if (mustHaveMutableSeed && (plantHolderComponent.Seed == null || plantHolderComponent.Seed.Immutable)) + return false; + + return true; + } + + private void OnExecutePlantAdjustHealth(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + plantHolderComp.Health += args.Effect.Amount; + _plantHolder.CheckHealth(args.Args.TargetEntity, plantHolderComp); + } + + private void OnExecutePlantAdjustMutationLevel(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + plantHolderComp.MutationLevel += args.Effect.Amount * plantHolderComp.MutationMod; + } + + private void OnExecutePlantAdjustMutationMod(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + plantHolderComp.MutationMod += args.Effect.Amount; + } + + private void OnExecutePlantAdjustNutrition(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp, mustHaveAlivePlant: false)) + return; + + _plantHolder.AdjustNutrient(args.Args.TargetEntity, args.Effect.Amount, plantHolderComp); + } + + private void OnExecutePlantAdjustPests(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + plantHolderComp.PestLevel += args.Effect.Amount; + } + + private void OnExecutePlantAdjustPotency(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + if (plantHolderComp.Seed == null) + return; + + _plantHolder.EnsureUniqueSeed(args.Args.TargetEntity, plantHolderComp); + plantHolderComp.Seed.Potency = Math.Max(plantHolderComp.Seed.Potency + args.Effect.Amount, 1); + } + + private void OnExecutePlantAdjustToxins(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + plantHolderComp.Toxins += args.Effect.Amount; + } + + private void OnExecutePlantAdjustWater(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp, mustHaveAlivePlant: false)) + return; + + _plantHolder.AdjustWater(args.Args.TargetEntity, args.Effect.Amount, plantHolderComp); + } + + private void OnExecutePlantAdjustWeeds(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + plantHolderComp.WeedLevel += args.Effect.Amount; + } + + private void OnExecutePlantAffectGrowth(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + _plantHolder.AffectGrowth(args.Args.TargetEntity, (int) args.Effect.Amount, plantHolderComp); + } + + // Mutate reference 'val' between 'min' and 'max' by pretending the value + // is representable by a thermometer code with 'bits' number of bits and + // randomly flipping some of them. + private void MutateFloat(ref float val, float min, float max, int bits) + { + if (min == max) + { + val = min; + return; + } + + // Starting number of bits that are high, between 0 and bits. + // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. + int valInt = (int)MathF.Round((val - min) / (max - min) * bits); + // val may be outside the range of min/max due to starting prototype values, so clamp. + valInt = Math.Clamp(valInt, 0, bits); + + // Probability that the bit flip increases n. + // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasive it it. + // In other words, it tends to go to the middle. + float probIncrease = 1 - (float)valInt / bits; + int valIntMutated; + if (_random.Prob(probIncrease)) + { + valIntMutated = valInt + 1; + } + else + { + valIntMutated = valInt - 1; + } + + // Set value based on mutated thermometer code. + float valMutated = Math.Clamp((float)valIntMutated / bits * (max - min) + min, min, max); + val = valMutated; + } + + private void MutateInt(ref int val, int min, int max, int bits) + { + if (min == max) + { + val = min; + return; + } + + // Starting number of bits that are high, between 0 and bits. + // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. + int valInt = (int)MathF.Round((val - min) / (max - min) * bits); + // val may be outside the range of min/max due to starting prototype values, so clamp. + valInt = Math.Clamp(valInt, 0, bits); + + // Probability that the bit flip increases n. + // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasing it. + // In other words, it tends to go to the middle. + float probIncrease = 1 - (float)valInt / bits; + int valMutated; + if (_random.Prob(probIncrease)) + { + valMutated = val + 1; + } + else + { + valMutated = val - 1; + } + + valMutated = Math.Clamp(valMutated, min, max); + val = valMutated; + } + + private void OnExecutePlantChangeStat(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + if (plantHolderComp.Seed == null) + return; + + var member = plantHolderComp.Seed.GetType().GetField(args.Effect.TargetValue); + + if (member == null) + { + _mutation.Log.Error(args.Effect.GetType().Name + " Error: Member " + args.Effect.TargetValue + " not found on " + plantHolderComp.Seed.GetType().Name + ". Did you misspell it?"); + return; + } + + var currentValObj = member.GetValue(plantHolderComp.Seed); + if (currentValObj == null) + return; + + if (member.FieldType == typeof(float)) + { + var floatVal = (float)currentValObj; + MutateFloat(ref floatVal, args.Effect.MinValue, args.Effect.MaxValue, args.Effect.Steps); + member.SetValue(plantHolderComp.Seed, floatVal); + } + else if (member.FieldType == typeof(int)) + { + var intVal = (int)currentValObj; + MutateInt(ref intVal, (int)args.Effect.MinValue, (int)args.Effect.MaxValue, args.Effect.Steps); + member.SetValue(plantHolderComp.Seed, intVal); + } + else if (member.FieldType == typeof(bool)) + { + var boolVal = (bool)currentValObj; + boolVal = !boolVal; + member.SetValue(plantHolderComp.Seed, boolVal); + } + } + + private void OnExecutePlantCryoxadone(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + var deviation = 0; + var seed = plantHolderComp.Seed; + if (seed == null) + return; + if (plantHolderComp.Age > seed.Maturation) + deviation = (int) Math.Max(seed.Maturation - 1, plantHolderComp.Age - _random.Next(7, 10)); + else + deviation = (int) (seed.Maturation / seed.GrowthStages); + plantHolderComp.Age -= deviation; + plantHolderComp.LastProduce = plantHolderComp.Age; + plantHolderComp.SkipAging++; + plantHolderComp.ForceUpdate = true; + } + + private void OnExecutePlantDestroySeeds(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp, mustHaveMutableSeed: true)) + return; + + if (plantHolderComp.Seed!.Seedless == false) + { + _plantHolder.EnsureUniqueSeed(args.Args.TargetEntity, plantHolderComp); + _popup.PopupEntity( + Loc.GetString("botany-plant-seedsdestroyed"), + args.Args.TargetEntity, + PopupType.SmallCaution + ); + plantHolderComp.Seed.Seedless = true; + } + } + + private void OnExecutePlantDiethylamine(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp, mustHaveMutableSeed: true)) + return; + + if (_random.Prob(0.1f)) + { + _plantHolder.EnsureUniqueSeed(args.Args.TargetEntity, plantHolderComp); + plantHolderComp.Seed!.Lifespan++; + } + + if (_random.Prob(0.1f)) + { + _plantHolder.EnsureUniqueSeed(args.Args.TargetEntity, plantHolderComp); + plantHolderComp.Seed!.Endurance++; + } + } + + private void OnExecutePlantPhalanximine(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp, mustHaveMutableSeed: true)) + return; + + plantHolderComp.Seed!.Viable = true; + } + + private void OnExecutePlantRestoreSeeds(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp, mustHaveMutableSeed: true)) + return; + + if (plantHolderComp.Seed!.Seedless) + { + _plantHolder.EnsureUniqueSeed(args.Args.TargetEntity, plantHolderComp); + _popup.PopupEntity(Loc.GetString("botany-plant-seedsrestored"), args.Args.TargetEntity); + plantHolderComp.Seed.Seedless = false; + } + } + + private void OnExecuteRobustHarvest(ref ExecuteEntityEffectEvent args) + { + if (!CanMetabolizePlant(args.Args.TargetEntity, out var plantHolderComp)) + return; + + if (plantHolderComp.Seed == null) + return; + + if (plantHolderComp.Seed.Potency < args.Effect.PotencyLimit) + { + _plantHolder.EnsureUniqueSeed(args.Args.TargetEntity, plantHolderComp); + plantHolderComp.Seed.Potency = Math.Min(plantHolderComp.Seed.Potency + args.Effect.PotencyIncrease, args.Effect.PotencyLimit); + + if (plantHolderComp.Seed.Potency > args.Effect.PotencySeedlessThreshold) + { + plantHolderComp.Seed.Seedless = true; + } + } + else if (plantHolderComp.Seed.Yield > 1 && _random.Prob(0.1f)) + { + // Too much of a good thing reduces yield + _plantHolder.EnsureUniqueSeed(args.Args.TargetEntity, plantHolderComp); + plantHolderComp.Seed.Yield--; + } + } + + private void OnExecuteAdjustTemperature(ref ExecuteEntityEffectEvent args) + { + if (TryComp(args.Args.TargetEntity, out TemperatureComponent? temp)) + { + var amount = args.Effect.Amount; + + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + amount *= reagentArgs.Scale.Float(); + } + + _temperature.ChangeHeat(args.Args.TargetEntity, amount, true, temp); + } + } + + private void OnExecuteAreaReactionEffect(ref ExecuteEntityEffectEvent args) + { + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + if (reagentArgs.Source == null) + return; + + var spreadAmount = (int) Math.Max(0, Math.Ceiling((reagentArgs.Quantity / args.Effect.OverflowThreshold).Float())); + var splitSolution = reagentArgs.Source.SplitSolution(reagentArgs.Source.Volume); + var transform = EntityManager.GetComponent(reagentArgs.TargetEntity); + var mapCoords = _xform.GetMapCoordinates(reagentArgs.TargetEntity, xform: transform); + + if (!_mapManager.TryFindGridAt(mapCoords, out var gridUid, out var grid) || + !_map.TryGetTileRef(gridUid, grid, transform.Coordinates, out var tileRef)) + { + return; + } + + if (_spreader.RequiresFloorToSpread(args.Effect.PrototypeId) && tileRef.Tile.IsSpace()) + return; + + var coords = _map.MapToGrid(gridUid, mapCoords); + var ent = EntityManager.SpawnEntity(args.Effect.PrototypeId, coords.SnapToGrid()); + + _smoke.StartSmoke(ent, splitSolution, args.Effect.Duration, spreadAmount); + + _audio.PlayPvs(args.Effect.Sound, reagentArgs.TargetEntity, AudioParams.Default.WithVariation(0.25f)); + return; + } + + // TODO: Someone needs to figure out how to do this for non-reagent effects. + throw new NotImplementedException(); + } + + private void OnExecuteCauseZombieInfection(ref ExecuteEntityEffectEvent args) + { + EnsureComp(args.Args.TargetEntity); + EnsureComp(args.Args.TargetEntity); + } + + private void OnExecuteChemCleanBloodstream(ref ExecuteEntityEffectEvent args) + { + var cleanseRate = args.Effect.CleanseRate; + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + if (reagentArgs.Source == null || reagentArgs.Reagent == null) + return; + + cleanseRate *= reagentArgs.Scale.Float(); + _bloodstream.FlushChemicals(args.Args.TargetEntity, reagentArgs.Reagent.ID, cleanseRate); + } + else + { + _bloodstream.FlushChemicals(args.Args.TargetEntity, "", cleanseRate); + } + } + + private void OnExecuteChemVomit(ref ExecuteEntityEffectEvent args) + { + if (args.Args is EntityEffectReagentArgs reagentArgs) + if (reagentArgs.Scale != 1f) + return; + + _vomit.Vomit(args.Args.TargetEntity, args.Effect.ThirstAmount, args.Effect.HungerAmount); + } + + private void OnExecuteCreateEntityReactionEffect(ref ExecuteEntityEffectEvent args) + { + var transform = Comp(args.Args.TargetEntity); + var quantity = (int)args.Effect.Number; + if (args.Args is EntityEffectReagentArgs reagentArgs) + quantity *= reagentArgs.Quantity.Int(); + + for (var i = 0; i < quantity; i++) + { + var uid = Spawn(args.Effect.Entity, _xform.GetMapCoordinates(args.Args.TargetEntity, xform: transform)); + _xform.AttachToGridOrMap(uid); + + // TODO figure out how to properly spawn inside of containers + // e.g. cheese: + // if the user is holding a bowl milk & enzyme, should drop to floor, not attached to the user. + // if reaction happens in a backpack, should insert cheese into backpack. + // --> if it doesn't fit, iterate through parent storage until it attaches to the grid (again, DON'T attach to players). + // if the reaction happens INSIDE a stomach? the bloodstream? I have no idea how to handle that. + // presumably having cheese materialize inside of your blood would have "disadvantages". + } + } + + private void OnExecuteCreateGas(ref ExecuteEntityEffectEvent args) + { + var tileMix = _atmosphere.GetContainingMixture(args.Args.TargetEntity, false, true); + + if (tileMix != null) + { + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + tileMix.AdjustMoles(args.Effect.Gas, reagentArgs.Quantity.Float() * args.Effect.Multiplier); + } + else + { + tileMix.AdjustMoles(args.Effect.Gas, args.Effect.Multiplier); + } + } + } + + private void OnExecuteCureZombieInfection(ref ExecuteEntityEffectEvent args) + { + if (HasComp(args.Args.TargetEntity)) + return; + + RemComp(args.Args.TargetEntity); + RemComp(args.Args.TargetEntity); + + if (args.Effect.Innoculate) + { + EnsureComp(args.Args.TargetEntity); + } + } + + private void OnExecuteEmote(ref ExecuteEntityEffectEvent args) + { + if (args.Effect.EmoteId == null) + return; + + if (args.Effect.ShowInChat) + _chat.TryEmoteWithChat(args.Args.TargetEntity, args.Effect.EmoteId, ChatTransmitRange.GhostRangeLimit, forceEmote: args.Effect.Force); + else + _chat.TryEmoteWithoutChat(args.Args.TargetEntity, args.Effect.EmoteId); + } + + private void OnExecuteEmpReactionEffect(ref ExecuteEntityEffectEvent args) + { + var transform = EntityManager.GetComponent(args.Args.TargetEntity); + + var range = args.Effect.EmpRangePerUnit; + + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + range = MathF.Min((float) (reagentArgs.Quantity * args.Effect.EmpRangePerUnit), args.Effect.EmpMaxRange); + } + + _emp.EmpPulse(_xform.GetMapCoordinates(args.Args.TargetEntity, xform: transform), + range, + args.Effect.EnergyConsumption, + args.Effect.DisableDuration); + } + + private void OnExecuteExplosionReactionEffect(ref ExecuteEntityEffectEvent args) + { + var intensity = args.Effect.IntensityPerUnit; + + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + intensity = MathF.Min((float) reagentArgs.Quantity * args.Effect.IntensityPerUnit, args.Effect.MaxTotalIntensity); + } + + _explosion.QueueExplosion( + args.Args.TargetEntity, + args.Effect.ExplosionType, + intensity, + args.Effect.IntensitySlope, + args.Effect.MaxIntensity, + args.Effect.TileBreakScale); + } + + private void OnExecuteFlammableReaction(ref ExecuteEntityEffectEvent args) + { + if (!TryComp(args.Args.TargetEntity, out FlammableComponent? flammable)) + return; + + // Sets the multiplier for FireStacks to MultiplierOnExisting is 0 or greater and target already has FireStacks + var multiplier = flammable.FireStacks != 0f && args.Effect.MultiplierOnExisting >= 0 ? args.Effect.MultiplierOnExisting : args.Effect.Multiplier; + var quantity = 1f; + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + quantity = reagentArgs.Quantity.Float(); + _flammable.AdjustFireStacks(args.Args.TargetEntity, quantity * multiplier, flammable); + if (reagentArgs.Reagent != null) + reagentArgs.Source?.RemoveReagent(reagentArgs.Reagent.ID, reagentArgs.Quantity); + } + else + { + _flammable.AdjustFireStacks(args.Args.TargetEntity, multiplier, flammable); + } + } + + private void OnExecuteFlashReactionEffect(ref ExecuteEntityEffectEvent args) + { + var transform = EntityManager.GetComponent(args.Args.TargetEntity); + + var range = 1f; + + if (args.Args is EntityEffectReagentArgs reagentArgs) + range = MathF.Min((float)(reagentArgs.Quantity * args.Effect.RangePerUnit), args.Effect.MaxRange); + + _flash.FlashArea( + args.Args.TargetEntity, + null, + range, + args.Effect.Duration * 1000, + slowTo: args.Effect.SlowTo, + sound: args.Effect.Sound); + + if (args.Effect.FlashEffectPrototype == null) + return; + + var uid = EntityManager.SpawnEntity(args.Effect.FlashEffectPrototype, _xform.GetMapCoordinates(transform)); + _xform.AttachToGridOrMap(uid); + + if (!TryComp(uid, out var pointLightComp)) + return; + + _pointLight.SetRadius(uid, MathF.Max(1.1f, range), pointLightComp); + } + + private void OnExecuteIgnite(ref ExecuteEntityEffectEvent args) + { + if (!TryComp(args.Args.TargetEntity, out FlammableComponent? flammable)) + return; + + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + _flammable.Ignite(reagentArgs.TargetEntity, reagentArgs.OrganEntity ?? reagentArgs.TargetEntity, flammable: flammable); + } + else + { + _flammable.Ignite(args.Args.TargetEntity, args.Args.TargetEntity, flammable: flammable); + } + } + + private void OnExecuteMakeSentient(ref ExecuteEntityEffectEvent args) + { + var uid = args.Args.TargetEntity; + + // Let affected entities speak normally to make this effect different from, say, the "random sentience" event + // This also works on entities that already have a mind + // We call this before the mind check to allow things like player-controlled mice to be able to benefit from the effect + RemComp(uid); + RemComp(uid); + + // Stops from adding a ghost role to things like people who already have a mind + if (TryComp(uid, out var mindContainer) && mindContainer.HasMind) + { + return; + } + + // Don't add a ghost role to things that already have ghost roles + if (TryComp(uid, out GhostRoleComponent? ghostRole)) + { + return; + } + + ghostRole = AddComp(uid); + EnsureComp(uid); + + var entityData = EntityManager.GetComponent(uid); + ghostRole.RoleName = entityData.EntityName; + ghostRole.RoleDescription = Loc.GetString("ghost-role-information-cognizine-description"); + } + + private void OnExecuteModifyBleedAmount(ref ExecuteEntityEffectEvent args) + { + if (TryComp(args.Args.TargetEntity, out var blood)) + { + var amt = args.Effect.Amount; + if (args.Args is EntityEffectReagentArgs reagentArgs) { + if (args.Effect.Scaled) + amt *= reagentArgs.Quantity.Float(); + amt *= reagentArgs.Scale.Float(); + } + + _bloodstream.TryModifyBleedAmount(args.Args.TargetEntity, amt, blood); + } + } + + private void OnExecuteModifyBloodLevel(ref ExecuteEntityEffectEvent args) + { + if (TryComp(args.Args.TargetEntity, out var blood)) + { + var amt = args.Effect.Amount; + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + if (args.Effect.Scaled) + amt *= reagentArgs.Quantity; + amt *= reagentArgs.Scale; + } + + _bloodstream.TryModifyBloodLevel(args.Args.TargetEntity, amt, blood); + } + } + + private void OnExecuteModifyLungGas(ref ExecuteEntityEffectEvent args) + { + LungComponent? lung; + float amount = 1f; + + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + if (!TryComp(reagentArgs.OrganEntity, out var organLung)) + return; + lung = organLung; + amount = reagentArgs.Quantity.Float(); + } + else + { + if (!TryComp(args.Args.TargetEntity, out var organLung)) //Likely needs to be modified to ensure it works correctly + return; + lung = organLung; + } + + if (lung != null) + { + foreach (var (gas, ratio) in args.Effect.Ratios) + { + var quantity = ratio * amount / Atmospherics.BreathMolesToReagentMultiplier; + if (quantity < 0) + quantity = Math.Max(quantity, -lung.Air[(int) gas]); + lung.Air.AdjustMoles(gas, quantity); + } + } + } + + private void OnExecuteOxygenate(ref ExecuteEntityEffectEvent args) + { + var multiplier = 1f; + if (args.Args is EntityEffectReagentArgs reagentArgs) + { + multiplier = reagentArgs.Quantity.Float(); + } + + if (TryComp(args.Args.TargetEntity, out var resp)) + { + _respirator.UpdateSaturation(args.Args.TargetEntity, multiplier * args.Effect.Factor, resp); + } + } + + private void OnExecutePlantMutateChemicals(ref ExecuteEntityEffectEvent args) + { + var plantholder = EntityManager.GetComponent(args.Args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var chemicals = plantholder.Seed.Chemicals; + var randomChems = _protoManager.Index("RandomPickBotanyReagent").Fills; + + // Add a random amount of a random chemical to this set of chemicals + if (randomChems != null) + { + var pick = _random.Pick(randomChems); + var chemicalId = _random.Pick(pick.Reagents); + var amount = _random.Next(1, (int)pick.Quantity); + var seedChemQuantity = new SeedChemQuantity(); + if (chemicals.ContainsKey(chemicalId)) + { + seedChemQuantity.Min = chemicals[chemicalId].Min; + seedChemQuantity.Max = chemicals[chemicalId].Max + amount; + } + else + { + seedChemQuantity.Min = 1; + seedChemQuantity.Max = 1 + amount; + seedChemQuantity.Inherent = false; + } + var potencyDivisor = (int)Math.Ceiling(100.0f / seedChemQuantity.Max); + seedChemQuantity.PotencyDivisor = potencyDivisor; + chemicals[chemicalId] = seedChemQuantity; + } + } + + private void OnExecutePlantMutateConsumeGasses(ref ExecuteEntityEffectEvent args) + { + var plantholder = EntityManager.GetComponent(args.Args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var gasses = plantholder.Seed.ExudeGasses; + + // Add a random amount of a random gas to this gas dictionary + float amount = _random.NextFloat(args.Effect.MinValue, args.Effect.MaxValue); + Gas gas = _random.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); + if (gasses.ContainsKey(gas)) + { + gasses[gas] += amount; + } + else + { + gasses.Add(gas, amount); + } + } + + private void OnExecutePlantMutateExudeGasses(ref ExecuteEntityEffectEvent args) + { + var plantholder = EntityManager.GetComponent(args.Args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var gasses = plantholder.Seed.ConsumeGasses; + + // Add a random amount of a random gas to this gas dictionary + float amount = _random.NextFloat(args.Effect.MinValue, args.Effect.MaxValue); + Gas gas = _random.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); + if (gasses.ContainsKey(gas)) + { + gasses[gas] += amount; + } + else + { + gasses.Add(gas, amount); + } + } + + private void OnExecutePlantMutateHarvest(ref ExecuteEntityEffectEvent args) + { + var plantholder = EntityManager.GetComponent(args.Args.TargetEntity); + + if (plantholder.Seed == null) + return; + + if (plantholder.Seed.HarvestRepeat == HarvestType.NoRepeat) + plantholder.Seed.HarvestRepeat = HarvestType.Repeat; + else if (plantholder.Seed.HarvestRepeat == HarvestType.Repeat) + plantholder.Seed.HarvestRepeat = HarvestType.SelfHarvest; + } + + private void OnExecutePlantSpeciesChange(ref ExecuteEntityEffectEvent args) + { + var plantholder = EntityManager.GetComponent(args.Args.TargetEntity); + if (plantholder.Seed == null) + return; + + if (plantholder.Seed.MutationPrototypes.Count == 0) + return; + + var targetProto = _random.Pick(plantholder.Seed.MutationPrototypes); + _protoManager.TryIndex(targetProto, out SeedPrototype? protoSeed); + + if (protoSeed == null) + { + Log.Error($"Seed prototype could not be found: {targetProto}!"); + return; + } + + plantholder.Seed = plantholder.Seed.SpeciesChange(protoSeed); + } + + private void OnExecutePolymorph(ref ExecuteEntityEffectEvent args) + { + // Make it into a prototype + EnsureComp(args.Args.TargetEntity); + _polymorph.PolymorphEntity(args.Args.TargetEntity, args.Effect.PolymorphPrototype); + } + + private void OnExecuteResetNarcolepsy(ref ExecuteEntityEffectEvent args) + { + if (args.Args is EntityEffectReagentArgs reagentArgs) + if (reagentArgs.Scale != 1f) + return; + + _narcolepsy.AdjustNarcolepsyTimer(args.Args.TargetEntity, args.Effect.TimerReset); + } +} diff --git a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs index bdbc265164..dfbad1bbe9 100644 --- a/Content.Server/Fluids/EntitySystems/SmokeSystem.cs +++ b/Content.Server/Fluids/EntitySystems/SmokeSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Administration.Logs; using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.EntityEffects.Effects; +using Content.Shared.EntityEffects.Effects; using Content.Server.Spreader; using Content.Shared.Chemistry; using Content.Shared.Chemistry.Components; diff --git a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs index f11a2c9041..7ac5c20a7d 100644 --- a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs @@ -1,6 +1,6 @@ using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.EntityEffects.Effects; +using Content.Shared.EntityEffects.Effects; using Content.Server.Fluids.EntitySystems; using Content.Server.Forensics; using Content.Server.Inventory; diff --git a/Content.Shared/Chemistry/Reaction/ReactionPrototype.cs b/Content.Shared/Chemistry/Reaction/ReactionPrototype.cs index 92559e4874..4bbb972572 100644 --- a/Content.Shared/Chemistry/Reaction/ReactionPrototype.cs +++ b/Content.Shared/Chemistry/Reaction/ReactionPrototype.cs @@ -60,7 +60,7 @@ namespace Content.Shared.Chemistry.Reaction /// /// Effects to be triggered when the reaction occurs. /// - [DataField("effects", serverOnly: true)] public List Effects = new(); + [DataField("effects")] public List Effects = new(); /// /// How dangerous is this effect? Stuff like bicaridine should be low, while things like methamphetamine diff --git a/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs b/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs index 2250347a47..1a3d17c340 100644 --- a/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs +++ b/Content.Shared/Chemistry/Reagent/ReagentPrototype.cs @@ -145,16 +145,16 @@ namespace Content.Shared.Chemistry.Reagent [DataField] public bool WorksOnTheDead; - [DataField(serverOnly: true)] + [DataField] public FrozenDictionary, ReagentEffectsEntry>? Metabolisms; - [DataField(serverOnly: true)] + [DataField] public Dictionary, ReactiveReagentEffectEntry>? ReactiveEffects; [DataField(serverOnly: true)] public List TileReactions = new(0); - [DataField("plantMetabolism", serverOnly: true)] + [DataField("plantMetabolism")] public List PlantMetabolisms = new(0); [DataField] diff --git a/Content.Server/EntityEffects/EffectConditions/BodyTemperature.cs b/Content.Shared/EntityEffects/EffectConditions/BodyTemperature.cs similarity index 52% rename from Content.Server/EntityEffects/EffectConditions/BodyTemperature.cs rename to Content.Shared/EntityEffects/EffectConditions/BodyTemperature.cs index 9f68bec918..351e4ee12c 100644 --- a/Content.Server/EntityEffects/EffectConditions/BodyTemperature.cs +++ b/Content.Shared/EntityEffects/EffectConditions/BodyTemperature.cs @@ -1,30 +1,18 @@ -using Content.Server.Temperature.Components; -using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.EffectConditions; +namespace Content.Shared.EntityEffects.EffectConditions; /// /// Requires the target entity to be above or below a certain temperature. /// Used for things like cryoxadone and pyroxadone. /// -public sealed partial class Temperature : EntityEffectCondition +public sealed partial class Temperature : EventEntityEffectCondition { [DataField] public float Min = 0; [DataField] public float Max = float.PositiveInfinity; - public override bool Condition(EntityEffectBaseArgs args) - { - if (args.EntityManager.TryGetComponent(args.TargetEntity, out TemperatureComponent? temp)) - { - if (temp.CurrentTemperature > Min && temp.CurrentTemperature < Max) - return true; - } - - return false; - } public override string GuidebookExplanation(IPrototypeManager prototype) { diff --git a/Content.Shared/EntityEffects/EffectConditions/BreathingCondition.cs b/Content.Shared/EntityEffects/EffectConditions/BreathingCondition.cs new file mode 100644 index 0000000000..9de1bfdbf6 --- /dev/null +++ b/Content.Shared/EntityEffects/EffectConditions/BreathingCondition.cs @@ -0,0 +1,21 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.EffectConditions; + +/// +/// Condition for if the entity is successfully breathing. +/// +public sealed partial class Breathing : EventEntityEffectCondition +{ + /// + /// If true, the entity must not have trouble breathing to pass. + /// + [DataField] + public bool IsBreathing = true; + + public override string GuidebookExplanation(IPrototypeManager prototype) + { + return Loc.GetString("reagent-effect-condition-guidebook-breathing", + ("isBreathing", IsBreathing)); + } +} diff --git a/Content.Server/EntityEffects/EffectConditions/HasTagCondition.cs b/Content.Shared/EntityEffects/EffectConditions/HasTagCondition.cs similarity index 86% rename from Content.Server/EntityEffects/EffectConditions/HasTagCondition.cs rename to Content.Shared/EntityEffects/EffectConditions/HasTagCondition.cs index b0428b41bf..379a248027 100644 --- a/Content.Server/EntityEffects/EffectConditions/HasTagCondition.cs +++ b/Content.Shared/EntityEffects/EffectConditions/HasTagCondition.cs @@ -1,12 +1,9 @@ -using Content.Shared.EntityEffects; using Content.Shared.Tag; -using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.EntityEffects.EffectConditions; +namespace Content.Shared.EntityEffects.EffectConditions; -[UsedImplicitly] public sealed partial class HasTag : EntityEffectCondition { [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] diff --git a/Content.Server/EntityEffects/EffectConditions/InternalsCondition.cs b/Content.Shared/EntityEffects/EffectConditions/InternalsCondition.cs similarity index 100% rename from Content.Server/EntityEffects/EffectConditions/InternalsCondition.cs rename to Content.Shared/EntityEffects/EffectConditions/InternalsCondition.cs diff --git a/Content.Server/EntityEffects/EffectConditions/JobCondition.cs b/Content.Shared/EntityEffects/EffectConditions/JobCondition.cs similarity index 95% rename from Content.Server/EntityEffects/EffectConditions/JobCondition.cs rename to Content.Shared/EntityEffects/EffectConditions/JobCondition.cs index 9621d6945f..7fec087d6b 100644 --- a/Content.Server/EntityEffects/EffectConditions/JobCondition.cs +++ b/Content.Shared/EntityEffects/EffectConditions/JobCondition.cs @@ -1,5 +1,4 @@ using System.Linq; -using Content.Shared.EntityEffects; using Content.Shared.Localizations; using Content.Shared.Mind; using Content.Shared.Mind.Components; @@ -7,7 +6,7 @@ using Content.Shared.Roles; using Content.Shared.Roles.Jobs; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.EffectConditions; +namespace Content.Shared.EntityEffects.EffectConditions; public sealed partial class JobCondition : EntityEffectCondition { diff --git a/Content.Server/EntityEffects/EffectConditions/MobStateCondition.cs b/Content.Shared/EntityEffects/EffectConditions/MobStateCondition.cs similarity index 88% rename from Content.Server/EntityEffects/EffectConditions/MobStateCondition.cs rename to Content.Shared/EntityEffects/EffectConditions/MobStateCondition.cs index d676b29bf9..efe7246b2a 100644 --- a/Content.Server/EntityEffects/EffectConditions/MobStateCondition.cs +++ b/Content.Shared/EntityEffects/EffectConditions/MobStateCondition.cs @@ -1,9 +1,8 @@ -using Content.Shared.EntityEffects; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.EffectConditions; +namespace Content.Shared.EntityEffects.EffectConditions; public sealed partial class MobStateCondition : EntityEffectCondition { diff --git a/Content.Shared/EntityEffects/EffectConditions/OrganType.cs b/Content.Shared/EntityEffects/EffectConditions/OrganType.cs new file mode 100644 index 0000000000..f99eb5cc77 --- /dev/null +++ b/Content.Shared/EntityEffects/EffectConditions/OrganType.cs @@ -0,0 +1,28 @@ +// using Content.Server.Body.Components; +using Content.Shared.Body.Prototypes; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.EntityEffects.EffectConditions; + +/// +/// Requires that the metabolizing organ is or is not tagged with a certain MetabolizerType +/// +public sealed partial class OrganType : EventEntityEffectCondition +{ + [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + public string Type = default!; + + /// + /// Does this condition pass when the organ has the type, or when it doesn't have the type? + /// + [DataField] + public bool ShouldHave = true; + + public override string GuidebookExplanation(IPrototypeManager prototype) + { + return Loc.GetString("reagent-effect-condition-guidebook-organ-type", + ("name", prototype.Index(Type).LocalizedName), + ("shouldhave", ShouldHave)); + } +} diff --git a/Content.Server/EntityEffects/EffectConditions/ReagentThreshold.cs b/Content.Shared/EntityEffects/EffectConditions/ReagentThreshold.cs similarity index 95% rename from Content.Server/EntityEffects/EffectConditions/ReagentThreshold.cs rename to Content.Shared/EntityEffects/EffectConditions/ReagentThreshold.cs index 6cbd7b4ea5..af71f20c8e 100644 --- a/Content.Server/EntityEffects/EffectConditions/ReagentThreshold.cs +++ b/Content.Shared/EntityEffects/EffectConditions/ReagentThreshold.cs @@ -1,9 +1,8 @@ using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; using Content.Shared.FixedPoint; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.EffectConditions; +namespace Content.Shared.EntityEffects.EffectConditions; /// /// Used for implementing reagent effects that require a certain amount of reagent before it should be applied. diff --git a/Content.Server/EntityEffects/EffectConditions/SolutionTemperature.cs b/Content.Shared/EntityEffects/EffectConditions/SolutionTemperature.cs similarity index 92% rename from Content.Server/EntityEffects/EffectConditions/SolutionTemperature.cs rename to Content.Shared/EntityEffects/EffectConditions/SolutionTemperature.cs index b964435db5..a9629401a0 100644 --- a/Content.Server/EntityEffects/EffectConditions/SolutionTemperature.cs +++ b/Content.Shared/EntityEffects/EffectConditions/SolutionTemperature.cs @@ -1,7 +1,6 @@ -using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.EffectConditions; +namespace Content.Shared.EntityEffects.EffectConditions; /// /// Requires the solution to be above or below a certain temperature. diff --git a/Content.Server/EntityEffects/EffectConditions/TotalDamage.cs b/Content.Shared/EntityEffects/EffectConditions/TotalDamage.cs similarity index 94% rename from Content.Server/EntityEffects/EffectConditions/TotalDamage.cs rename to Content.Shared/EntityEffects/EffectConditions/TotalDamage.cs index 2d039a1ac8..62b3e037e1 100644 --- a/Content.Server/EntityEffects/EffectConditions/TotalDamage.cs +++ b/Content.Shared/EntityEffects/EffectConditions/TotalDamage.cs @@ -3,7 +3,7 @@ using Content.Shared.Damage; using Content.Shared.FixedPoint; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.EffectConditions; +namespace Content.Shared.EntityEffects.EffectConditions; public sealed partial class TotalDamage : EntityEffectCondition { diff --git a/Content.Server/EntityEffects/EffectConditions/TotalHunger.cs b/Content.Shared/EntityEffects/EffectConditions/TotalHunger.cs similarity index 94% rename from Content.Server/EntityEffects/EffectConditions/TotalHunger.cs rename to Content.Shared/EntityEffects/EffectConditions/TotalHunger.cs index c4f69b60de..b4f1a1af89 100644 --- a/Content.Server/EntityEffects/EffectConditions/TotalHunger.cs +++ b/Content.Shared/EntityEffects/EffectConditions/TotalHunger.cs @@ -3,7 +3,7 @@ using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.EffectConditions; +namespace Content.Shared.EntityEffects.EffectConditions; public sealed partial class Hunger : EntityEffectCondition { diff --git a/Content.Server/EntityEffects/Effects/AddToSolutionReaction.cs b/Content.Shared/EntityEffects/Effects/AddToSolutionReaction.cs similarity index 91% rename from Content.Server/EntityEffects/Effects/AddToSolutionReaction.cs rename to Content.Shared/EntityEffects/Effects/AddToSolutionReaction.cs index b5bb2a22fb..0f2d35d369 100644 --- a/Content.Server/EntityEffects/Effects/AddToSolutionReaction.cs +++ b/Content.Shared/EntityEffects/Effects/AddToSolutionReaction.cs @@ -1,11 +1,8 @@ using Content.Shared.Chemistry.EntitySystems; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects +namespace Content.Shared.EntityEffects.Effects { - [UsedImplicitly] public sealed partial class AddToSolutionReaction : EntityEffect { [DataField("solution")] diff --git a/Content.Server/EntityEffects/Effects/AdjustAlert.cs b/Content.Shared/EntityEffects/Effects/AdjustAlert.cs similarity index 95% rename from Content.Server/EntityEffects/Effects/AdjustAlert.cs rename to Content.Shared/EntityEffects/Effects/AdjustAlert.cs index 3bf57b309d..282de0a06c 100644 --- a/Content.Server/EntityEffects/Effects/AdjustAlert.cs +++ b/Content.Shared/EntityEffects/Effects/AdjustAlert.cs @@ -1,9 +1,8 @@ using Content.Shared.Alert; -using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; public sealed partial class AdjustAlert : EntityEffect { diff --git a/Content.Server/EntityEffects/Effects/AdjustReagent.cs b/Content.Shared/EntityEffects/Effects/AdjustReagent.cs similarity index 96% rename from Content.Server/EntityEffects/Effects/AdjustReagent.cs rename to Content.Shared/EntityEffects/Effects/AdjustReagent.cs index 71117d6ec5..bb655b46bc 100644 --- a/Content.Server/EntityEffects/Effects/AdjustReagent.cs +++ b/Content.Shared/EntityEffects/Effects/AdjustReagent.cs @@ -1,14 +1,11 @@ using Content.Shared.Body.Prototypes; using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; using Content.Shared.FixedPoint; -using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.EntityEffects.Effects +namespace Content.Shared.EntityEffects.Effects { - [UsedImplicitly] public sealed partial class AdjustReagent : EntityEffect { /// @@ -90,3 +87,4 @@ namespace Content.Server.EntityEffects.Effects } } } + diff --git a/Content.Shared/EntityEffects/Effects/AdjustTemperature.cs b/Content.Shared/EntityEffects/Effects/AdjustTemperature.cs new file mode 100644 index 0000000000..03dc226e93 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/AdjustTemperature.cs @@ -0,0 +1,15 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class AdjustTemperature : EventEntityEffect +{ + [DataField] + public float Amount; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-adjust-temperature", + ("chance", Probability), + ("deltasign", MathF.Sign(Amount)), + ("amount", MathF.Abs(Amount))); +} diff --git a/Content.Shared/EntityEffects/Effects/AreaReactionEffect.cs b/Content.Shared/EntityEffects/Effects/AreaReactionEffect.cs new file mode 100644 index 0000000000..45ed261a35 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/AreaReactionEffect.cs @@ -0,0 +1,43 @@ +using Content.Shared.Database; +using Content.Shared.FixedPoint; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Basically smoke and foam reactions. +/// +public sealed partial class AreaReactionEffect : EventEntityEffect +{ + /// + /// How many seconds will the effect stay, counting after fully spreading. + /// + [DataField("duration")] public float Duration = 10; + + /// + /// How many units of reaction for 1 smoke entity. + /// + [DataField] public FixedPoint2 OverflowThreshold = FixedPoint2.New(2.5); + + /// + /// The entity prototype that will be spawned as the effect. + /// + [DataField("prototypeId", required: true, customTypeSerializer:typeof(PrototypeIdSerializer))] + public string PrototypeId = default!; + + /// + /// Sound that will get played when this reaction effect occurs. + /// + [DataField("sound", required: true)] public SoundSpecifier Sound = default!; + + public override bool ShouldLog => true; + + protected override string ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-area-reaction", + ("duration", Duration) + ); + + public override LogImpact LogImpact => LogImpact.High; +} diff --git a/Content.Server/EntityEffects/Effects/ArtifactUnlock.cs b/Content.Shared/EntityEffects/Effects/ArtifactUnlock.cs similarity index 84% rename from Content.Server/EntityEffects/Effects/ArtifactUnlock.cs rename to Content.Shared/EntityEffects/Effects/ArtifactUnlock.cs index 21454ff7a7..077e1ebfd2 100644 --- a/Content.Server/EntityEffects/Effects/ArtifactUnlock.cs +++ b/Content.Shared/EntityEffects/Effects/ArtifactUnlock.cs @@ -1,25 +1,22 @@ -using Content.Server.Popups; -using Content.Server.Xenoarchaeology.Artifact; +using Content.Shared.Xenoarchaeology.Artifact; using Content.Shared.EntityEffects; using Content.Shared.Popups; using Content.Shared.Xenoarchaeology.Artifact.Components; -using JetBrains.Annotations; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Sets an artifact into the unlocking state and marks the artifexium effect as true. /// This is a very specific behavior intended for a specific chem. /// -[UsedImplicitly] public sealed partial class ArtifactUnlock : EntityEffect { public override void Effect(EntityEffectBaseArgs args) { var entMan = args.EntityManager; - var xenoArtifactSys = entMan.System(); - var popupSys = entMan.System(); + var xenoArtifactSys = entMan.System(); + var popupSys = entMan.System(); if (!entMan.TryGetComponent(args.TargetEntity, out var xenoArtifact)) return; diff --git a/Content.Shared/EntityEffects/Effects/CauseZombieInfection.cs b/Content.Shared/EntityEffects/Effects/CauseZombieInfection.cs new file mode 100644 index 0000000000..3f8c58b74c --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/CauseZombieInfection.cs @@ -0,0 +1,9 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class CauseZombieInfection : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-cause-zombie-infection", ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/ChemCleanBloodstream.cs b/Content.Shared/EntityEffects/Effects/ChemCleanBloodstream.cs new file mode 100644 index 0000000000..98181b8667 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/ChemCleanBloodstream.cs @@ -0,0 +1,15 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Basically smoke and foam reactions. +/// +public sealed partial class ChemCleanBloodstream : EventEntityEffect +{ + [DataField] + public float CleanseRate = 3.0f; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-chem-clean-bloodstream", ("chance", Probability)); +} diff --git a/Content.Server/EntityEffects/Effects/ChemHealEyeDamage.cs b/Content.Shared/EntityEffects/Effects/ChemHealEyeDamage.cs similarity index 87% rename from Content.Server/EntityEffects/Effects/ChemHealEyeDamage.cs rename to Content.Shared/EntityEffects/Effects/ChemHealEyeDamage.cs index 42fc9ffa9f..83b2aa96e5 100644 --- a/Content.Server/EntityEffects/Effects/ChemHealEyeDamage.cs +++ b/Content.Shared/EntityEffects/Effects/ChemHealEyeDamage.cs @@ -1,14 +1,11 @@ -using Content.Shared.EntityEffects; using Content.Shared.Eye.Blinding.Systems; -using JetBrains.Annotations; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Heal or apply eye damage /// -[UsedImplicitly] public sealed partial class ChemHealEyeDamage : EntityEffect { /// diff --git a/Content.Shared/EntityEffects/Effects/ChemVomit.cs b/Content.Shared/EntityEffects/Effects/ChemVomit.cs new file mode 100644 index 0000000000..1cd6b2552c --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/ChemVomit.cs @@ -0,0 +1,19 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Forces you to vomit. +/// +public sealed partial class ChemVomit : EventEntityEffect +{ + /// How many units of thirst to add each time we vomit + [DataField] + public float ThirstAmount = -8f; + /// How many units of hunger to add each time we vomit + [DataField] + public float HungerAmount = -8f; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-chem-vomit", ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/CreateEntityReactionEffect.cs b/Content.Shared/EntityEffects/Effects/CreateEntityReactionEffect.cs new file mode 100644 index 0000000000..33173b1737 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/CreateEntityReactionEffect.cs @@ -0,0 +1,26 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.EntityEffects.Effects; + +[DataDefinition] +public sealed partial class CreateEntityReactionEffect : EventEntityEffect +{ + /// + /// What entity to create. + /// + [DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + public string Entity = default!; + + /// + /// How many entities to create per unit reaction. + /// + [DataField] + public uint Number = 1; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-create-entity-reaction-effect", + ("chance", Probability), + ("entname", IoCManager.Resolve().Index(Entity).Name), + ("amount", Number)); +} diff --git a/Content.Shared/EntityEffects/Effects/CreateGas.cs b/Content.Shared/EntityEffects/Effects/CreateGas.cs new file mode 100644 index 0000000000..75d554cdb3 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/CreateGas.cs @@ -0,0 +1,32 @@ +using Content.Shared.Atmos; +using Content.Shared.Atmos.EntitySystems; +using Content.Shared.Database; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class CreateGas : EventEntityEffect +{ + [DataField(required: true)] + public Gas Gas = default!; + + /// + /// For each unit consumed, how many moles of gas should be created? + /// + [DataField] + public float Multiplier = 3f; + + public override bool ShouldLog => true; + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + var atmos = entSys.GetEntitySystem(); + var gasProto = atmos.GetGas(Gas); + + return Loc.GetString("reagent-effect-guidebook-create-gas", + ("chance", Probability), + ("moles", Multiplier), + ("gas", gasProto.Name)); + } + + public override LogImpact LogImpact => LogImpact.High; +} diff --git a/Content.Shared/EntityEffects/Effects/CureZombieInfection.cs b/Content.Shared/EntityEffects/Effects/CureZombieInfection.cs new file mode 100644 index 0000000000..dd2d21854c --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/CureZombieInfection.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class CureZombieInfection : EventEntityEffect +{ + [DataField] + public bool Innoculate; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + if(Innoculate) + return Loc.GetString("reagent-effect-guidebook-innoculate-zombie-infection", ("chance", Probability)); + + return Loc.GetString("reagent-effect-guidebook-cure-zombie-infection", ("chance", Probability)); + } +} + diff --git a/Content.Server/EntityEffects/Effects/Drunk.cs b/Content.Shared/EntityEffects/Effects/Drunk.cs similarity index 91% rename from Content.Server/EntityEffects/Effects/Drunk.cs rename to Content.Shared/EntityEffects/Effects/Drunk.cs index 493560e5b9..5f7f29c342 100644 --- a/Content.Server/EntityEffects/Effects/Drunk.cs +++ b/Content.Shared/EntityEffects/Effects/Drunk.cs @@ -1,8 +1,7 @@ using Content.Shared.Drunk; -using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; public sealed partial class Drunk : EntityEffect { @@ -28,7 +27,7 @@ public sealed partial class Drunk : EntityEffect if (args is EntityEffectReagentArgs reagentArgs) { boozePower *= reagentArgs.Scale.Float(); } - + var drunkSys = args.EntityManager.EntitySysManager.GetEntitySystem(); drunkSys.TryApplyDrunkenness(args.TargetEntity, boozePower, SlurSpeech); } diff --git a/Content.Server/EntityEffects/Effects/Electrocute.cs b/Content.Shared/EntityEffects/Effects/Electrocute.cs similarity index 78% rename from Content.Server/EntityEffects/Effects/Electrocute.cs rename to Content.Shared/EntityEffects/Effects/Electrocute.cs index f6a5f1a2da..32e0ff1172 100644 --- a/Content.Server/EntityEffects/Effects/Electrocute.cs +++ b/Content.Shared/EntityEffects/Effects/Electrocute.cs @@ -1,8 +1,7 @@ -using Content.Server.Electrocution; -using Content.Shared.EntityEffects; +using Content.Shared.Electrocution; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; public sealed partial class Electrocute : EntityEffect { @@ -24,14 +23,14 @@ public sealed partial class Electrocute : EntityEffect { if (args is EntityEffectReagentArgs reagentArgs) { - reagentArgs.EntityManager.System().TryDoElectrocution(reagentArgs.TargetEntity, null, + reagentArgs.EntityManager.System().TryDoElectrocution(reagentArgs.TargetEntity, null, Math.Max((reagentArgs.Quantity * ElectrocuteDamageScale).Int(), 1), TimeSpan.FromSeconds(ElectrocuteTime), Refresh, ignoreInsulation: true); if (reagentArgs.Reagent != null) reagentArgs.Source?.RemoveReagent(reagentArgs.Reagent.ID, reagentArgs.Quantity); } else { - args.EntityManager.System().TryDoElectrocution(args.TargetEntity, null, + args.EntityManager.System().TryDoElectrocution(args.TargetEntity, null, Math.Max(ElectrocuteDamageScale, 1), TimeSpan.FromSeconds(ElectrocuteTime), Refresh, ignoreInsulation: true); } } diff --git a/Content.Server/EntityEffects/Effects/Emote.cs b/Content.Shared/EntityEffects/Effects/Emote.cs similarity index 70% rename from Content.Server/EntityEffects/Effects/Emote.cs rename to Content.Shared/EntityEffects/Effects/Emote.cs index 227e60a175..08cf58c39a 100644 --- a/Content.Server/EntityEffects/Effects/Emote.cs +++ b/Content.Shared/EntityEffects/Effects/Emote.cs @@ -1,17 +1,13 @@ -using Content.Server.Chat.Systems; using Content.Shared.Chat.Prototypes; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Tries to force someone to emote (scream, laugh, etc). Still respects whitelists/blacklists and other limits unless specially forced. /// -[UsedImplicitly] -public sealed partial class Emote : EntityEffect +public sealed partial class Emote : EventEntityEffect { /// /// The emote the entity will preform. @@ -44,13 +40,4 @@ public sealed partial class Emote : EntityEffect return Loc.GetString("reagent-effect-guidebook-emote", ("chance", Probability), ("emote", EmoteId)); } - - public override void Effect(EntityEffectBaseArgs args) - { - var chatSys = args.EntityManager.System(); - if (ShowInChat) - chatSys.TryEmoteWithChat(args.TargetEntity, EmoteId, ChatTransmitRange.GhostRangeLimit, forceEmote: Force); - else - chatSys.TryEmoteWithoutChat(args.TargetEntity, EmoteId); - } } diff --git a/Content.Shared/EntityEffects/Effects/EmpReactionEffect.cs b/Content.Shared/EntityEffects/Effects/EmpReactionEffect.cs new file mode 100644 index 0000000000..eee0aeb51b --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/EmpReactionEffect.cs @@ -0,0 +1,34 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +[DataDefinition] +public sealed partial class EmpReactionEffect : EventEntityEffect +{ + /// + /// Impulse range per unit of quantity + /// + [DataField("rangePerUnit")] + public float EmpRangePerUnit = 0.5f; + + /// + /// Maximum impulse range + /// + [DataField("maxRange")] + public float EmpMaxRange = 10; + + /// + /// How much energy will be drain from sources + /// + [DataField] + public float EnergyConsumption = 12500; + + /// + /// Amount of time entities will be disabled + /// + [DataField("duration")] + public float DisableDuration = 15; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-emp-reaction-effect", ("chance", Probability)); +} diff --git a/Content.Server/EntityEffects/Effects/EvenHealthChange.cs b/Content.Shared/EntityEffects/Effects/EvenHealthChange.cs similarity index 98% rename from Content.Server/EntityEffects/Effects/EvenHealthChange.cs rename to Content.Shared/EntityEffects/Effects/EvenHealthChange.cs index acf2bfafab..968d559939 100644 --- a/Content.Server/EntityEffects/Effects/EvenHealthChange.cs +++ b/Content.Shared/EntityEffects/Effects/EvenHealthChange.cs @@ -3,16 +3,14 @@ using Content.Shared.Damage.Prototypes; using Content.Shared.EntityEffects; using Content.Shared.FixedPoint; using Content.Shared.Localizations; -using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Utility; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Version of that distributes the healing to groups /// -[UsedImplicitly] public sealed partial class EvenHealthChange : EntityEffect { /// diff --git a/Content.Server/EntityEffects/Effects/ExplosionReactionEffect.cs b/Content.Shared/EntityEffects/Effects/ExplosionReactionEffect.cs similarity index 74% rename from Content.Server/EntityEffects/Effects/ExplosionReactionEffect.cs rename to Content.Shared/EntityEffects/Effects/ExplosionReactionEffect.cs index 24c58898c6..bc9af15092 100644 --- a/Content.Server/EntityEffects/Effects/ExplosionReactionEffect.cs +++ b/Content.Shared/EntityEffects/Effects/ExplosionReactionEffect.cs @@ -1,15 +1,13 @@ -using Content.Server.Explosion.EntitySystems; using Content.Shared.Database; -using Content.Shared.EntityEffects; using Content.Shared.Explosion; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using System.Text.Json.Serialization; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; [DataDefinition] -public sealed partial class ExplosionReactionEffect : EntityEffect +public sealed partial class ExplosionReactionEffect : EventEntityEffect { /// /// The type of explosion. Determines damage types and tile break chance scaling. @@ -45,7 +43,7 @@ public sealed partial class ExplosionReactionEffect : EntityEffect /// [DataField] public float IntensityPerUnit = 1; - + /// /// Factor used to scale the explosion intensity when calculating tile break chances. Allows for stronger /// explosives that don't space tiles, without having to create a new explosion-type prototype. @@ -58,23 +56,4 @@ public sealed partial class ExplosionReactionEffect : EntityEffect protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-explosion-reaction-effect", ("chance", Probability)); public override LogImpact LogImpact => LogImpact.High; - - public override void Effect(EntityEffectBaseArgs args) - { - var intensity = IntensityPerUnit; - - if (args is EntityEffectReagentArgs reagentArgs) - { - intensity = MathF.Min((float) reagentArgs.Quantity * IntensityPerUnit, MaxTotalIntensity); - } - - args.EntityManager.System() - .QueueExplosion( - args.TargetEntity, - ExplosionType, - intensity, - IntensitySlope, - MaxIntensity, - TileBreakScale); - } } diff --git a/Content.Server/EntityEffects/Effects/ExtinguishReaction.cs b/Content.Shared/EntityEffects/Effects/ExtinguishReaction.cs similarity index 88% rename from Content.Server/EntityEffects/Effects/ExtinguishReaction.cs rename to Content.Shared/EntityEffects/Effects/ExtinguishReaction.cs index d36ac9a576..11e776ac90 100644 --- a/Content.Server/EntityEffects/Effects/ExtinguishReaction.cs +++ b/Content.Shared/EntityEffects/Effects/ExtinguishReaction.cs @@ -1,11 +1,8 @@ using Content.Shared.Atmos; -using Content.Shared.EntityEffects; -using JetBrains.Annotations; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects +namespace Content.Shared.EntityEffects.Effects { - [UsedImplicitly] public sealed partial class ExtinguishReaction : EntityEffect { /// diff --git a/Content.Shared/EntityEffects/Effects/FlammableReaction.cs b/Content.Shared/EntityEffects/Effects/FlammableReaction.cs new file mode 100644 index 0000000000..9f7d504f4e --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/FlammableReaction.cs @@ -0,0 +1,21 @@ +using Content.Shared.Database; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class FlammableReaction : EventEntityEffect +{ + [DataField] + public float Multiplier = 0.05f; + + // The fire stack multiplier if fire stacks already exist on target, only works if 0 or greater + [DataField] + public float MultiplierOnExisting = -1f; + + public override bool ShouldLog => true; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-flammable-reaction", ("chance", Probability)); + + public override LogImpact LogImpact => LogImpact.Medium; +} diff --git a/Content.Shared/EntityEffects/Effects/FlashReactionEffect.cs b/Content.Shared/EntityEffects/Effects/FlashReactionEffect.cs new file mode 100644 index 0000000000..5cd7f06c52 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/FlashReactionEffect.cs @@ -0,0 +1,48 @@ +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +[DataDefinition] +public sealed partial class FlashReactionEffect : EventEntityEffect +{ + /// + /// Flash range per unit of reagent. + /// + [DataField] + public float RangePerUnit = 0.2f; + + /// + /// Maximum flash range. + /// + [DataField] + public float MaxRange = 10f; + + /// + /// How much to entities are slowed down. + /// + [DataField] + public float SlowTo = 0.5f; + + /// + /// The time entities will be flashed in seconds. + /// The default is chosen to be better than the hand flash so it is worth using it for grenades etc. + /// + [DataField] + public float Duration = 4f; + + /// + /// The prototype ID used for the visual effect. + /// + [DataField] + public EntProtoId? FlashEffectPrototype = "ReactionFlash"; + + /// + /// The sound the flash creates. + /// + [DataField] + public SoundSpecifier? Sound = new SoundPathSpecifier("/Audio/Weapons/flash.ogg"); + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-flash-reaction-effect", ("chance", Probability)); +} diff --git a/Content.Server/EntityEffects/Effects/Glow.cs b/Content.Shared/EntityEffects/Effects/Glow.cs similarity index 96% rename from Content.Server/EntityEffects/Effects/Glow.cs rename to Content.Shared/EntityEffects/Effects/Glow.cs index 9f03476729..394d406700 100644 --- a/Content.Server/EntityEffects/Effects/Glow.cs +++ b/Content.Shared/EntityEffects/Effects/Glow.cs @@ -2,7 +2,7 @@ using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; using Robust.Shared.Random; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Makes a mob glow. diff --git a/Content.Server/EntityEffects/Effects/HealthChange.cs b/Content.Shared/EntityEffects/Effects/HealthChange.cs similarity index 98% rename from Content.Server/EntityEffects/Effects/HealthChange.cs rename to Content.Shared/EntityEffects/Effects/HealthChange.cs index dd398da5b2..17c24f6b5a 100644 --- a/Content.Server/EntityEffects/Effects/HealthChange.cs +++ b/Content.Shared/EntityEffects/Effects/HealthChange.cs @@ -3,17 +3,15 @@ using Content.Shared.Damage.Prototypes; using Content.Shared.EntityEffects; using Content.Shared.FixedPoint; using Content.Shared.Localizations; -using JetBrains.Annotations; using Robust.Shared.Prototypes; using System.Linq; using System.Text.Json.Serialization; -namespace Content.Server.EntityEffects.Effects +namespace Content.Shared.EntityEffects.Effects { /// /// Default metabolism used for medicine reagents. /// - [UsedImplicitly] public sealed partial class HealthChange : EntityEffect { /// diff --git a/Content.Shared/EntityEffects/Effects/Ignite.cs b/Content.Shared/EntityEffects/Effects/Ignite.cs new file mode 100644 index 0000000000..707ecc3208 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/Ignite.cs @@ -0,0 +1,18 @@ +using Content.Shared.Database; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Ignites a mob. +/// +public sealed partial class Ignite : EventEntityEffect +{ + public override bool ShouldLog => true; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-ignite", ("chance", Probability)); + + public override LogImpact LogImpact => LogImpact.Medium; +} diff --git a/Content.Shared/EntityEffects/Effects/MakeSentient.cs b/Content.Shared/EntityEffects/Effects/MakeSentient.cs new file mode 100644 index 0000000000..9c70eb452b --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/MakeSentient.cs @@ -0,0 +1,10 @@ +using Content.Shared.Mind.Components; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class MakeSentient : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-make-sentient", ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/ModifyBleedAmount.cs b/Content.Shared/EntityEffects/Effects/ModifyBleedAmount.cs new file mode 100644 index 0000000000..9f15652095 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/ModifyBleedAmount.cs @@ -0,0 +1,16 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class ModifyBleedAmount : EventEntityEffect +{ + [DataField] + public bool Scaled = false; + + [DataField] + public float Amount = -1.0f; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-modify-bleed-amount", ("chance", Probability), + ("deltasign", MathF.Sign(Amount))); +} diff --git a/Content.Shared/EntityEffects/Effects/ModifyBloodLevel.cs b/Content.Shared/EntityEffects/Effects/ModifyBloodLevel.cs new file mode 100644 index 0000000000..06c026f128 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/ModifyBloodLevel.cs @@ -0,0 +1,17 @@ +using Content.Shared.FixedPoint; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class ModifyBloodLevel : EventEntityEffect +{ + [DataField] + public bool Scaled = false; + + [DataField] + public FixedPoint2 Amount = 1.0f; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-modify-blood-level", ("chance", Probability), + ("deltasign", MathF.Sign(Amount.Float()))); +} diff --git a/Content.Shared/EntityEffects/Effects/ModifyLungGas.cs b/Content.Shared/EntityEffects/Effects/ModifyLungGas.cs new file mode 100644 index 0000000000..45dc8c84c6 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/ModifyLungGas.cs @@ -0,0 +1,14 @@ +using Content.Shared.Atmos; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class ModifyLungGas : EventEntityEffect +{ + [DataField("ratios", required: true)] + public Dictionary Ratios = default!; + + // JUSTIFICATION: This is internal magic that players never directly interact with. + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => null; +} diff --git a/Content.Server/EntityEffects/Effects/MovespeedModifier.cs b/Content.Shared/EntityEffects/Effects/MovespeedModifier.cs similarity index 97% rename from Content.Server/EntityEffects/Effects/MovespeedModifier.cs rename to Content.Shared/EntityEffects/Effects/MovespeedModifier.cs index 74f4489c75..5e72746e32 100644 --- a/Content.Server/EntityEffects/Effects/MovespeedModifier.cs +++ b/Content.Shared/EntityEffects/Effects/MovespeedModifier.cs @@ -1,10 +1,9 @@ using Content.Shared.Chemistry.Components; -using Content.Shared.EntityEffects; using Content.Shared.Movement.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Default metabolism for stimulants and tranqs. Attempts to find a MovementSpeedModifier on the target, diff --git a/Content.Shared/EntityEffects/Effects/Oxygenate.cs b/Content.Shared/EntityEffects/Effects/Oxygenate.cs new file mode 100644 index 0000000000..e990a3fec6 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/Oxygenate.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +public sealed partial class Oxygenate : EventEntityEffect +{ + [DataField] + public float Factor = 1f; + + // JUSTIFICATION: This is internal magic that players never directly interact with. + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => null; +} diff --git a/Content.Server/EntityEffects/Effects/Paralyze.cs b/Content.Shared/EntityEffects/Effects/Paralyze.cs similarity index 79% rename from Content.Server/EntityEffects/Effects/Paralyze.cs rename to Content.Shared/EntityEffects/Effects/Paralyze.cs index ba020dd39b..2da6a6a079 100644 --- a/Content.Server/EntityEffects/Effects/Paralyze.cs +++ b/Content.Shared/EntityEffects/Effects/Paralyze.cs @@ -1,8 +1,8 @@ -using Content.Server.Stunnable; using Content.Shared.EntityEffects; +using Content.Shared.Stunnable; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; public sealed partial class Paralyze : EntityEffect { @@ -27,7 +27,7 @@ public sealed partial class Paralyze : EntityEffect paralyzeTime *= (double)reagentArgs.Scale; } - args.EntityManager.System().TryParalyze(args.TargetEntity, TimeSpan.FromSeconds(paralyzeTime), Refresh); + args.EntityManager.System().TryParalyze(args.TargetEntity, TimeSpan.FromSeconds(paralyzeTime), Refresh); } } diff --git a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustAttribute.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustAttribute.cs similarity index 51% rename from Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustAttribute.cs rename to Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustAttribute.cs index 5133fe502f..2c8046452b 100644 --- a/Content.Server/EntityEffects/Effects/PlantMetabolism/PlantAdjustAttribute.cs +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustAttribute.cs @@ -1,13 +1,12 @@ -using Content.Server.Botany.Components; using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; using Robust.Shared.Random; using System.Diagnostics.CodeAnalysis; -namespace Content.Server.EntityEffects.Effects.PlantMetabolism; +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; [ImplicitDataDefinitionForInheritors] -public abstract partial class PlantAdjustAttribute : EntityEffect +public abstract partial class PlantAdjustAttribute : EventEntityEffect where T : PlantAdjustAttribute { [DataField] public float Amount { get; protected set; } = 1; @@ -24,27 +23,6 @@ public abstract partial class PlantAdjustAttribute : EntityEffect [DataField] public virtual bool GuidebookIsAttributePositive { get; protected set; } = true; - /// - /// Checks if the plant holder can metabolize the reagent or not. Checks if it has an alive plant by default. - /// - /// The entity holding the plant - /// The plant holder component - /// The entity manager - /// Whether to check if it has an alive plant or not - /// - public bool CanMetabolize(EntityUid plantHolder, [NotNullWhen(true)] out PlantHolderComponent? plantHolderComponent, - IEntityManager entityManager, - bool mustHaveAlivePlant = true) - { - plantHolderComponent = null; - - if (!entityManager.TryGetComponent(plantHolder, out plantHolderComponent) - || mustHaveAlivePlant && (plantHolderComponent.Seed == null || plantHolderComponent.Dead)) - return false; - - return true; - } - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) { string color; diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustHealth.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustHealth.cs new file mode 100644 index 0000000000..c1e71894e5 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustHealth.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAdjustHealth : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-health"; +} + diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationLevel.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationLevel.cs new file mode 100644 index 0000000000..6610adf708 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationLevel.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAdjustMutationLevel : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-mutation-level"; +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationMod.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationMod.cs new file mode 100644 index 0000000000..91be222807 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustMutationMod.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAdjustMutationMod : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-mutation-mod"; +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustNutrition.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustNutrition.cs new file mode 100644 index 0000000000..db01d5d060 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustNutrition.cs @@ -0,0 +1,6 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAdjustNutrition : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-nutrition"; +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs new file mode 100644 index 0000000000..18c00550d5 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustPests.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAdjustPests : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-pests"; + public override bool GuidebookIsAttributePositive { get; protected set; } = false; +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustPotency.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustPotency.cs new file mode 100644 index 0000000000..971f05f32d --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustPotency.cs @@ -0,0 +1,12 @@ +// using Content.Server.Botany.Systems; + +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +/// +/// Handles increase or decrease of plant potency. +/// + +public sealed partial class PlantAdjustPotency : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-potency"; +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs new file mode 100644 index 0000000000..9123b5847d --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustToxins.cs @@ -0,0 +1,8 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAdjustToxins : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-toxins"; + public override bool GuidebookIsAttributePositive { get; protected set; } = false; +} + diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustWater.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustWater.cs new file mode 100644 index 0000000000..610d02231b --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustWater.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAdjustWater : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-water"; +} + diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs new file mode 100644 index 0000000000..70ff0747dd --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAdjustWeeds.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAdjustWeeds : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-weeds"; + public override bool GuidebookIsAttributePositive { get; protected set; } = false; +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAffectGrowth.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAffectGrowth.cs new file mode 100644 index 0000000000..36b8f57d08 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantAffectGrowth.cs @@ -0,0 +1,7 @@ +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantAffectGrowth : PlantAdjustAttribute +{ + public override string GuidebookAttributeName { get; set; } = "plant-attribute-growth"; +} + diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantChangeStat.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantChangeStat.cs new file mode 100644 index 0000000000..66cfb66d4b --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantChangeStat.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantChangeStat : EventEntityEffect +{ + [DataField] + public string TargetValue; + + [DataField] + public float MinValue; + + [DataField] + public float MaxValue; + + [DataField] + public int Steps; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + throw new NotImplementedException(); + } +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantCryoxadone.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantCryoxadone.cs new file mode 100644 index 0000000000..0dabf1f22b --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantCryoxadone.cs @@ -0,0 +1,8 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantCryoxadone : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-plant-cryoxadone", ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantDestroySeeds.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantDestroySeeds.cs new file mode 100644 index 0000000000..9f16c35402 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantDestroySeeds.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +/// +/// Handles removal of seeds on a plant. +/// + +public sealed partial class PlantDestroySeeds : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => + Loc.GetString("reagent-effect-guidebook-plant-seeds-remove", ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantDiethylamine.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantDiethylamine.cs new file mode 100644 index 0000000000..9feccbf224 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantDiethylamine.cs @@ -0,0 +1,9 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantDiethylamine : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-plant-diethylamine", ("chance", Probability)); +} + diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantPhalanximine.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantPhalanximine.cs new file mode 100644 index 0000000000..9dc5140063 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantPhalanximine.cs @@ -0,0 +1,8 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class PlantPhalanximine : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-plant-phalanximine", ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantRestoreSeeds.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantRestoreSeeds.cs new file mode 100644 index 0000000000..51ce353dbb --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/PlantRestoreSeeds.cs @@ -0,0 +1,12 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +/// +/// Handles restoral of seeds on a plant. +/// +public sealed partial class PlantRestoreSeeds : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => + Loc.GetString("reagent-effect-guidebook-plant-seeds-add", ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMetabolism/RobustHarvest.cs b/Content.Shared/EntityEffects/Effects/PlantMetabolism/RobustHarvest.cs new file mode 100644 index 0000000000..6ba37c9be0 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMetabolism/RobustHarvest.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Shared.EntityEffects.Effects.PlantMetabolism; + +public sealed partial class RobustHarvest : EventEntityEffect +{ + [DataField] + public int PotencyLimit = 50; + + [DataField] + public int PotencyIncrease = 3; + + [DataField] + public int PotencySeedlessThreshold = 30; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) => Loc.GetString("reagent-effect-guidebook-plant-robust-harvest", ("seedlesstreshold", PotencySeedlessThreshold), ("limit", PotencyLimit), ("increase", PotencyIncrease), ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMutateChemicals.cs b/Content.Shared/EntityEffects/Effects/PlantMutateChemicals.cs new file mode 100644 index 0000000000..9a3408bb8e --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMutateChemicals.cs @@ -0,0 +1,16 @@ +using Content.Shared.Random; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// changes the chemicals available in a plant's produce +/// +public sealed partial class PlantMutateChemicals : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMutateGases.cs b/Content.Shared/EntityEffects/Effects/PlantMutateGases.cs new file mode 100644 index 0000000000..5eb5b1d07c --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMutateGases.cs @@ -0,0 +1,39 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using System.Linq; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// changes the gases that a plant or produce create. +/// +public sealed partial class PlantMutateExudeGasses : EventEntityEffect +{ + [DataField] + public float MinValue = 0.01f; + + [DataField] + public float MaxValue = 0.5f; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// changes the gases that a plant or produce consumes. +/// +public sealed partial class PlantMutateConsumeGasses : EventEntityEffect +{ + [DataField] + public float MinValue = 0.01f; + + [DataField] + public float MaxValue = 0.5f; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Shared/EntityEffects/Effects/PlantMutateHarvest.cs b/Content.Shared/EntityEffects/Effects/PlantMutateHarvest.cs new file mode 100644 index 0000000000..84d6293185 --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantMutateHarvest.cs @@ -0,0 +1,14 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Upgrades a plant's harvest type. +/// +public sealed partial class PlantMutateHarvest : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Shared/EntityEffects/Effects/PlantSpeciesChange.cs b/Content.Shared/EntityEffects/Effects/PlantSpeciesChange.cs new file mode 100644 index 0000000000..e2acc4cb7c --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/PlantSpeciesChange.cs @@ -0,0 +1,14 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Changes a plant into one of the species its able to mutate into. +/// +public sealed partial class PlantSpeciesChange : EventEntityEffect +{ + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Server/EntityEffects/Effects/Polymorph.cs b/Content.Shared/EntityEffects/Effects/Polymorph.cs similarity index 55% rename from Content.Server/EntityEffects/Effects/Polymorph.cs rename to Content.Shared/EntityEffects/Effects/Polymorph.cs index 2ee533a4d7..65711ff99a 100644 --- a/Content.Server/EntityEffects/Effects/Polymorph.cs +++ b/Content.Shared/EntityEffects/Effects/Polymorph.cs @@ -1,13 +1,10 @@ -using Content.Server.Polymorph.Components; -using Content.Server.Polymorph.Systems; -using Content.Shared.EntityEffects; using Content.Shared.Polymorph; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; -public sealed partial class Polymorph : EntityEffect +public sealed partial class Polymorph : EventEntityEffect { /// /// What polymorph prototype is used on effect @@ -19,15 +16,4 @@ public sealed partial class Polymorph : EntityEffect => Loc.GetString("reagent-effect-guidebook-make-polymorph", ("chance", Probability), ("entityname", prototype.Index(prototype.Index(PolymorphPrototype).Configuration.Entity).Name)); - - public override void Effect(EntityEffectBaseArgs args) - { - var entityManager = args.EntityManager; - var uid = args.TargetEntity; - var polySystem = entityManager.System(); - - // Make it into a prototype - entityManager.EnsureComponent(uid); - polySystem.PolymorphEntity(uid, PolymorphPrototype); - } } diff --git a/Content.Server/EntityEffects/Effects/PopupMessage.cs b/Content.Shared/EntityEffects/Effects/PopupMessage.cs similarity index 95% rename from Content.Server/EntityEffects/Effects/PopupMessage.cs rename to Content.Shared/EntityEffects/Effects/PopupMessage.cs index ac22b13051..a837f816e4 100644 --- a/Content.Server/EntityEffects/Effects/PopupMessage.cs +++ b/Content.Shared/EntityEffects/Effects/PopupMessage.cs @@ -1,9 +1,8 @@ -using Content.Shared.EntityEffects; using Content.Shared.Popups; using Robust.Shared.Prototypes; using Robust.Shared.Random; -namespace Content.Server.EntityEffects.Effects +namespace Content.Shared.EntityEffects.Effects { public sealed partial class PopupMessage : EntityEffect { diff --git a/Content.Shared/EntityEffects/Effects/ReduceRotting.cs b/Content.Shared/EntityEffects/Effects/ReduceRotting.cs new file mode 100644 index 0000000000..b5f2a7ae7e --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/ReduceRotting.cs @@ -0,0 +1,32 @@ +using Content.Shared.Chemistry.Reagent; +using Robust.Shared.Prototypes; +using Content.Shared.Atmos.Rotting; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Reduces the rotting accumulator on the patient, making them revivable. +/// +public sealed partial class ReduceRotting : EntityEffect +{ + [DataField("seconds")] + public double RottingAmount = 10; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-reduce-rotting", + ("chance", Probability), + ("time", RottingAmount)); + + public override void Effect(EntityEffectBaseArgs args) + { + if (args is EntityEffectReagentArgs reagentArgs) + { + if (reagentArgs.Scale != 1f) + return; + } + + var rottingSys = args.EntityManager.EntitySysManager.GetEntitySystem(); + + rottingSys.ReduceAccumulator(args.TargetEntity, TimeSpan.FromSeconds(RottingAmount)); + } +} diff --git a/Content.Shared/EntityEffects/Effects/ResetNarcolepsy.cs b/Content.Shared/EntityEffects/Effects/ResetNarcolepsy.cs new file mode 100644 index 0000000000..71d228aece --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/ResetNarcolepsy.cs @@ -0,0 +1,19 @@ +using Content.Shared.Chemistry.Reagent; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Reset narcolepsy timer +/// +public sealed partial class ResetNarcolepsy : EventEntityEffect +{ + /// + /// The # of seconds the effect resets the narcolepsy timer to + /// + [DataField("TimerReset")] + public int TimerReset = 600; + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-reset-narcolepsy", ("chance", Probability)); +} diff --git a/Content.Shared/EntityEffects/Effects/SatiateHunger.cs b/Content.Shared/EntityEffects/Effects/SatiateHunger.cs new file mode 100644 index 0000000000..3e7af8833c --- /dev/null +++ b/Content.Shared/EntityEffects/Effects/SatiateHunger.cs @@ -0,0 +1,40 @@ +using Content.Shared.Chemistry.Reagent; +using Content.Shared.Nutrition.Components; +using Content.Shared.Nutrition.EntitySystems; +using Robust.Shared.Prototypes; + +namespace Content.Shared.EntityEffects.Effects; + +/// +/// Attempts to find a HungerComponent on the target, +/// and to update it's hunger values. +/// +public sealed partial class SatiateHunger : EntityEffect +{ + private const float DefaultNutritionFactor = 3.0f; + + /// + /// How much hunger is satiated. + /// Is multiplied by quantity if used with EntityEffectReagentArgs. + /// + [DataField("factor")] public float NutritionFactor { get; set; } = DefaultNutritionFactor; + + //Remove reagent at set rate, satiate hunger if a HungerComponent can be found + public override void Effect(EntityEffectBaseArgs args) + { + var entman = args.EntityManager; + if (!entman.TryGetComponent(args.TargetEntity, out HungerComponent? hunger)) + return; + if (args is EntityEffectReagentArgs reagentArgs) + { + entman.System().ModifyHunger(reagentArgs.TargetEntity, NutritionFactor * (float) reagentArgs.Quantity, hunger); + } + else + { + entman.System().ModifyHunger(args.TargetEntity, NutritionFactor, hunger); + } + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + => Loc.GetString("reagent-effect-guidebook-satiate-hunger", ("chance", Probability), ("relative", NutritionFactor / DefaultNutritionFactor)); +} diff --git a/Content.Server/EntityEffects/Effects/SatiateThirst.cs b/Content.Shared/EntityEffects/Effects/SatiateThirst.cs similarity index 93% rename from Content.Server/EntityEffects/Effects/SatiateThirst.cs rename to Content.Shared/EntityEffects/Effects/SatiateThirst.cs index d0dbe4371b..21a055b528 100644 --- a/Content.Server/EntityEffects/Effects/SatiateThirst.cs +++ b/Content.Shared/EntityEffects/Effects/SatiateThirst.cs @@ -1,10 +1,9 @@ using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; using Content.Shared.Nutrition.Components; using Content.Shared.Nutrition.EntitySystems; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Default metabolism for drink reagents. Attempts to find a ThirstComponent on the target, diff --git a/Content.Server/EntityEffects/Effects/Slipify.cs b/Content.Shared/EntityEffects/Effects/Slipify.cs similarity index 95% rename from Content.Server/EntityEffects/Effects/Slipify.cs rename to Content.Shared/EntityEffects/Effects/Slipify.cs index bc1cc062a3..c152b8b010 100644 --- a/Content.Server/EntityEffects/Effects/Slipify.cs +++ b/Content.Shared/EntityEffects/Effects/Slipify.cs @@ -1,4 +1,3 @@ -using Content.Shared.EntityEffects; using Content.Shared.Physics; using Content.Shared.Slippery; using Content.Shared.StepTrigger.Components; @@ -7,7 +6,7 @@ using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Makes a mob slippery. diff --git a/Content.Server/EntityEffects/Effects/SolutionTemperatureEffects.cs b/Content.Shared/EntityEffects/Effects/SolutionTemperatureEffects.cs similarity index 98% rename from Content.Server/EntityEffects/Effects/SolutionTemperatureEffects.cs rename to Content.Shared/EntityEffects/Effects/SolutionTemperatureEffects.cs index 85c20dbcd1..30ac6c3d77 100644 --- a/Content.Server/EntityEffects/Effects/SolutionTemperatureEffects.cs +++ b/Content.Shared/EntityEffects/Effects/SolutionTemperatureEffects.cs @@ -1,8 +1,7 @@ using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// Sets the temperature of the solution involved with the reaction to a new value. diff --git a/Content.Server/EntityEffects/Effects/StatusEffects/GenericStatusEffect.cs b/Content.Shared/EntityEffects/Effects/StatusEffects/GenericStatusEffect.cs similarity index 94% rename from Content.Server/EntityEffects/Effects/StatusEffects/GenericStatusEffect.cs rename to Content.Shared/EntityEffects/Effects/StatusEffects/GenericStatusEffect.cs index bb9bbf3446..c6b162a82f 100644 --- a/Content.Server/EntityEffects/Effects/StatusEffects/GenericStatusEffect.cs +++ b/Content.Shared/EntityEffects/Effects/StatusEffects/GenericStatusEffect.cs @@ -1,10 +1,8 @@ using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; using Content.Shared.StatusEffect; -using JetBrains.Annotations; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects.StatusEffects; +namespace Content.Shared.EntityEffects.Effects.StatusEffects; /// /// Adds a generic status effect to the entity, @@ -15,7 +13,6 @@ namespace Content.Server.EntityEffects.Effects.StatusEffects; /// /// Can be used for things like adding accents or something. I don't know. Go wild. /// -[UsedImplicitly] public sealed partial class GenericStatusEffect : EntityEffect { [DataField(required: true)] diff --git a/Content.Server/EntityEffects/Effects/StatusEffects/Jitter.cs b/Content.Shared/EntityEffects/Effects/StatusEffects/Jitter.cs similarity index 92% rename from Content.Server/EntityEffects/Effects/StatusEffects/Jitter.cs rename to Content.Shared/EntityEffects/Effects/StatusEffects/Jitter.cs index dbca4fad58..891c791b07 100644 --- a/Content.Server/EntityEffects/Effects/StatusEffects/Jitter.cs +++ b/Content.Shared/EntityEffects/Effects/StatusEffects/Jitter.cs @@ -1,9 +1,8 @@ using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; using Content.Shared.Jittering; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects.StatusEffects; +namespace Content.Shared.EntityEffects.Effects.StatusEffects; /// /// Adds the jitter status effect to a mob. diff --git a/Content.Server/EntityEffects/Effects/WashCreamPieReaction.cs b/Content.Shared/EntityEffects/Effects/WashCreamPieReaction.cs similarity index 67% rename from Content.Server/EntityEffects/Effects/WashCreamPieReaction.cs rename to Content.Shared/EntityEffects/Effects/WashCreamPieReaction.cs index 67bfac6335..e6992a3ec8 100644 --- a/Content.Server/EntityEffects/Effects/WashCreamPieReaction.cs +++ b/Content.Shared/EntityEffects/Effects/WashCreamPieReaction.cs @@ -1,13 +1,10 @@ -using Content.Server.Nutrition.EntitySystems; using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; using Content.Shared.Nutrition.Components; -using JetBrains.Annotations; +using Content.Shared.Nutrition.EntitySystems; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects; +namespace Content.Shared.EntityEffects.Effects; -[UsedImplicitly] public sealed partial class WashCreamPieReaction : EntityEffect { protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -17,6 +14,6 @@ public sealed partial class WashCreamPieReaction : EntityEffect { if (!args.EntityManager.TryGetComponent(args.TargetEntity, out CreamPiedComponent? creamPied)) return; - args.EntityManager.System().SetCreamPied(args.TargetEntity, creamPied, false); + args.EntityManager.System().SetCreamPied(args.TargetEntity, creamPied, false); } } diff --git a/Content.Server/EntityEffects/Effects/WearableReaction.cs b/Content.Shared/EntityEffects/Effects/WearableReaction.cs similarity index 94% rename from Content.Server/EntityEffects/Effects/WearableReaction.cs rename to Content.Shared/EntityEffects/Effects/WearableReaction.cs index 9655bbc073..08c28f9821 100644 --- a/Content.Server/EntityEffects/Effects/WearableReaction.cs +++ b/Content.Shared/EntityEffects/Effects/WearableReaction.cs @@ -1,9 +1,8 @@ using Content.Shared.Inventory; using Content.Shared.Chemistry.Reagent; -using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; -namespace Content.Server.EntityEffects.Effects.Effects; +namespace Content.Shared.EntityEffects.Effects; /// /// A reaction effect that spawns a PrototypeID in the entity's Slot, and attempts to consume the reagent if EntityEffectReagentArgs. diff --git a/Content.Shared/EntityEffects/EntityEffect.cs b/Content.Shared/EntityEffects/EntityEffect.cs index 21e79f224d..998759006f 100644 --- a/Content.Shared/EntityEffects/EntityEffect.cs +++ b/Content.Shared/EntityEffects/EntityEffect.cs @@ -89,6 +89,19 @@ public static class EntityEffectExt } } +[ByRefEvent] +public struct ExecuteEntityEffectEvent where T : EntityEffect +{ + public T Effect; + public EntityEffectBaseArgs Args; + + public ExecuteEntityEffectEvent(T effect, EntityEffectBaseArgs args) + { + Effect = effect; + Args = args; + } +} + /// /// 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). diff --git a/Content.Shared/EntityEffects/EntityEffectCondition.cs b/Content.Shared/EntityEffects/EntityEffectCondition.cs index d6028b9f2c..4c27b1e6ed 100644 --- a/Content.Shared/EntityEffects/EntityEffectCondition.cs +++ b/Content.Shared/EntityEffects/EntityEffectCondition.cs @@ -20,3 +20,10 @@ public abstract partial class EntityEffectCondition public abstract string GuidebookExplanation(IPrototypeManager prototype); } +[ByRefEvent] +public struct CheckEntityEffectConditionEvent where T : EntityEffectCondition +{ + public T Condition; + public EntityEffectBaseArgs Args; + public bool Result; +} diff --git a/Content.Shared/EntityEffects/EventEntityEffect.cs b/Content.Shared/EntityEffects/EventEntityEffect.cs new file mode 100644 index 0000000000..22cd035867 --- /dev/null +++ b/Content.Shared/EntityEffects/EventEntityEffect.cs @@ -0,0 +1,12 @@ +namespace Content.Shared.EntityEffects; + +public abstract partial class EventEntityEffect : EntityEffect where T : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + if (this is not T type) + return; + var ev = new ExecuteEntityEffectEvent(type, args); + args.EntityManager.EventBus.RaiseEvent(EventSource.Local, ref ev); + } +} diff --git a/Content.Shared/EntityEffects/EventEntityEffectCondition.cs b/Content.Shared/EntityEffects/EventEntityEffectCondition.cs new file mode 100644 index 0000000000..f36b1771b2 --- /dev/null +++ b/Content.Shared/EntityEffects/EventEntityEffectCondition.cs @@ -0,0 +1,14 @@ +namespace Content.Shared.EntityEffects; + +public abstract partial class EventEntityEffectCondition : EntityEffectCondition where T : EventEntityEffectCondition +{ + public override bool Condition(EntityEffectBaseArgs args) + { + if (this is not T type) + return false; + + var evt = new CheckEntityEffectConditionEvent { Condition = type, Args = args }; + args.EntityManager.EventBus.RaiseEvent(EventSource.Local, ref evt); + return evt.Result; + } +}