diff --git a/Content.Server/Interaction/InteractionSystem.cs b/Content.Server/Interaction/InteractionSystem.cs index f21ee116ef..7aef3681c7 100644 --- a/Content.Server/Interaction/InteractionSystem.cs +++ b/Content.Server/Interaction/InteractionSystem.cs @@ -112,6 +112,10 @@ namespace Content.Server.Interaction // trigger dragdrops on the dropped entity RaiseLocalEvent(msg.Dropped, interactionArgs); + + if (interactionArgs.Handled) + return; + foreach (var dragDrop in AllComps(msg.Dropped)) { if (dragDrop.CanDrop(interactionArgs) && @@ -123,6 +127,10 @@ namespace Content.Server.Interaction // trigger dragdropons on the targeted entity RaiseLocalEvent(msg.Target, interactionArgs, false); + + if (interactionArgs.Handled) + return; + foreach (var dragDropOn in AllComps(msg.Target)) { if (dragDropOn.CanDragDropOn(interactionArgs) && diff --git a/Content.Server/Kitchen/Components/KitchenSpikeComponent.cs b/Content.Server/Kitchen/Components/KitchenSpikeComponent.cs index 11802518ee..66467dab1a 100644 --- a/Content.Server/Kitchen/Components/KitchenSpikeComponent.cs +++ b/Content.Server/Kitchen/Components/KitchenSpikeComponent.cs @@ -1,166 +1,38 @@ -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using Content.Server.Act; using Content.Server.Chat.Managers; -using Content.Server.DoAfter; +using Content.Server.Kitchen.EntitySystems; using Content.Server.Popups; using Content.Shared.DragDrop; -using Content.Shared.Interaction; using Content.Shared.Kitchen.Components; -using Content.Shared.MobState.Components; -using Content.Shared.Nutrition.Components; using Content.Shared.Popups; -using Robust.Shared.Audio; +using Robust.Shared.Analyzers; using Robust.Shared.GameObjects; -using Robust.Shared.IoC; using Robust.Shared.Localization; -using Robust.Shared.Player; +using System.Threading; namespace Content.Server.Kitchen.Components { - [RegisterComponent] - [ComponentReference(typeof(IActivate))] - public class KitchenSpikeComponent : SharedKitchenSpikeComponent, IActivate, ISuicideAct + [RegisterComponent, Friend(typeof(KitchenSpikeSystem))] + public class KitchenSpikeComponent : SharedKitchenSpikeComponent, ISuicideAct { - [Dependency] private readonly IEntityManager _entMan = default!; + public int MeatParts; + public string? MeatPrototype; - private int _meatParts; - private string? _meatPrototype; - private string _meatSource1p = "?"; - private string _meatSource0 = "?"; - private string _meatName = "?"; + // TODO: Spiking alive mobs? (Replace with uid) (deal damage to their limbs on spiking, kill on first butcher attempt?) + public string MeatSource1p = "?"; + public string MeatSource0 = "?"; + public string MeatName = "?"; - private List _beingButchered = new(); - - void IActivate.Activate(ActivateEventArgs eventArgs) - { - if (_meatParts == 0) - { - return; - } - _meatParts--; - - if (!string.IsNullOrEmpty(_meatPrototype)) - { - var meat = _entMan.SpawnEntity(_meatPrototype, _entMan.GetComponent(Owner).Coordinates); - _entMan.GetComponent(meat).EntityName = _meatName; - } - - if (_meatParts != 0) - { - eventArgs.User.PopupMessage(_meatSource1p); - } - else - { - UpdateAppearance(); - - eventArgs.User.PopupMessage(_meatSource0); - } - - return; - - } + // Prevents simultaneous spiking of two bodies (could be replaced with CancellationToken, but I don't see any situation where Cancel could be called) + public bool InUse; + // ECS this out!, when DragDropSystem and InteractionSystem refactored public override bool DragDropOn(DragDropEvent eventArgs) { - TrySpike(eventArgs.Dragged, eventArgs.User); return true; } - private void UpdateAppearance() - { - if (_entMan.TryGetComponent(Owner, out AppearanceComponent? appearance)) - { - appearance.SetData(KitchenSpikeVisuals.Status, (_meatParts > 0) ? KitchenSpikeStatus.Bloody : KitchenSpikeStatus.Empty); - } - } - - private bool Spikeable(EntityUid user, EntityUid victim, [NotNullWhen(true)] out SharedButcherableComponent? butcherable) - { - butcherable = null; - - if (_meatParts > 0) - { - Owner.PopupMessage(user, Loc.GetString("comp-kitchen-spike-deny-collect", ("this", Owner))); - return false; - } - - if (!_entMan.TryGetComponent(victim, out butcherable)) - { - Owner.PopupMessage(user, Loc.GetString("comp-kitchen-spike-deny-butcher", ("victim", victim), ("this", Owner))); - return false; - } - - if (butcherable.MeatPrototype == null) - return false; - - return true; - } - - public async void TrySpike(EntityUid victim, EntityUid user) - { - var victimUid = (EntityUid) victim; - if (_beingButchered.Contains(victimUid)) return; - - SharedButcherableComponent? butcherable; - - if (!Spikeable(user, victim, out butcherable)) - return; - - // Prevent dead from being spiked TODO: Maybe remove when rounds can be played and DOT is implemented - if (_entMan.TryGetComponent(victim, out var state) && - !state.IsDead()) - { - Owner.PopupMessage(user, Loc.GetString("comp-kitchen-spike-deny-not-dead", ("victim", victim))); - return; - } - - if (user != victim) - Owner.PopupMessage(victim, Loc.GetString("comp-kitchen-spike-begin-hook-victim", ("user", user), ("this", Owner))); - else - Owner.PopupMessage(victim, Loc.GetString("comp-kitchen-spike-begin-hook-self", ("this", Owner))); - - var doAfterSystem = EntitySystem.Get(); - - var doAfterArgs = new DoAfterEventArgs(user, SpikeDelay, default, victim) - { - BreakOnTargetMove = true, - BreakOnUserMove = true, - BreakOnDamage = true, - BreakOnStun = true, - NeedHand = true, - }; - - _beingButchered.Add(victimUid); - - var result = await doAfterSystem.WaitDoAfter(doAfterArgs); - - _beingButchered.Remove(victimUid); - - if (result == DoAfterStatus.Cancelled) - return; - - if (!Spikeable(user, victim, out butcherable)) - return; - - _meatPrototype = butcherable.MeatPrototype; - _meatParts = 5; - _meatSource1p = Loc.GetString("comp-kitchen-spike-remove-meat", ("victim", victim)); - _meatSource0 = Loc.GetString("comp-kitchen-spike-remove-meat-last", ("victim", victim)); - // TODO: This could stand to be improved somehow, but it'd require Name to be much 'richer' in detail than it presently is. - // But Name is RobustToolbox-level, so presumably it'd have to be done in some other way (interface???) - _meatName = Loc.GetString("comp-kitchen-spike-meat-name", ("victim", victim)); - - // TODO: Visualizer - UpdateAppearance(); - - Owner.PopupMessageEveryone(Loc.GetString("comp-kitchen-spike-kill", ("user", user), ("victim", victim))); - // TODO: Need to be able to leave them on the spike to do DoT, see ss13. - _entMan.DeleteEntity((EntityUid) victim); - - SoundSystem.Play(Filter.Pvs(Owner), SpikeSound.GetSound(), Owner); - } - + // ECS this out!, Handleable SuicideEvent? SuicideKind ISuicideAct.Suicide(EntityUid victim, IChatManager chat) { var othersMessage = Loc.GetString("comp-kitchen-spike-suicide-other", ("victim", victim)); diff --git a/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs b/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs new file mode 100644 index 0000000000..7f11412cbb --- /dev/null +++ b/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs @@ -0,0 +1,242 @@ +using Content.Server.DoAfter; +using Content.Server.Kitchen.Components; +using Content.Server.Nutrition.Components; +using Content.Server.Popups; +using Content.Shared.DragDrop; +using Content.Shared.Interaction; +using Content.Shared.MobState.Components; +using Content.Shared.Nutrition.Components; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Player; +using System; +using static Content.Shared.Kitchen.Components.SharedKitchenSpikeComponent; + +namespace Content.Server.Kitchen.EntitySystems +{ + internal class KitchenSpikeSystem : EntitySystem + { + [Dependency] private readonly PopupSystem _popupSystem = default!; + [Dependency] private readonly DoAfterSystem _doAfter = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInteractUsing); + SubscribeLocalEvent(OnInteractHand); + SubscribeLocalEvent(OnDragDrop); + + //DoAfter + SubscribeLocalEvent(OnSpikingFinished); + SubscribeLocalEvent(OnSpikingFail); + } + + private void OnSpikingFail(EntityUid uid, KitchenSpikeComponent component, SpikingFailEvent args) + { + component.InUse = false; + + if (EntityManager.TryGetComponent(args.VictimUid, out var butcherable)) + butcherable.BeingButchered = false; + } + + private void OnSpikingFinished(EntityUid uid, KitchenSpikeComponent component, SpikingFinishedEvent args) + { + component.InUse = false; + + if (EntityManager.TryGetComponent(args.VictimUid, out var butcherable)) + butcherable.BeingButchered = false; + + if (Spikeable(uid, args.UserUid, args.VictimUid, component, butcherable)) + { + Spike(uid, args.UserUid, args.VictimUid, component); + } + } + + private void OnDragDrop(EntityUid uid, KitchenSpikeComponent component, DragDropEvent args) + { + if(args.Handled) + return; + + if (!Spikeable(uid, args.User, args.Dragged, component)) + return; + + if (TrySpike(uid, args.User, args.Dragged, component)) + args.Handled = true; + } + private void OnInteractHand(EntityUid uid, KitchenSpikeComponent component, InteractHandEvent args) + { + if (args.Handled) + return; + + if (component.MeatParts > 0) { + _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-knife-needed"), uid, Filter.Entities(args.User)); + args.Handled = true; + } + } + + private void OnInteractUsing(EntityUid uid, KitchenSpikeComponent component, InteractUsingEvent args) + { + if (args.Handled) + return; + + if (TryGetPiece(uid, args.User, args.Used)) + args.Handled = true; + } + + private void Spike(EntityUid uid, EntityUid userUid, EntityUid victimUid, + KitchenSpikeComponent? component = null, SharedButcherableComponent? butcherable = null) + { + if (!Resolve(uid, ref component) || !Resolve(victimUid, ref butcherable)) + return; + + component.MeatPrototype = butcherable.MeatPrototype; + component.MeatParts = butcherable.Pieces; + + // This feels not okay, but entity is getting deleted on "Spike", for now... + component.MeatSource1p = Loc.GetString("comp-kitchen-spike-remove-meat", ("victim", victimUid)); + component.MeatSource0 = Loc.GetString("comp-kitchen-spike-remove-meat-last", ("victim", victimUid)); + component.MeatName = Loc.GetString("comp-kitchen-spike-meat-name", ("victim", victimUid)); + + UpdateAppearance(uid, null, component); + + _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-kill", ("user", userUid), ("victim", victimUid)), uid, Filter.Pvs(userUid)); + + // THE WHAT? + // TODO: Need to be able to leave them on the spike to do DoT, see ss13. + EntityManager.QueueDeleteEntity(victimUid); + + SoundSystem.Play(Filter.Pvs(uid), component.SpikeSound.GetSound(), uid); + } + + private bool TryGetPiece(EntityUid uid, EntityUid user, EntityUid used, + KitchenSpikeComponent? component = null, UtensilComponent? utensil = null) + { + if (!Resolve(uid, ref component) || component.MeatParts == 0) + return false; + + // Is using knife + if (!Resolve(used, ref utensil, false) || (utensil.Types & UtensilType.Knife) == 0) + { + return false; + } + + component.MeatParts--; + + if (!string.IsNullOrEmpty(component.MeatPrototype)) + { + var meat = EntityManager.SpawnEntity(component.MeatPrototype, Transform(uid).Coordinates); + MetaData(meat).EntityName = component.MeatName; + } + + if (component.MeatParts != 0) + { + _popupSystem.PopupEntity(component.MeatSource1p, uid, Filter.Entities(user)); + } + else + { + UpdateAppearance(uid, null, component); + _popupSystem.PopupEntity(component.MeatSource0, uid, Filter.Entities(user)); + } + + return true; + } + + private void UpdateAppearance(EntityUid uid, AppearanceComponent? appearance = null, KitchenSpikeComponent? component = null) + { + if (!Resolve(uid, ref component, ref appearance, false)) + return; + + appearance.SetData(KitchenSpikeVisuals.Status, (component.MeatParts > 0) ? KitchenSpikeStatus.Bloody : KitchenSpikeStatus.Empty); + } + + private bool Spikeable(EntityUid uid, EntityUid userUid, EntityUid victimUid, + KitchenSpikeComponent? component = null, SharedButcherableComponent? butcherable = null) + { + if (!Resolve(uid, ref component)) + return false; + + if (component.MeatParts > 0) + { + _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-deny-collect", ("this", uid)), uid, Filter.Entities(userUid)); + return false; + } + + if (!Resolve(victimUid, ref butcherable, false) || butcherable.MeatPrototype == null) + { + _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-deny-butcher", ("victim", victimUid), ("this", uid)), victimUid, Filter.Entities(userUid)); + return false; + } + + return true; + } + + public bool TrySpike(EntityUid uid, EntityUid userUid, EntityUid victimUid, KitchenSpikeComponent? component = null, + SharedButcherableComponent? butcherable = null, MobStateComponent? mobState = null) + { + if (!Resolve(uid, ref component) || component.InUse || + !Resolve(victimUid, ref butcherable) || butcherable.BeingButchered) + return false; + + // THE WHAT? (again) + // Prevent dead from being spiked TODO: Maybe remove when rounds can be played and DOT is implemented + if (Resolve(victimUid, ref mobState, false) && + !mobState.IsDead()) + { + _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-deny-not-dead", ("victim", victimUid)), + victimUid, Filter.Entities(userUid)); + return true; + } + + if (userUid != victimUid) + { + _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-begin-hook-victim", ("user", userUid), ("this", uid)), victimUid, Filter.Entities(victimUid)); + } + // TODO: make it work when SuicideEvent is implemented + // else + // _popupSystem.PopupEntity(Loc.GetString("comp-kitchen-spike-begin-hook-self", ("this", uid)), victimUid, Filter.Pvs(uid)); // This is actually unreachable and should be in SuicideEvent + + butcherable.BeingButchered = true; + component.InUse = true; + + var doAfterArgs = new DoAfterEventArgs(userUid, component.SpikeDelay, default, uid) + { + BreakOnTargetMove = true, + BreakOnUserMove = true, + BreakOnDamage = true, + BreakOnStun = true, + NeedHand = true, + TargetFinishedEvent = new SpikingFinishedEvent(userUid, victimUid), + TargetCancelledEvent = new SpikingFailEvent(victimUid) + }; + + _doAfter.DoAfter(doAfterArgs); + + return true; + } + + private class SpikingFinishedEvent : EntityEventArgs + { + public EntityUid VictimUid; + public EntityUid UserUid; + + public SpikingFinishedEvent(EntityUid userUid, EntityUid victimUid) + { + UserUid = userUid; + VictimUid = victimUid; + } + } + + private class SpikingFailEvent : EntityEventArgs + { + public EntityUid VictimUid; + + public SpikingFailEvent(EntityUid victimUid) + { + VictimUid = victimUid; + } + } + } +} diff --git a/Content.Shared/DragDrop/IDraggable.cs b/Content.Shared/DragDrop/IDraggable.cs index c98e66d71e..276abfa58c 100644 --- a/Content.Shared/DragDrop/IDraggable.cs +++ b/Content.Shared/DragDrop/IDraggable.cs @@ -56,7 +56,7 @@ namespace Content.Shared.DragDrop } } - public class StartDragDropEvent : EntityEventArgs + public class StartDragDropEvent : HandledEntityEventArgs { /// /// Entity doing the drag and drop. diff --git a/Content.Shared/Kitchen/Components/SharedKitchenSpikeComponent.cs b/Content.Shared/Kitchen/Components/SharedKitchenSpikeComponent.cs index 283eb976e2..e8efaff81f 100644 --- a/Content.Shared/Kitchen/Components/SharedKitchenSpikeComponent.cs +++ b/Content.Shared/Kitchen/Components/SharedKitchenSpikeComponent.cs @@ -16,11 +16,11 @@ namespace Content.Shared.Kitchen.Components [ViewVariables] [DataField("delay")] - protected float SpikeDelay = 12.0f; + public float SpikeDelay = 12.0f; [ViewVariables(VVAccess.ReadWrite)] [DataField("sound")] - protected SoundSpecifier SpikeSound = new SoundPathSpecifier("/Audio/Effects/Fluids/splat.ogg"); + public SoundSpecifier SpikeSound = new SoundPathSpecifier("/Audio/Effects/Fluids/splat.ogg"); bool IDragDropOn.CanDragDropOn(DragDropEvent eventArgs) { diff --git a/Content.Shared/Nutrition/Components/SharedButcherableComponent.cs b/Content.Shared/Nutrition/Components/SharedButcherableComponent.cs index 11a6bd4661..75455b9d16 100644 --- a/Content.Shared/Nutrition/Components/SharedButcherableComponent.cs +++ b/Content.Shared/Nutrition/Components/SharedButcherableComponent.cs @@ -1,6 +1,8 @@ using Content.Shared.DragDrop; using Robust.Shared.GameObjects; +using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager.Attributes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.ViewVariables; namespace Content.Shared.Nutrition.Components @@ -13,13 +15,23 @@ namespace Content.Shared.Nutrition.Components { public override string Name => "Butcherable"; + //TODO: List for sub-products like animal-hides, organs and etc? [ViewVariables] - public string? MeatPrototype => _meatPrototype; + [DataField("meat", customTypeSerializer:typeof(PrototypeIdSerializer))] + public string MeatPrototype = "FoodMeat"; [ViewVariables] - [DataField("meat")] - private string? _meatPrototype; + [DataField("pieces")] + public int Pieces = 5; + /// + /// Prevents butchering same entity on two and more spikes simultaneously and multiple doAfters on the same Spike + /// + public bool BeingButchered; + + // TODO: ECS this out!, my guess CanDropEvent should be client side only and then "ValidDragDrop" in the DragDropSystem needs a little touch + // But this may lead to creating client-side systems for every Draggable component subbed to CanDrop. Actually those systems could control + // CanDropOn behaviors as well (IDragDropOn) bool IDraggable.CanDrop(CanDropEvent args) { return true; diff --git a/Resources/Locale/en-US/kitchen/components/kitchen-spike-component.ftl b/Resources/Locale/en-US/kitchen/components/kitchen-spike-component.ftl index d0d45be805..6b9d2f3c6c 100644 --- a/Resources/Locale/en-US/kitchen/components/kitchen-spike-component.ftl +++ b/Resources/Locale/en-US/kitchen/components/kitchen-spike-component.ftl @@ -10,6 +10,7 @@ comp-kitchen-spike-kill = { CAPITALIZE(THE($user)) } has forced { THE($victim) } comp-kitchen-spike-suicide-other = { CAPITALIZE(THE($victim)) } has thrown themselves on a meat spike! comp-kitchen-spike-suicide-self = You throw yourself on a meat spike! +comp-kitchen-spike-knife-needed = You need a knife to do this. comp-kitchen-spike-remove-meat = You remove some meat from { THE($victim) }. comp-kitchen-spike-remove-meat-last = You remove the last piece of meat from { THE($victim) }! diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 419c307974..da04a4edf4 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -36,6 +36,9 @@ normal: bat crit: dead dead: dead + - type: Butcherable + meat: FoodMeat + pieces: 1 - type: entity name: bee @@ -100,6 +103,9 @@ normal: chicken-0 crit: dead-0 dead: dead-0 + - type: Butcherable + meat: FoodMeatChicken + pieces: 1 - type: entity name: butterfly @@ -196,6 +202,9 @@ targetSolution: udder quantity: 25 updateRate: 30 + - type: Butcherable + meat: FoodMeat + pieces: 5 - type: entity name: crab @@ -230,6 +239,9 @@ crit: dead dead: dead - type: AsteroidRockVisualizer + - type: Butcherable + meat: FoodMeatCrab + pieces: 2 - type: entity name: goat @@ -249,6 +261,9 @@ normal: goat crit: dead dead: dead + - type: Butcherable + meat: FoodMeat + pieces: 4 # Note that we gotta make this bitch vomit someday when you feed it anthrax or sumthin. Needs to be a small item thief too and aggressive if attacked. - type: entity @@ -269,6 +284,9 @@ normal: goose crit: dead dead: dead + - type: Butcherable + meat: FoodMeatChicken + pieces: 2 - type: entity name: gorilla @@ -302,6 +320,9 @@ normal: crawling crit: dead dead: dead + - type: Butcherable + meat: FoodMeat + pieces: 4 - type: entity name: kangaroo @@ -370,6 +391,9 @@ - type: FireVisualizer sprite: Mobs/Effects/onfire.rsi normalState: Monkey_burning + - type: Butcherable + meat: FoodMeat + pieces: 3 - type: MonkeyAccent - type: entity @@ -432,6 +456,9 @@ reagents: - ReagentId: Nutriment Quantity: 5 + - type: Butcherable + meat: FoodMeat + pieces: 1 - type: ReplacementAccent accent: mouse @@ -512,6 +539,9 @@ normal: parrot crit: dead dead: dead + - type: Butcherable + meat: FoodMeat + pieces: 1 - type: entity name: penguin @@ -545,6 +575,9 @@ normal: penguin crit: penguin_dead dead: penguin_dead + - type: Butcherable + meat: FoodMeatPenguin + pieces: 3 - type: entity name: snake @@ -581,6 +614,9 @@ # looks stupid, Rotation visualizer for now # dead: dead # crit: dead + - type: Butcherable + meat: FoodMeat + pieces: 1 # Code unique spider prototypes or combine them all into one spider and get a # random sprite state when you spawn it. @@ -616,3 +652,6 @@ normal: tarantula crit: tarantula_dead dead: tarantula_dead + - type: Butcherable + meat: FoodMeatSpider + pieces: 2 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml index ebf630a92d..7039f3956f 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml @@ -42,6 +42,9 @@ normal: alive crit: crit dead: dead + - type: Butcherable + meat: FoodMeat # TODO: CrapMeat or FishMeat + pieces: 2 - type: entity name: magicarp diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml index 38ea01d948..b1dc2e1112 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/pets.yml @@ -33,6 +33,9 @@ normal: corgi crit: corgi_dead dead: corgi_dead + - type: Butcherable + meat: FoodMeat + pieces: 3 - type: ReplacementAccent accent: dog @@ -87,6 +90,9 @@ normal: cat crit: cat_dead dead: cat_dead + - type: Butcherable + meat: FoodMeat + pieces: 2 - type: ReplacementAccent accent: cat @@ -163,3 +169,6 @@ normal: sloth crit: sloth_dead dead: sloth_dead + - type: Butcherable + meat: FoodMeat + pieces: 3 diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml index 195c661e89..9771436550 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml @@ -116,8 +116,6 @@ - type: Buckle - type: Recyclable safe: false - - type: Butcherable - meat: FoodMeat - type: StandingState - type: Alerts diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index 166aae1ccc..ffe9f189eb 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -60,3 +60,6 @@ crit: crit dead: dead - type: Puller + - type: Butcherable + meat: FoodMeatXeno + pieces: 5 diff --git a/Resources/Prototypes/Entities/Structures/meat_spike.yml b/Resources/Prototypes/Entities/Structures/meat_spike.yml index da8b281845..0d82a0df32 100644 --- a/Resources/Prototypes/Entities/Structures/meat_spike.yml +++ b/Resources/Prototypes/Entities/Structures/meat_spike.yml @@ -40,4 +40,3 @@ states: enum.KitchenSpikeStatus.Empty: spike enum.KitchenSpikeStatus.Bloody: spikebloody -