diff --git a/Content.Server/Devour/DevourSystem.cs b/Content.Server/Devour/DevourSystem.cs index 88edc3ec4c..ede13fa817 100644 --- a/Content.Server/Devour/DevourSystem.cs +++ b/Content.Server/Devour/DevourSystem.cs @@ -3,13 +3,14 @@ using Content.Shared.Body.Events; using Content.Shared.Chemistry.Components; using Content.Shared.Devour; using Content.Shared.Devour.Components; -using Content.Shared.Humanoid; +using Content.Shared.Whitelist; namespace Content.Server.Devour; public sealed class DevourSystem : SharedDevourSystem { [Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!; + [Dependency] private readonly EntityWhitelistSystem _entityWhitelistSystem = default!; public override void Initialize() { @@ -26,18 +27,20 @@ public sealed class DevourSystem : SharedDevourSystem var ichorInjection = new Solution(component.Chemical, component.HealRate); - if (component.FoodPreference == FoodPreference.All || - (component.FoodPreference == FoodPreference.Humanoid && HasComp(args.Args.Target))) + // Grant ichor if the devoured thing meets the dragon's food preference + if (args.Args.Target != null && _entityWhitelistSystem.IsWhitelistPassOrNull(component.FoodPreferenceWhitelist, (EntityUid)args.Args.Target)) { - if (component.ShouldStoreDevoured && args.Args.Target is not null) - { - ContainerSystem.Insert(args.Args.Target.Value, component.Stomach); - } _bloodstreamSystem.TryAddToChemicals(uid, ichorInjection); } + // If the devoured thing meets the stomach whitelist criteria, add it to the stomach + if (args.Args.Target != null && _entityWhitelistSystem.IsWhitelistPass(component.StomachStorageWhitelist, (EntityUid)args.Args.Target)) + { + ContainerSystem.Insert(args.Args.Target.Value, component.Stomach); + } //TODO: Figure out a better way of removing structures via devour that still entails standing still and waiting for a DoAfter. Somehow. - //If it's not human, it must be a structure + //If it's not alive, it must be a structure. + // Delete if the thing isn't in the stomach storage whitelist (or the stomach whitelist is null/empty) else if (args.Args.Target != null) { QueueDel(args.Args.Target.Value); @@ -48,7 +51,7 @@ public sealed class DevourSystem : SharedDevourSystem private void OnGibContents(EntityUid uid, DevourerComponent component, ref BeingGibbedEvent args) { - if (!component.ShouldStoreDevoured) + if (component.StomachStorageWhitelist == null) return; // For some reason we have two different systems that should handle gibbing, diff --git a/Content.Shared/Devour/Components/DevourerComponent.cs b/Content.Shared/Devour/Components/DevourerComponent.cs index fbeec28ca5..d110175951 100644 --- a/Content.Shared/Devour/Components/DevourerComponent.cs +++ b/Content.Shared/Devour/Components/DevourerComponent.cs @@ -12,19 +12,19 @@ namespace Content.Shared.Devour.Components; [Access(typeof(SharedDevourSystem))] public sealed partial class DevourerComponent : Component { - [DataField("devourAction", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string? DevourAction = "ActionDevour"; - [DataField("devourActionEntity")] + [DataField] public EntityUid? DevourActionEntity; - [ViewVariables(VVAccess.ReadWrite), DataField("soundDevour")] + [DataField] public SoundSpecifier? SoundDevour = new SoundPathSpecifier("/Audio/Effects/demon_consume.ogg") { Params = AudioParams.Default.WithVolume(-3f), }; - [DataField("devourTime")] + [DataField] public float DevourTime = 3f; /// @@ -33,10 +33,10 @@ public sealed partial class DevourerComponent : Component /// NOTE: original intended design was to increase this proportionally with damage thresholds, but those proved quite difficult to get consistently. right now it devours the structure at a fixed timer. /// /// - [DataField("structureDevourTime")] + [DataField] public float StructureDevourTime = 10f; - [ViewVariables(VVAccess.ReadWrite), DataField("soundStructureDevour")] + [DataField] public SoundSpecifier? SoundStructureDevour = new SoundPathSpecifier("/Audio/Machines/airlock_creaking.ogg") { Params = AudioParams.Default.WithVolume(-3f), @@ -47,10 +47,10 @@ public sealed partial class DevourerComponent : Component /// public Container Stomach = default!; - [ViewVariables(VVAccess.ReadWrite), DataField("shouldStoreDevoured")] - public bool ShouldStoreDevoured = true; - - [ViewVariables(VVAccess.ReadWrite), DataField("whitelist")] + /// + /// Determines what things the devourer can consume. + /// + [DataField] public EntityWhitelist? Whitelist = new() { Components = new[] @@ -59,22 +59,31 @@ public sealed partial class DevourerComponent : Component } }; + /// + /// Determines what things end up in the dragon's stomach if they eat it. + /// If it isn't in the whitelist, it's deleted. + /// + [DataField] + public EntityWhitelist? StomachStorageWhitelist; + + /// + /// Determine's the dragon's food preference. If the eaten thing matches, + /// it is rewarded with the reward chemical. If null, all food is fine. + /// + [DataField] + public EntityWhitelist? FoodPreferenceWhitelist; + /// /// The chemical ID injected upon devouring /// - [DataField("chemical", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string Chemical = "Ichor"; /// /// The amount of ichor injected per devour /// - [ViewVariables(VVAccess.ReadWrite), DataField("healRate")] + [DataField] public float HealRate = 15f; - /// - /// The favorite food not only feeds you, but also heals - /// - [DataField("foodPreference")] - public FoodPreference FoodPreference = FoodPreference.All; } diff --git a/Content.Shared/Devour/SharedDevourSystem.cs b/Content.Shared/Devour/SharedDevourSystem.cs index 14047fba7d..702884c984 100644 --- a/Content.Shared/Devour/SharedDevourSystem.cs +++ b/Content.Shared/Devour/SharedDevourSystem.cs @@ -87,9 +87,3 @@ public sealed partial class DevourActionEvent : EntityTargetActionEvent { } [Serializable, NetSerializable] public sealed partial class DevourDoAfterEvent : SimpleDoAfterEvent { } -[Serializable, NetSerializable] -public enum FoodPreference : byte -{ - Humanoid = 0, - All = 1 -} diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml index fc2dddb23d..0d6489744f 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -136,8 +136,12 @@ Piercing: 15 Slash: 15 - type: Devourer - foodPreference: Humanoid - shouldStoreDevoured: true + foodPreferenceWhitelist: + components: + - HumanoidAppearance + stomachStorageWhitelist: + components: + - MobState chemical: Ichor healRate: 7.5 whitelist: