diff --git a/Content.Shared/_Impstation/RemoveComp/RemoveCompComponent.cs b/Content.Shared/_Impstation/RemoveComp/RemoveCompComponent.cs new file mode 100644 index 00000000000000..3e36e4ec14f8d8 --- /dev/null +++ b/Content.Shared/_Impstation/RemoveComp/RemoveCompComponent.cs @@ -0,0 +1,20 @@ +using Content.Shared.Whitelist; + +namespace Content.Shared._Impstation.RemoveComp +{ + /// + /// If there is any other possible way to do what you want to do, reconsider using this. + /// Takes a list of components and removes them from the entity. + /// Necessary for removing components from entities which are parented. + /// + [RegisterComponent, AutoGenerateComponentState, Access(typeof(RemoveCompSystem))] + public sealed partial class RemoveCompComponent : Component + { + /// + /// The list of components to be removed. + /// I must reiterate, exhaust all other options before using this component. + /// + [DataField("unwantedComponents"), AutoNetworkedField] + public EntityWhitelist UnwantedComponents = new(); + } +} diff --git a/Content.Shared/_Impstation/RemoveComp/SharedRemoveCompSystem.cs b/Content.Shared/_Impstation/RemoveComp/SharedRemoveCompSystem.cs new file mode 100644 index 00000000000000..f66bae78d4ae66 --- /dev/null +++ b/Content.Shared/_Impstation/RemoveComp/SharedRemoveCompSystem.cs @@ -0,0 +1,82 @@ +using Content.Shared.Whitelist; +using Content.Shared.IdentityManagement; +using Robust.Shared.Timing; +using Content.Shared.GameTicking; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Content.Shared._Impstation.RemoveComp; + +public sealed class RemoveCompSystem : EntitySystem +{ + [Dependency] private readonly EntityWhitelistSystem _whitelist = default!; + [Dependency] private readonly IGameTiming _gameTiming = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + } + + + /// + /// complains if an entity has this but it is either defined wrong or undefined, and if not, runs RemoveComponents + /// + /// + /// + /// + /// + private void OnMapInit(EntityUid uid, RemoveCompComponent comp, ref MapInitEvent args) + { + // log a message and quit if RequireAll is false. + if (!comp.UnwantedComponents.RequireAll) + { + Log.Error("RemoveComp only supports RequireAll = true!"); + return; + } + + // if there are no components listed, throw an "improperly defined" error. + if (comp.UnwantedComponents.Components == null) + { + Log.Error($"RemoveComp on {ToPrettyString(Identity.Entity(uid, EntityManager))} must use at least 1 component as a filter in UnwantedComponents!"); + throw new ArgumentException($"RemoveComp on {ToPrettyString(Identity.Entity(uid, EntityManager))} must use at least 1 component as a filter in UnwantedComponents!"); + } + + // if the blacklist contains a component that the entity does not possess, throw an error. + if (_whitelist.IsBlacklistFail(comp.UnwantedComponents, uid)) + { + Log.Error($"RemoveComp on {ToPrettyString(Identity.Entity(uid, EntityManager))} is trying to remove a component that does not exist."); + throw new ArgumentException($"RemoveComp on {ToPrettyString(Identity.Entity(uid, EntityManager))} is trying to remove a component that does not exist."); + } + + // if no errors are detected, run RemoveComponents() and then delete yourself. + else + { + RemoveComponents(uid, comp); + EntityManager.RemoveComponent(uid); + } + } + + // This is unfortunately something I have to do because we do not have a team big enough to refactor stuff. Don't be like me. + /// + /// Removes components from the list until there are no components left to remove. + /// + /// + /// + private void RemoveComponents(EntityUid uid, RemoveCompComponent comp) + { + // if the entity has any of the components on the list, + if (_whitelist.IsBlacklistPass(comp.UnwantedComponents, uid)) + { + // loop through each component in the list, + for (var i = 0; i < comp.UnwantedComponents.Components!.Length; i++) + { + // set a variable to return the type of each component, and... + var compType = EntityManager.ComponentFactory.GetRegistration(comp.UnwantedComponents.Components[i]).Type; + + // remove the offending components. + EntityManager.RemoveComponent(uid, compType); + } + } + } +} diff --git a/Resources/Prototypes/_Impstation/Entities/Mobs/Species/decapoid.yml b/Resources/Prototypes/_Impstation/Entities/Mobs/Species/decapoid.yml index 33af08c64109c2..9aeb91039da1d3 100644 --- a/Resources/Prototypes/_Impstation/Entities/Mobs/Species/decapoid.yml +++ b/Resources/Prototypes/_Impstation/Entities/Mobs/Species/decapoid.yml @@ -154,6 +154,11 @@ - type: Puller needsHands: false # they drag with the claw, or their back legs applySpeedModifier: false # they're strong as fuck. also i made this variable just for them. + - type: RemoveComp # this solution sucks but what are u gonna do shrug + unwantedComponents: + requireAll: true + components: + - InjectableSolution - type: Inventory speciesId: decapoid templateId: decapoid diff --git a/Resources/Prototypes/_Impstation/Entities/Objects/Decapoid/decapoid_items.yml b/Resources/Prototypes/_Impstation/Entities/Objects/Decapoid/decapoid_items.yml index 6d742f9c812eb7..ed8e131a0193e6 100644 --- a/Resources/Prototypes/_Impstation/Entities/Objects/Decapoid/decapoid_items.yml +++ b/Resources/Prototypes/_Impstation/Entities/Objects/Decapoid/decapoid_items.yml @@ -75,7 +75,7 @@ - type: entity name: vaporizer - parent: ClothingMaskGas + parent: ClothingMaskPullableBase id: DecapoidBreathingApparatus description: 'A neck-mounted breathing apparatus for Decapoids. Moistens your gills, if you have them. Also functions as a brain-to-voice translator.' components: @@ -86,6 +86,8 @@ tags: - Vaporizer - BreathMask + - WhitelistChameleon + - GasMask - type: Clothing quickEquip: true slots: @@ -100,6 +102,7 @@ - type: HideLayerClothing slots: - Snout + hideOnToggle: true - type: SpeechSound speechSounds: Decapoid speechVerb: Robotic diff --git a/Resources/ServerInfo/_Impstation/Guidebook/Mobs/Decapoid.xml b/Resources/ServerInfo/_Impstation/Guidebook/Mobs/Decapoid.xml index bea17575f58987..c24f00c1c6ccb1 100644 --- a/Resources/ServerInfo/_Impstation/Guidebook/Mobs/Decapoid.xml +++ b/Resources/ServerInfo/_Impstation/Guidebook/Mobs/Decapoid.xml @@ -4,14 +4,14 @@ - + [color=red]Caution! This species has several SEVERELY limiting game mechanics and is only recommended for highly experienced players. Some jobs and tasks may be difficult or impossible to perform by yourself with only one hand, and you will be limited to melee combat only.[/color] - + ## Physiology Decapoids are a recent addition to Nanotrasen's list of accepted species, and are one of the more unusual species NT has encountered. [color=#1e90ff]Their carapace is uniquely adapted for extreme pressures, allowing them to traverse space without the aid of a pressure suit.[/color] Perhaps as a result of this, [color=#1e90ff]they have developed an affinity for microgravity - they are capable of moving considerably faster in it.[/color] - - This enormous benefit comes with a laundry list of detriments, however, when it comes to operating aboard a Nanotrasen vessel. Due to the weight of their carapace, [color=#ffa500]they move approximately 20% slower than most NT-accepted species,[/color] and their unique configuration of lower limbs makes it [color=#ffa500]impossible for them to wear shoes.[/color] - + + This enormous benefit comes with a laundry list of detriments, however, when it comes to operating aboard a Nanotrasen vessel. Due to the weight of their carapace, [color=#ffa500]they move approximately 20% slower than most NT-accepted species,[/color] and their unique configuration of lower limbs makes it [color=#ffa500]impossible for them to wear shoes.[/color] + Their major claw is enormous and somewhat unwieldy. [color=#ffa500]This left "hand" is useless for most of the tasks one might use a hand for,[/color] and functions primarily as a [color=#1e90ff]prying tool and cutting tool, though it can also serve as a competent melee weapon and shield.[/color] Their minor claw isn't much more dextrous, and while its smaller size allows it to manipulate most tools, [color=#ffa500]Decapoids are incapable of efficiently using firearms of any kind.[/color] It's not all bad, however - Their abundance of limbs allows them to [color=#1e90ff]drag objects without the use of their claws,[/color] and their immense physical strength [color=#1e90ff]negates the normal speed penalty for dragging.[/color] ## Breathing Requirements @@ -26,17 +26,19 @@ This is not the only feature their aquatic history has left them, however - Decapoids do not possess vocal cords that would function in a gaseous atmosphere. [color=#ffa500]They are incapable of normal speech.[/color] This deficit is fortunately mitigated by their [color=#1e90ff]Vaporizers,[/color] which plug directly into their nervous system and [color=#1e90ff]translate their brainwaves into sound directly.[/color] The NT Board of Directors would like to once again stress that [color=red][bold]Decapoids should avoid losing these devices at all costs, as they cannot be replaced.[/color][/bold] In the event of the loss of these items, [color=#1e90ff]reach out to the Atmos team immediately to be supplied with water vapor. Decapoids are capable of using any NT-provided internals mask as a stopgap measure, [/color]but [color=#ffa500]they will be unable to speak while doing so. [/color][color=red]Keep this in mind.[/color] - + ## Damage A Decapoid's carapace is extremely sturdy, and capable of deflecting blades and bullets alike, but relatively brittle. As a result, they take [color=#1e90ff]30% less damage from Slashing and Piercing,[/color] but [color=#ffa500]20% more damage from Blunt.[/color] Their particular adaptations render them [color=#1e90ff]fully immune to Cold damage and barotrauma from spacing,[/color] but more sensitive to high temperatures - [color=#ffa500]They take 50% more damage from Heat.[/color] - + + Their thick, spaceproof chitin is not conducive to some methods of healing typically used on humanoids. [color=#ffa500]They cannot be injected with fluids,[/color] as syringes and hyposprays will simply fail to penetrate their carapace. As such, it is recommended that all NT Medical staff familiarize themselves with both pillmaking and the station's Cryo Pods. + Their blood, similarly to that of Arachnids, uses a copper-based respiratory protein, and as such [color=#ffa500]can only be metabolized from copper, not iron.[/color] - + ## Decapoid Naming Conventions and Culture - Decapoids are born in broods of (almost always) exactly thirty individuals. The Empire has developed a caste system based on the order in which these brood eggs hatch, with the oldest among a brood being ranked highest. - + Decapoids are born in broods of (almost always) exactly thirty individuals. The Empire has developed a caste system based on the order in which these brood eggs hatch, with the oldest among a brood being ranked highest. + As a result, the structure of their names is very simple - Decapoid names consist of a "brood name," similar to a Human last name, which indicates familial relation, followed by the ordinal number of their rank. Some Decapoids who are estranged from the Empire for one reason or another may choose to go by a mononym, rather than display their rank. - + Brood names are written in a rough transliteration of native Decapoid, and thus only use voiceless consonants (Ch, K, P, S, Sh, T, Th,) with an apostrophe marking a glottal stop. - [color=#449944]Acceptable:[/color] U'uqet, Sixth - [color=#449944]Acceptable:[/color] 'Uut, Seventeenth