]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Randomizes more humanoid appearances (#27997)
authorVerm <32827189+Vermidia@users.noreply.github.com>
Sat, 1 Jun 2024 04:51:07 +0000 (23:51 -0500)
committerGitHub <noreply@github.com>
Sat, 1 Jun 2024 04:51:07 +0000 (00:51 -0400)
Content.Server/Humanoid/Components/RandomHumanoidAppearanceComponent.cs
Content.Server/Humanoid/Systems/RandomHumanoidAppearanceSystem.cs
Content.Shared/Humanoid/Prototypes/RandomHumanoidSettingsPrototype.cs
Resources/Prototypes/Entities/Mobs/Player/human.yml
Resources/Prototypes/Entities/Mobs/Player/humanoid.yml

index 5a0f6fcef11091296421eed215943c7a0547a263..5efea024f4e3e15b029ef77c3fc33bfcc132c300 100644 (file)
@@ -1,4 +1,4 @@
-using Content.Shared.Humanoid.Prototypes;
+using Content.Shared.Humanoid.Prototypes;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
 
 namespace Content.Server.CharacterAppearance.Components;
@@ -7,4 +7,8 @@ namespace Content.Server.CharacterAppearance.Components;
 public sealed partial class RandomHumanoidAppearanceComponent : Component
 {
     [DataField("randomizeName")] public bool RandomizeName = true;
+    /// <summary>
+    /// After randomizing, sets the hair style to this, if possible
+    /// </summary>
+    [DataField] public string? Hair = null;
 }
index 9185fedc389944850e390e2262bbe6640894f3d2..2822fb69e1441ec18bee844a49eaedbe0fa40bb4 100644 (file)
@@ -25,6 +25,9 @@ public sealed class RandomHumanoidAppearanceSystem : EntitySystem
         }
 
         var profile = HumanoidCharacterProfile.RandomWithSpecies(humanoid.Species);
+        //If we have a specified hair style, change it to this
+        if(component.Hair != null)
+            profile = profile.WithCharacterAppearance(profile.Appearance.WithHairStyleName(component.Hair));
 
         _humanoid.LoadProfile(uid, profile, humanoid);
 
index ec6818221a9ac5c917d297525419e769af735468..a97c3134bedc932d824662ebefed70765aa5ad51 100644 (file)
@@ -15,6 +15,7 @@ public sealed partial class RandomHumanoidSettingsPrototype : IPrototype, IInher
     public string[]? Parents { get; }
 
     [AbstractDataField]
+    [NeverPushInheritance]
     public bool Abstract { get; }
 
     /// <summary>
@@ -32,6 +33,7 @@ public sealed partial class RandomHumanoidSettingsPrototype : IPrototype, IInher
     /// <summary>
     ///     Extra components to add to this entity.
     /// </summary>
-    [DataField("components")]
+    [DataField]
+    [AlwaysPushInheritance]
     public ComponentRegistry? Components { get; private set; }
 }
index 2c7ad4972c0c79cf1e48d06667d686065578a1c5..629ba91518aecd7b3403fe61620e54157f1d98c4 100644 (file)
@@ -11,6 +11,9 @@
   name: syndicate agent
   suffix: Human, Base
   components:
+    - type: RandomHumanoidAppearance
+      randomizeName: false
+      hair: HairBald
     - type: Loadout
       prototypes: [SyndicateOperativeGearExtremelyBasic]
     - type: RandomMetadata
index c5805f0ed9217d214f59049210f21cf593d53d42..e365ee3a1cfac79ac58114432a731943c1601010 100644 (file)
@@ -1,4 +1,18 @@
-# Random humanoids
+## Random humanoids
+
+- type: randomHumanoidSettings
+  id: EventHumanoid
+  components:
+    - type: RandomHumanoidAppearance
+      randomizeName: false
+    - type: GhostTakeoverAvailable
+
+- type: randomHumanoidSettings
+  id: EventHumanoidMindShielded
+  parent: EventHumanoid
+  components:
+    - type: MindShield
+    - type: InitialInfectedExempt
 
 ## Death Squad
 
 
 - type: randomHumanoidSettings
   id: DeathSquad
+  parent: EventHumanoidMindShielded
   randomizeName: false
-  components:
-    - type: MindShield
+  components:        
     - type: GhostRole
       name: ghost-role-information-Death-Squad-name
       description: ghost-role-information-Death-Squad-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ DeathSquadGear ]
     - type: RandomMetadata
       nameSegments:
         - NamesFirstMilitaryLeader
         - NamesLastMilitary
-    - type: InitialInfectedExempt
 
 
 ## ERT Leader
 
 - type: randomHumanoidSettings
   id: ERTLeader
+  parent: EventHumanoidMindShielded
   randomizeName: false
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-leader-name
       description: ghost-role-information-ert-leader-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTLeaderGear ]
     - type: RandomMetadata
       nameSegments:
       - NamesFirstMilitaryLeader
       - NamesLastMilitary
-    - type: InitialInfectedExempt
 
 - type: entity
   id: RandomHumanoidSpawnerERTLeaderEVA
   id: ERTLeaderEVA
   parent: ERTLeader
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-leader-name
       description: ghost-role-information-ert-leader-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTLeaderGearEVA ]
-    - type: InitialInfectedExempt
 
 - type: entity
   id: RandomHumanoidSpawnerERTLeaderEVALecter
   id: ERTLeaderEVALecter
   parent: ERTLeaderEVA
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-leader-name
       description: ghost-role-information-ert-leader-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTLeaderGearEVALecter ]
-    - type: InitialInfectedExempt
 
 ## ERT Chaplain
 
   id: ERTChaplain
   parent: ERTLeader
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-chaplain-name
       description: ghost-role-information-ert-chaplain-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: RandomMetadata
       nameSegments:
       - NamesFirstMilitary
       - NamesLastMilitary
     - type: Loadout
       prototypes: [ ERTChaplainGear ]
-    - type: InitialInfectedExempt
 
 - type: entity
   id: RandomHumanoidSpawnerERTChaplainEVA
   id: ERTChaplainEVA
   parent: ERTChaplain
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-chaplain-name
       description: ghost-role-information-ert-chaplain-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTChaplainGearEVA ]
-    - type: InitialInfectedExempt
 
 ## ERT Janitor
 
   id: ERTJanitor
   parent: ERTLeader
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-janitor-name
       description: ghost-role-information-ert-janitor-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: RandomMetadata
       nameSegments:
       - NamesFirstMilitary
       - NamesLastMilitary
     - type: Loadout
       prototypes: [ ERTJanitorGear ]
-    - type: InitialInfectedExempt
 
 - type: entity
   id: RandomHumanoidSpawnerERTJanitorEVA
   id: ERTJanitorEVA
   parent: ERTJanitor
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-janitor-name
       description: ghost-role-information-ert-janitor-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTJanitorGearEVA ]
-    - type: InitialInfectedExempt
 
 ## ERT Engineer
 
   id: ERTEngineer
   parent: ERTLeader
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-engineer-name
       description: ghost-role-information-ert-engineer-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: RandomMetadata
       nameSegments:
       - NamesFirstMilitary
       - NamesLastMilitary
     - type: Loadout
       prototypes: [ ERTEngineerGear ]
-    - type: InitialInfectedExempt
 
 - type: entity
   id: RandomHumanoidSpawnerERTEngineerEVA
   id: ERTEngineerEVA
   parent: ERTEngineer
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-engineer-name
       description: ghost-role-information-ert-engineer-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTEngineerGearEVA ]
-    - type: InitialInfectedExempt
 
 ## ERT Security
 
   id: ERTSecurity
   parent: ERTLeader
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-security-name
       description: ghost-role-information-ert-security-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: RandomMetadata
       nameSegments:
       - NamesFirstMilitary
       - NamesLastMilitary
     - type: Loadout
       prototypes: [ ERTSecurityGear ]
-    - type: InitialInfectedExempt
 
 - type: entity
   id: RandomHumanoidSpawnerERTSecurityEVA
   id: ERTSecurityEVA
   parent: ERTSecurity
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-security-name
       description: ghost-role-information-ert-security-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTSecurityGearEVA ]
-    - type: InitialInfectedExempt
 
 - type: entity
   id: RandomHumanoidSpawnerERTSecurityEVALecter
   id: ERTSecurityEVALecter
   parent: ERTSecurityEVA
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-security-name
       description: ghost-role-information-ert-security-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTSecurityGearEVALecter ]
-    - type: InitialInfectedExempt
 
 ## ERT Medic
 
   id: ERTMedical
   parent: ERTLeader
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-medical-name
       description: ghost-role-information-ert-medical-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: RandomMetadata
       nameSegments:
       - NamesFirstMilitary
       - NamesLastMilitary
     - type: Loadout
       prototypes: [ ERTMedicalGear ]
-    - type: InitialInfectedExempt
 
 - type: entity
   id: RandomHumanoidSpawnerERTMedicalEVA
   id: ERTMedicalEVA
   parent: ERTMedical
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-ert-medical-name
       description: ghost-role-information-ert-medical-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ERTMedicalGearEVA ]
-    - type: InitialInfectedExempt
 
 ## CBURN
 
 
 - type: randomHumanoidSettings
   id: CBURNAgent
+  parent: EventHumanoidMindShielded
   components:
-    - type: MindShield
     - type: Loadout
       prototypes: [CBURNGear]
     - type: GhostRole
       description: ghost-role-information-cburn-agent-description
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: RandomMetadata
       nameSegments:
       - NamesFirstMilitary
       - NamesLastMilitary
-    - type: InitialInfectedExempt
 ## Central Command
 
 - type: entity
 
 - type: randomHumanoidSettings
   id: CentcomOfficial
+  parent: EventHumanoidMindShielded
   components:
-    - type: MindShield
     - type: GhostRole
       name: ghost-role-information-centcom-official-name
       description: ghost-role-information-centcom-official-description
       raffle:
         settings: default
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ CentcomGear ]
-    - type: InitialInfectedExempt
 
 ## Syndicate
 
 - type: randomHumanoidSettings
   id: SyndicateAgent
   components:
