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()
{
var ichorInjection = new Solution(component.Chemical, component.HealRate);
- if (component.FoodPreference == FoodPreference.All ||
- (component.FoodPreference == FoodPreference.Humanoid && HasComp<HumanoidAppearanceComponent>(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);
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,
[Access(typeof(SharedDevourSystem))]
public sealed partial class DevourerComponent : Component
{
- [DataField("devourAction", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
+ [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
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;
/// <summary>
/// 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.
/// </remarks>
/// </summary>
- [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),
/// </summary>
public Container Stomach = default!;
- [ViewVariables(VVAccess.ReadWrite), DataField("shouldStoreDevoured")]
- public bool ShouldStoreDevoured = true;
-
- [ViewVariables(VVAccess.ReadWrite), DataField("whitelist")]
+ /// <summary>
+ /// Determines what things the devourer can consume.
+ /// </summary>
+ [DataField]
public EntityWhitelist? Whitelist = new()
{
Components = new[]
}
};
+ /// <summary>
+ /// Determines what things end up in the dragon's stomach if they eat it.
+ /// If it isn't in the whitelist, it's deleted.
+ /// </summary>
+ [DataField]
+ public EntityWhitelist? StomachStorageWhitelist;
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ [DataField]
+ public EntityWhitelist? FoodPreferenceWhitelist;
+
/// <summary>
/// The chemical ID injected upon devouring
/// </summary>
- [DataField("chemical", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
+ [DataField(customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
public string Chemical = "Ichor";
/// <summary>
/// The amount of ichor injected per devour
/// </summary>
- [ViewVariables(VVAccess.ReadWrite), DataField("healRate")]
+ [DataField]
public float HealRate = 15f;
- /// <summary>
- /// The favorite food not only feeds you, but also heals
- /// </summary>
- [DataField("foodPreference")]
- public FoodPreference FoodPreference = FoodPreference.All;
}