From 9c23b4a6d8d3188b8027ae5c0042a31455e31e03 Mon Sep 17 00:00:00 2001 From: pathetic meowmeow Date: Sun, 8 Feb 2026 13:30:09 -0500 Subject: [PATCH] Documents all the public APIs for Nubody & markings code (#42857) --- Content.Client/Humanoid/MarkingsViewModel.cs | 117 +++++++++++++++++- Content.Shared/Body/BodyComponent.cs | 5 + .../Body/BodySystem.Compatibility.cs | 11 ++ Content.Shared/Body/BodySystem.Relay.cs | 18 ++- Content.Shared/Body/BodySystem.cs | 11 ++ Content.Shared/Body/GibbableOrganComponent.cs | 5 + Content.Shared/Body/HandOrganComponent.cs | 9 ++ Content.Shared/Body/InitialBodyComponent.cs | 4 + Content.Shared/Body/OrganComponent.cs | 4 + .../Body/SharedVisualBodySystem.Modifiers.cs | 47 +++++++ Content.Shared/Body/SharedVisualBodySystem.cs | 17 +-- Content.Shared/Body/VisualBodyComponent.cs | 3 + Content.Shared/Body/VisualOrganComponent.cs | 13 +- .../Body/VisualOrganMarkingsComponent.cs | 7 +- .../Humanoid/Markings/MarkingManager.cs | 48 ++++++- 15 files changed, 297 insertions(+), 22 deletions(-) diff --git a/Content.Client/Humanoid/MarkingsViewModel.cs b/Content.Client/Humanoid/MarkingsViewModel.cs index 6305d5eea51..ed62c3d62d7 100644 --- a/Content.Client/Humanoid/MarkingsViewModel.cs +++ b/Content.Client/Humanoid/MarkingsViewModel.cs @@ -7,6 +7,9 @@ using Robust.Shared.Utility; namespace Content.Client.Humanoid; +/// +/// View model for UIs manipulating a set of markings, responsible for applying markings logic and keeping state synchronized. +/// public sealed class MarkingsViewModel { [Dependency] private readonly MarkingManager _marking = default!; @@ -14,6 +17,10 @@ public sealed class MarkingsViewModel private bool _enforceLimits = true; + /// + /// Whether the markings view model will enforce limitations on how many markings an organ can have + /// + /// public bool EnforceLimits { get => _enforceLimits; @@ -29,6 +36,10 @@ public sealed class MarkingsViewModel private bool _enforceGroupAndSexRestrictions = true; + /// + /// Whether the markings view model will enforce restrictions on the group and sex of markings for an organ + /// + /// public bool EnforceGroupAndSexRestrictions { get => _enforceGroupAndSexRestrictions; @@ -44,10 +55,18 @@ public sealed class MarkingsViewModel private bool AnyEnforcementsLifted => !_enforceLimits || !_enforceGroupAndSexRestrictions; + /// + /// Raised whenever the view model is enforcing a different set of constraints on possible markings than before + /// + /// + /// public event Action? EnforcementsChanged; private Dictionary, OrganProfileData> _organProfileData = new(); + /// + /// The organ profile data this view model is concerned with. + /// public Dictionary, OrganProfileData> OrganProfileData { get => _organProfileData; @@ -58,6 +77,10 @@ public sealed class MarkingsViewModel } } + /// + /// Sets the sex of all organ profiles in the view model. + /// + /// The new sex public void SetOrganSexes(Sex sex) { foreach (var (organ, data) in _organProfileData) @@ -67,6 +90,10 @@ public sealed class MarkingsViewModel OrganProfileDataChanged?.Invoke(true); } + /// + /// Sets the skin color of all organ profiles in the view model. + /// + /// The new skin color public void SetOrganSkinColor(Color skinColor) { foreach (var (organ, data) in _organProfileData) @@ -76,6 +103,10 @@ public sealed class MarkingsViewModel OrganProfileDataChanged?.Invoke(false); } + /// + /// Sets the eye color of all organ profiles in the view model. + /// + /// The new eye color public void SetOrganEyeColor(Color eyeColor) { foreach (var (organ, data) in _organProfileData) @@ -85,10 +116,21 @@ public sealed class MarkingsViewModel OrganProfileDataChanged?.Invoke(false); } + /// + /// Raised whenever the organ profile data changes. + /// The boolean value represents whether the set of possible markings may have changed. + /// + /// + /// + /// + /// public event Action? OrganProfileDataChanged; private Dictionary, Dictionary>> _markings = new(); + /// + /// The currently applied set of markings + /// public Dictionary, Dictionary>> Markings { get => _markings; @@ -104,12 +146,21 @@ public sealed class MarkingsViewModel } } + /// + /// Raised whenever the set of markings has fully changed and requires a UI reload + /// public event Action? MarkingsReset; + /// + /// Raised whenever a specific layer's markings have changed + /// public event Action, HumanoidVisualLayers>? MarkingsChanged; private Dictionary, OrganMarkingData> _organData = new(); + /// + /// The organ marking data the view model is concerned with. + /// public Dictionary, OrganMarkingData> OrganData { @@ -125,15 +176,25 @@ public sealed class MarkingsViewModel } } + /// + /// Raised whenever the organ data within the view model is changed. + /// public event Action? OrganDataChanged; - private Dictionary, List> _previousColors = new(); + private readonly Dictionary, List> _previousColors = new(); public MarkingsViewModel() { IoCManager.InjectDependencies(this); } + /// + /// Returns whether the given marking is currently selected in the model + /// + /// The organ to check for the marking within + /// The layer within the organ to check for the marking within + /// The marking ID to check for + /// Whether the marking is currently present within the set of selected markings public bool IsMarkingSelected(ProtoId organ, HumanoidVisualLayers layer, ProtoId markingId) @@ -141,6 +202,11 @@ public sealed class MarkingsViewModel return GetMarking(organ, layer, markingId) is not null; } + /// + /// Returns whether the marking at the given location can have its color customized by the user + /// + /// + /// Whether the marking is capable of having its color customized by the user public bool IsMarkingColorCustomizable(ProtoId organ, HumanoidVisualLayers layer, ProtoId markingId) @@ -163,6 +229,11 @@ public sealed class MarkingsViewModel return !appearance.MatchSkin; } + /// + /// Returns the currently applied marking by its ID, if it exists + /// + /// + /// The marking currently applied if it exists, otherwise null public Marking? GetMarking(ProtoId organ, HumanoidVisualLayers layer, ProtoId markingId) @@ -176,6 +247,11 @@ public sealed class MarkingsViewModel return markings.FirstOrNull(it => it.MarkingId == markingId); } + /// + /// Attempts to add a marking to the current set of markings + /// + /// + /// Whether the marking was successfully added to the set of markings public bool TrySelectMarking(ProtoId organ, HumanoidVisualLayers layer, ProtoId markingId) @@ -230,6 +306,12 @@ public sealed class MarkingsViewModel return false; } + /// + /// Returns the list of currently selected markings for the layer on the given organ + /// + /// The organ to look up the layer within + /// The layer within the organ to look up + /// The set of markings for the provided organ if it has any, or null public List? SelectedMarkings(ProtoId organ, HumanoidVisualLayers layer) { @@ -238,6 +320,11 @@ public sealed class MarkingsViewModel : organMarkings.GetValueOrDefault(layer); } + /// + /// Attempts to remove a marking from the current set of markings + /// + /// + /// Whether the marking was successfully removed from the set of markings public bool TryDeselectMarking(ProtoId organ, HumanoidVisualLayers layer, ProtoId markingId) @@ -275,6 +362,12 @@ public sealed class MarkingsViewModel return true; } + /// + /// Attempts to set the color of the specified marking at the given index + /// + /// + /// The index within the marking's color array to set + /// The new color to set public void TrySetMarkingColor(ProtoId organ, HumanoidVisualLayers layer, ProtoId markingId, @@ -295,6 +388,9 @@ public sealed class MarkingsViewModel MarkingsChanged?.Invoke(organ, layer); } + /// + /// Ensures the markings within the model are valid. + /// public void ValidateMarkings() { foreach (var (organ, organData) in _organData) @@ -318,6 +414,14 @@ public sealed class MarkingsViewModel MarkingsReset?.Invoke(); } + /// + /// Gets the count data for an organ layer. + /// + /// The organ to look up count data for + /// The layer within the organ to look up count data for + /// Whether this layer requires at least one marking to be selected + /// The maximum amount of markings that can be selected for this layer + /// The currently selected amount of markings public void GetMarkingCounts(ProtoId organ, HumanoidVisualLayers layer, out bool isRequired, out int count, out int selected) { isRequired = false; @@ -348,6 +452,14 @@ public sealed class MarkingsViewModel selected = layerMarkings.Count; } + /// + /// Reorders the specified marking ID to the index and position relative to its index + /// + /// The organ to reorder the markings of + /// The layer to reorder the markings of + /// The marking to reorder + /// Whether the marking should be moved to before or after the given index + /// The new position index of the marking public void ChangeMarkingOrder(ProtoId organ, HumanoidVisualLayers layer, ProtoId markingId, @@ -381,6 +493,9 @@ public sealed class MarkingsViewModel } } +/// +/// Specifies whether an item in a list will be moved to before or after a corresponding index +/// public enum CandidatePosition { Before, diff --git a/Content.Shared/Body/BodyComponent.cs b/Content.Shared/Body/BodyComponent.cs index 0b32657f2ec..1e0776739d8 100644 --- a/Content.Shared/Body/BodyComponent.cs +++ b/Content.Shared/Body/BodyComponent.cs @@ -3,6 +3,11 @@ using Robust.Shared.GameStates; namespace Content.Shared.Body; +/// +/// Component on the entity that "has" a body, and that oversees entities with the inside it. +/// +/// +/// [RegisterComponent, NetworkedComponent] [Access(typeof(BodySystem))] public sealed partial class BodyComponent : Component diff --git a/Content.Shared/Body/BodySystem.Compatibility.cs b/Content.Shared/Body/BodySystem.Compatibility.cs index c6dd2bc2ba5..82d1b6a7eb4 100644 --- a/Content.Shared/Body/BodySystem.Compatibility.cs +++ b/Content.Shared/Body/BodySystem.Compatibility.cs @@ -1,8 +1,19 @@ +using JetBrains.Annotations; + namespace Content.Shared.Body; public sealed partial class BodySystem { + /// + /// Returns a list of organs with a given component in the body. + /// This is only provided to ease migration from the older BodySystem and should not be used in new code. + /// + /// The body to query. + /// The set of organs with the given component. + /// The component to test for. + /// Whether any organs were returned. [Obsolete("Use an event-relay based approach instead")] + [PublicAPI] public bool TryGetOrgansWithComponent(Entity ent, out List> organs) where TComp : Component { organs = new(); diff --git a/Content.Shared/Body/BodySystem.Relay.cs b/Content.Shared/Body/BodySystem.Relay.cs index 82587aa737d..68dbe4f22a7 100644 --- a/Content.Shared/Body/BodySystem.Relay.cs +++ b/Content.Shared/Body/BodySystem.Relay.cs @@ -2,11 +2,13 @@ using Content.Shared.Body.Events; using Content.Shared.Gibbing; using Content.Shared.Humanoid; using Content.Shared.Medical; +using JetBrains.Annotations; namespace Content.Shared.Body; public sealed partial class BodySystem { + // Refrain from adding an infinite block of relays here - consuming systems can use RelayEvent private void InitializeRelay() { SubscribeLocalEvent(RefRelayBodyEvent); @@ -28,6 +30,13 @@ public sealed partial class BodySystem RelayEvent((uid, component), args); } + /// + /// Relays the given event to organs within a body. + /// + /// The body to relay the event within + /// The event to relay + /// The type of the event + [PublicAPI] public void RelayEvent(Entity ent, ref T args) where T : struct { var ev = new BodyRelayedEvent(ent, args); @@ -38,6 +47,13 @@ public sealed partial class BodySystem args = ev.Args; } + /// + /// Relays the given event to organs within a body. + /// + /// The body to relay the event within + /// The event to relay + /// The type of the event + [PublicAPI] public void RelayEvent(Entity ent, T args) where T : class { var ev = new BodyRelayedEvent(ent, args); @@ -49,7 +65,7 @@ public sealed partial class BodySystem } /// -/// Event wrapper for relayed events. +/// Event wrapper for events being relayed to organs within a body. /// [ByRefEvent] public record struct BodyRelayedEvent(Entity Body, TEvent Args); diff --git a/Content.Shared/Body/BodySystem.cs b/Content.Shared/Body/BodySystem.cs index c53ab22452e..4cd5a4e7924 100644 --- a/Content.Shared/Body/BodySystem.cs +++ b/Content.Shared/Body/BodySystem.cs @@ -3,6 +3,17 @@ using Robust.Shared.Containers; namespace Content.Shared.Body; +/// +/// System responsible for coordinating entities with and their entities with . +/// This system is primarily responsible for event relaying and the relationships between a body and its organs. +/// It is not responsible for player-facing body features, e.g. "blood" or "breathing." +/// Such features should be implemented in systems relying on the various events raised by this class. +/// +/// +/// +/// +/// +/// public sealed partial class BodySystem : EntitySystem { [Dependency] private readonly SharedContainerSystem _container = default!; diff --git a/Content.Shared/Body/GibbableOrganComponent.cs b/Content.Shared/Body/GibbableOrganComponent.cs index fd813049092..0ac2025facb 100644 --- a/Content.Shared/Body/GibbableOrganComponent.cs +++ b/Content.Shared/Body/GibbableOrganComponent.cs @@ -1,7 +1,12 @@ +using Content.Shared.Gibbing; using Robust.Shared.GameStates; namespace Content.Shared.Body; +/// +/// Component that causes this entity to become gibs when the body it's in is gibbed +/// +/// [RegisterComponent, NetworkedComponent] [Access(typeof(GibbableOrganSystem))] public sealed partial class GibbableOrganComponent : Component; diff --git a/Content.Shared/Body/HandOrganComponent.cs b/Content.Shared/Body/HandOrganComponent.cs index 78cdea4a698..a9de7ecdaa9 100644 --- a/Content.Shared/Body/HandOrganComponent.cs +++ b/Content.Shared/Body/HandOrganComponent.cs @@ -3,13 +3,22 @@ using Robust.Shared.GameStates; namespace Content.Shared.Body; +/// +/// Organs with this component provide a hand with the given ID and data to the body when inserted. +/// [RegisterComponent, NetworkedComponent] [Access(typeof(HandOrganSystem))] public sealed partial class HandOrganComponent : Component { + /// + /// The hand ID used by on the body + /// [DataField(required: true)] public string HandID; + /// + /// The data used to create the hand + /// [DataField(required: true)] public Hand Data; } diff --git a/Content.Shared/Body/InitialBodyComponent.cs b/Content.Shared/Body/InitialBodyComponent.cs index cfb7a26b5d8..a27e5c092c5 100644 --- a/Content.Shared/Body/InitialBodyComponent.cs +++ b/Content.Shared/Body/InitialBodyComponent.cs @@ -4,11 +4,15 @@ namespace Content.Shared.Body; /// /// On map initialization, spawns the given organs into the body. +/// Liable to change as the body becomes more complex. /// [RegisterComponent] [Access(typeof(InitialBodySystem))] public sealed partial class InitialBodyComponent : Component { + /// + /// The organs to spawn based on their category. + /// [DataField(required: true)] public Dictionary, EntProtoId> Organs; } diff --git a/Content.Shared/Body/OrganComponent.cs b/Content.Shared/Body/OrganComponent.cs index 4126c192fb9..cad2ad86da7 100644 --- a/Content.Shared/Body/OrganComponent.cs +++ b/Content.Shared/Body/OrganComponent.cs @@ -3,6 +3,10 @@ using Robust.Shared.Prototypes; namespace Content.Shared.Body; +/// +/// Marks an entity as being able to be inserted into an entity with . +/// +/// [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] [Access(typeof(BodySystem))] public sealed partial class OrganComponent : Component diff --git a/Content.Shared/Body/SharedVisualBodySystem.Modifiers.cs b/Content.Shared/Body/SharedVisualBodySystem.Modifiers.cs index 0eb0d103b9a..6273b0640bf 100644 --- a/Content.Shared/Body/SharedVisualBodySystem.Modifiers.cs +++ b/Content.Shared/Body/SharedVisualBodySystem.Modifiers.cs @@ -6,6 +6,7 @@ using Content.Shared.Humanoid; using Content.Shared.Humanoid.Markings; using Content.Shared.Preferences; using Content.Shared.Verbs; +using JetBrains.Annotations; using Robust.Shared.Containers; using Robust.Shared.Prototypes; using Robust.Shared.Utility; @@ -47,6 +48,26 @@ public abstract partial class SharedVisualBodySystem }); } + /// + /// Copies the appearance of organs from one body to another + /// + /// The body whose organs to copy the appearance from + /// The body whose organs to copy the appearance to + [PublicAPI] + public void CopyAppearanceFrom(Entity source, Entity target) + { + if (!Resolve(source, ref source.Comp) || !Resolve(target, ref target.Comp)) + return; + + var sourceOrgans = _container.EnsureContainer(source, BodyComponent.ContainerID); + + foreach (var sourceOrgan in sourceOrgans.ContainedEntities) + { + var evt = new OrganCopyAppearanceEvent(sourceOrgan); + RaiseLocalEvent(target, ref evt); + } + } + /// /// Gathers all the markings-relevant data from this entity /// @@ -111,6 +132,12 @@ public abstract partial class SharedVisualBodySystem RaiseLocalEvent(ent, ref markingsEvt); } + /// + /// Applies the given set of markings to the body. + /// + /// The body whose organs to apply markings to. + /// A dictionary of organ categories to markings information. Organs not included in this dictionary will remain unaffected. + [PublicAPI] public void ApplyMarkings(EntityUid ent, Dictionary, Dictionary>> markings) { var markingsEvt = new ApplyOrganMarkingsEvent(markings); @@ -134,17 +161,37 @@ public abstract partial class SharedVisualBodySystem RaiseLocalEvent(ent, ref markingsEvt); } + /// + /// Applies the information contained with a to a visual body's appearance. + /// This sets the profile data and markings of all organs contained within the profile. + /// + /// The body to apply the profile to + /// The profile to apply + [PublicAPI] public void ApplyProfileTo(Entity ent, HumanoidCharacterProfile profile) { ApplyAppearanceTo(ent, profile.Appearance, profile.Sex); } + /// + /// Applies profile data to all visual organs within the body. + /// + /// The body to apply the organ profile to + /// The profile to apply + [PublicAPI] public void ApplyProfile(EntityUid ent, OrganProfileData profile) { var profileEvt = new ApplyOrganProfileDataEvent(profile, null); RaiseLocalEvent(ent, ref profileEvt); } + /// + /// Applies profile data to the specified visual organs within the body. + /// Organs not specified are left unchanged. + /// + /// The body to apply the organ profiles to. + /// The profiles to apply. + [PublicAPI] public void ApplyProfiles(EntityUid ent, Dictionary, OrganProfileData> profiles) { var profileEvt = new ApplyOrganProfileDataEvent(null, profiles); diff --git a/Content.Shared/Body/SharedVisualBodySystem.cs b/Content.Shared/Body/SharedVisualBodySystem.cs index 8254586abef..553dbe838e3 100644 --- a/Content.Shared/Body/SharedVisualBodySystem.cs +++ b/Content.Shared/Body/SharedVisualBodySystem.cs @@ -7,6 +7,9 @@ using Robust.Shared.Utility; namespace Content.Shared.Body; +/// +/// Class responsible for managing the appearance of an entity with via its organs with +/// public abstract partial class SharedVisualBodySystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototype = default!; @@ -84,20 +87,6 @@ public abstract partial class SharedVisualBodySystem : EntitySystem Dirty(ent); } - public void CopyAppearanceFrom(Entity source, Entity target) - { - if (!Resolve(source, ref source.Comp) || !Resolve(target, ref target.Comp)) - return; - - var sourceOrgans = _container.EnsureContainer(source, BodyComponent.ContainerID); - - foreach (var sourceOrgan in sourceOrgans.ContainedEntities) - { - var evt = new OrganCopyAppearanceEvent(sourceOrgan); - RaiseLocalEvent(target, ref evt); - } - } - private void OnVisualOrganCopyAppearance(Entity ent, ref BodyRelayedEvent args) { if (!TryComp(args.Args.Organ, out var other)) diff --git a/Content.Shared/Body/VisualBodyComponent.cs b/Content.Shared/Body/VisualBodyComponent.cs index 030b2876c0d..96c3920a248 100644 --- a/Content.Shared/Body/VisualBodyComponent.cs +++ b/Content.Shared/Body/VisualBodyComponent.cs @@ -2,6 +2,9 @@ using Robust.Shared.GameStates; namespace Content.Shared.Body; +/// +/// Component on an entity with that modifies its appearance based on contained organs with +/// [RegisterComponent, NetworkedComponent] [Access(typeof(SharedVisualBodySystem))] public sealed partial class VisualBodyComponent : Component; diff --git a/Content.Shared/Body/VisualOrganComponent.cs b/Content.Shared/Body/VisualOrganComponent.cs index 9ca2c363746..6427c8f0e3a 100644 --- a/Content.Shared/Body/VisualOrganComponent.cs +++ b/Content.Shared/Body/VisualOrganComponent.cs @@ -4,28 +4,35 @@ using Robust.Shared.Serialization; namespace Content.Shared.Body; +/// +/// Defines an organ that applies a sprite to the specified within the body +/// [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)] [Access(typeof(SharedVisualBodySystem))] public sealed partial class VisualOrganComponent : Component { /// - /// The layer on the entity that this contributes to + /// The sprite layer on the entity that this contributes to /// [DataField(required: true)] public Enum Layer; /// - /// The data for the layer + /// The sprite data for the layer /// [DataField(required: true), AutoNetworkedField, AlwaysPushInheritance] public PrototypeLayerData Data; /// - /// When applying a profile, if the sex is present in this dictionary, overrides the state of the data. + /// When applying a profile, if the sex is present in this dictionary, overrides the state of the sprite data. + /// Used for e.g. male vs female torsoes. /// [DataField] public Dictionary? SexStateOverrides; + /// + /// The current profile data of this organ, used for alternate sprite selection and colouration. + /// [DataField, AutoNetworkedField] public OrganProfileData Profile = new(); } diff --git a/Content.Shared/Body/VisualOrganMarkingsComponent.cs b/Content.Shared/Body/VisualOrganMarkingsComponent.cs index a0af5a6a16e..af79fd1830a 100644 --- a/Content.Shared/Body/VisualOrganMarkingsComponent.cs +++ b/Content.Shared/Body/VisualOrganMarkingsComponent.cs @@ -6,18 +6,21 @@ using Robust.Shared.Serialization; namespace Content.Shared.Body; +/// +/// Defines an organ that applies markings on top of the layer specified in +/// [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(raiseAfterAutoHandleState: true, fieldDeltas: true)] [Access(typeof(SharedVisualBodySystem))] public sealed partial class VisualOrganMarkingsComponent : Component { /// - /// What markings this organ can take + /// Defines the type of markings this organ can take /// [DataField(required: true), AlwaysPushInheritance] public OrganMarkingData MarkingData = default!; /// - /// The list of markings to apply to the entity + /// The list of markings this organ is currently providing to the entity /// [DataField, AutoNetworkedField] public Dictionary> Markings = new(); diff --git a/Content.Shared/Humanoid/Markings/MarkingManager.cs b/Content.Shared/Humanoid/Markings/MarkingManager.cs index 175d1f978b9..74eb5600337 100644 --- a/Content.Shared/Humanoid/Markings/MarkingManager.cs +++ b/Content.Shared/Humanoid/Markings/MarkingManager.cs @@ -7,6 +7,9 @@ using Robust.Shared.Prototypes; namespace Content.Shared.Humanoid.Markings; +/// +/// Manager responsible for sharing the logic of markings between in-simulation bodies and out-of-simulation profile editing +/// public sealed class MarkingManager { [Dependency] private readonly IComponentFactory _component = default!; @@ -81,6 +84,12 @@ public sealed class MarkingManager return res; } + /// + /// Gets the marking prototype associated with the marking. + /// + /// The marking to look up + /// When this method returns; will contain the marking prototype corresponding to the one specified by the marking if it exists. + /// Whether a marking prototype exists for the given marking public bool TryGetMarking(Marking marking, [NotNullWhen(true)] out MarkingPrototype? markingResult) { return _markings.TryGetValue(marking.MarkingId, out markingResult); @@ -92,7 +101,13 @@ public sealed class MarkingManager CachePrototypes(); } - + /// + /// Determines if a marking prototype can be applied to something with the given markings group and sex. + /// + /// The markings group to test + /// The sex to test + /// The prototype to reference against + /// True if a marking with the prototype could be applied public bool CanBeApplied(ProtoId group, Sex sex, MarkingPrototype prototype) { var groupProto = _prototype.Index(group); @@ -223,6 +238,11 @@ public sealed class MarkingManager } } + /// + /// Returns the expected set of organs for a species to have. + /// + /// The species to look up. + /// A dictionary of organ categories to their usual organs within a species. public Dictionary, EntProtoId> GetOrgans(ProtoId species) { var speciesPrototype = _prototype.Index(species); @@ -234,6 +254,11 @@ public sealed class MarkingManager return initialBody.Organs; } + /// + /// Looks up the expected set of for the species to have + /// + /// The species to look up the usual organs of. + /// A dictionary of organ categories to their usual organ marking data within a species. public Dictionary, OrganMarkingData> GetMarkingData(ProtoId species) { var ret = new Dictionary, OrganMarkingData>(); @@ -249,6 +274,15 @@ public sealed class MarkingManager return ret; } + /// + /// Expands the provided profile data into all the categories for a species. + /// + /// The species the returned dictionary should be comprehensive for. + /// The sex to apply to all organs + /// The skin color to apply to all organs + /// The eye color to apply to all organs + /// + /// public Dictionary, OrganProfileData> GetProfileData(ProtoId species, Sex sex, Color skinColor, @@ -269,6 +303,12 @@ public sealed class MarkingManager return ret; } + /// + /// Gets the for the entity prototype corresponding to an organ + /// + /// The ID of the organ entity prototype to look up + /// The marking data for the organ if it exists + /// Whether the provided entity prototype ID corresponded to organ marking data that could be returned public bool TryGetMarkingData(EntProtoId organ, [NotNullWhen(true)] out OrganMarkingData? organData) { organData = null; @@ -284,6 +324,12 @@ public sealed class MarkingManager return true; } + /// + /// Converts a legacy flat list of markings to a structured markings dictionary for a given species + /// + /// A flat list of markings + /// The species to convert the markings for + /// A dictionary with the provided markings categorized appropriately for the species public Dictionary, Dictionary>> ConvertMarkings(List markings, ProtoId species) {