+    - type: RandomHumanoidAppearance
+      randomizeName: false
     - type: Loadout
       prototypes: [SyndicateOperativeGearExtremelyBasic]
 
 - type: randomHumanoidSettings
   id: NukeOp
   components:
+    - type: RandomHumanoidAppearance
+      randomizeName: false
     - type: NukeOperative
 
 - type: entity
 
 - type: randomHumanoidSettings
   id: Cluwne
+  parent: EventHumanoid
   randomizeName: false
   components:
     - type: GhostRole
       description: ghost-role-information-cluwne-description
       raffle:
         settings: default
-    - type: GhostTakeoverAvailable
     - type: Cluwne
 
+
+## Shuttle roles
+
 ## Lost Cargo technician
 
 - type: entity
 
 - type: randomHumanoidSettings
   id: LostCargoTechnician
-  randomizeName: false
+  parent: EventHumanoid
   components:
     - type: GhostRole
       name: ghost-role-information-lost-cargo-technical-name
       rules: ghost-role-information-lost-cargo-technical-rules
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ LostCargoTechGearSuit, LostCargoTechGearCoat ]
-    - type: RandomMetadata
-      nameSegments:
-      - names_first
-      - names_last
 
 # Clown troupe
 
 
 - type: randomHumanoidSettings
   id: ClownTroupe
+  parent: EventHumanoid
   randomizeName: false
   components:
     - type: GhostRole
       rules: ghost-role-information-clown-troupe-rules
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ ClownTroupe ]
     - type: RandomMetadata
 
 - type: randomHumanoidSettings
   id: ClownTroupeBanana
+  parent: ClownTroupe
   randomizeName: false
   components:
-    - type: GhostRole
-      name: ghost-role-information-clown-troupe-name
-      description: ghost-role-information-clown-troupe-description
-      rules: ghost-role-information-clown-troupe-rules
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ BananaClown ]
-    - type: RandomMetadata
-      nameSegments:
-      - names_clown
 
 # Traveling exotic chef
 
 
 - type: randomHumanoidSettings
   id: TravelingChef
-  randomizeName: false
+  parent: EventHumanoid
   components:
     - type: GhostRole
       name: ghost-role-information-traveling-chef-name
       rules: ghost-role-information-traveling-chef-rules
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ TravelingChef ]
-    - type: RandomMetadata
-      nameSegments:
-      - names_first
-      - names_last
 
 # Disaster victim
 
     - type: RandomHumanoidSpawner
       settings: DisasterVictimCaptain
 
+## Following use EventHumanoidMindShielded since they are heads and probably should have mindshields
+
 - type: randomHumanoidSettings
-  id: DisasterVictimResearchDirector
-  randomizeName: false
+  id: DisasterVictimHead
+  parent: EventHumanoidMindShielded
   components:
     - type: GhostRole
       name: ghost-role-information-disaster-victim-name
       rules: ghost-role-information-disaster-victim-rules
       raffle:
         settings: default
-    - type: GhostTakeoverAvailable
+
+- type: randomHumanoidSettings
+  id: DisasterVictimResearchDirector
+  parent: DisasterVictimHead
+  components:
     - type: Loadout
       prototypes: [ DisasterVictimRD, DisasterVictimRDAlt ]
-    - type: RandomMetadata
-      nameSegments:
-      - names_first
-      - names_last
 
 - type: randomHumanoidSettings
   id: DisasterVictimCMO
-  randomizeName: false
+  parent: DisasterVictimHead
   components:
-    - type: GhostRole
-      name: ghost-role-information-disaster-victim-name
-      description: ghost-role-information-disaster-victim-description
-      rules: ghost-role-information-disaster-victim-rules
-      raffle:
-        settings: default
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ DisasterVictimCMO, DisasterVictimCMOAlt ]
-    - type: RandomMetadata
-      nameSegments:
-      - names_first
-      - names_last
 
 - type: randomHumanoidSettings
   id: DisasterVictimCaptain
-  randomizeName: false
+  parent: DisasterVictimHead
   components:
-    - type: GhostRole
-      name: ghost-role-information-disaster-victim-name
-      description: ghost-role-information-disaster-victim-description
-      rules: ghost-role-information-disaster-victim-rules
-      raffle:
-        settings: default
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ DisasterVictimCaptain, DisasterVictimCaptainAlt ]
-    - type: RandomMetadata
-      nameSegments:
-      - names_first
-      - names_last
 
 # Syndie Disaster Victim
 
 
 - type: randomHumanoidSettings
   id: SyndieDisasterVictim
-  randomizeName: false
+  parent: EventHumanoid
   components:
     - type: NpcFactionMember
       factions:
       rules: ghost-role-information-syndie-disaster-victim-rules
       raffle:
         settings: short
-    - type: GhostTakeoverAvailable
     - type: Loadout
       prototypes: [ SyndicateOperativeGearCivilian ]
-    - type: RandomMetadata
-      nameSegments:
-      - names_first
-      - names_last