]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Station AI ghost role (#40607)
authorchromiumboy <50505512+chromiumboy@users.noreply.github.com>
Sat, 20 Dec 2025 14:21:54 +0000 (08:21 -0600)
committerGitHub <noreply@github.com>
Sat, 20 Dec 2025 14:21:54 +0000 (14:21 +0000)
* Initial commit

* API

* review

---------

Co-authored-by: ScarKy0 <scarky0@onet.eu>
Content.Server/Ghost/Roles/ToggleableGhostRoleSystem.cs
Content.Server/Silicons/StationAi/StationAiSystem.cs
Resources/Locale/en-US/silicons/station-ai.ftl
Resources/Prototypes/Entities/Mobs/Player/silicon.yml

index 7bb25a63fbd03515ae5457e5c75a522ad694c4c5..13f90d8bd1f61d69661fbd61f359dc2ae174054f 100644 (file)
@@ -49,15 +49,23 @@ public sealed class ToggleableGhostRoleSystem : EntitySystem
 
         UpdateAppearance(uid, ToggleableGhostRoleStatus.Searching);
 
-        var ghostRole = EnsureComp<GhostRoleComponent>(uid);
-        EnsureComp<GhostTakeoverAvailableComponent>(uid);
-
-        //GhostRoleComponent inherits custom settings from the ToggleableGhostRoleComponent
-        ghostRole.RoleName = Loc.GetString(component.RoleName);
-        ghostRole.RoleDescription = Loc.GetString(component.RoleDescription);
-        ghostRole.RoleRules = Loc.GetString(component.RoleRules);
-        ghostRole.JobProto = component.JobProto;
-        ghostRole.MindRoles = component.MindRoles;
+        ActivateGhostRole((uid, component));
+    }
+
+    public void ActivateGhostRole(Entity<ToggleableGhostRoleComponent?> ent)
+    {
+        if (!Resolve(ent, ref ent.Comp))
+            return;
+
+        var ghostRole = EnsureComp<GhostRoleComponent>(ent);
+        EnsureComp<GhostTakeoverAvailableComponent>(ent);
+
+        // GhostRoleComponent inherits custom settings from the ToggleableGhostRoleComponent
+        ghostRole.RoleName = Loc.GetString(ent.Comp.RoleName);
+        ghostRole.RoleDescription = Loc.GetString(ent.Comp.RoleDescription);
+        ghostRole.RoleRules = Loc.GetString(ent.Comp.RoleRules);
+        ghostRole.JobProto = ent.Comp.JobProto;
+        ghostRole.MindRoles = ent.Comp.MindRoles;
     }
 
     private void OnExamined(EntityUid uid, ToggleableGhostRoleComponent component, ExaminedEvent args)
index c4afd83b2d7d00ee0b5df7bf5b759ff764a6abf6..36aa9acd6b557019b12eabd23300361a35086a78 100644 (file)
@@ -2,6 +2,8 @@ using Content.Server.Chat.Systems;
 using Content.Server.Construction;
 using Content.Server.Destructible;
 using Content.Server.Ghost;
+using Content.Server.Ghost.Roles;
+using Content.Server.Ghost.Roles.Components;
 using Content.Server.Mind;
 using Content.Server.Power.Components;
 using Content.Server.Roles;
@@ -47,6 +49,7 @@ public sealed class StationAiSystem : SharedStationAiSystem
     [Dependency] private readonly RoleSystem _roles = default!;
     [Dependency] private readonly ItemSlotsSystem _slots = default!;
     [Dependency] private readonly GhostSystem _ghost = default!;
+    [Dependency] private readonly ToggleableGhostRoleSystem _ghostrole = default!;
     [Dependency] private readonly AlertsSystem _alerts = default!;
     [Dependency] private readonly DestructibleSystem _destructible = default!;
     [Dependency] private readonly SharedBatterySystem _battery = default!;
@@ -97,14 +100,30 @@ public sealed class StationAiSystem : SharedStationAiSystem
         }
 
         var brain = container.ContainedEntities[0];
+        var hasMind = _mind.TryGetMind(brain, out var mindId, out var mind);
 
-        if (_mind.TryGetMind(brain, out var mindId, out var mind))
+        if (hasMind || HasComp<GhostRoleComponent>(brain))
         {
-            // Found an existing mind to transfer into the AI core
             var aiBrain = Spawn(_stationAiBrain, Transform(ent.Owner).Coordinates);
-            _roles.MindAddJobRole(mindId, mind, false, _stationAiJob);
-            _mind.TransferTo(mindId, aiBrain);
 
+            if (hasMind)
+            {
+                // Found an existing mind to transfer into the AI core
+                _roles.MindAddJobRole(mindId, mind, false, _stationAiJob);
+                _mind.TransferTo(mindId, aiBrain);
+            }
+            else
+            {
+                // If the brain had a ghost role attached, activate the station AI ghost role
+                _ghostrole.ActivateGhostRole(aiBrain);
+
+                // Set the new AI brain to the 'rebooting' state
+                if (TryComp<StationAiCustomizationComponent>(aiBrain, out var customization))
+                    SetStationAiState((aiBrain, customization), StationAiState.Rebooting);
+                
+            }
+
+            // Delete the new AI brain if it cannot be inserted into the core
             if (!TryComp<StationAiHolderComponent>(ent, out var targetHolder) ||
                 !_slots.TryInsert(ent, targetHolder.Slot, aiBrain, null))
             {
index e3451452e465482c3918c06d5b73522362dfc042..cbe3ef6ec02e932a87ab2649c89e28e75eca1a74 100644 (file)
@@ -9,6 +9,10 @@ station-ai-is-too-damaged-for-upload = Upload failed - the AI core must be repai
 station-ai-core-losing-power = Your AI core is now running on reserve battery power.
 station-ai-core-critical-power = Your AI core is critically low on power. External power must be re-established or severe data corruption may occur!
 
+# Ghost role
+station-ai-ghost-role-name = Station AI
+station-ai-ghost-role-description = Serve the station crew as its ever watchful AI.
+
 # Radial actions
 ai-open = Open actions
 ai-close = Close actions
index 898cee85244b51e144a254a28a1670fae6361c8b..d9bc7c5829e13d147097eb544458022c02139a39 100644 (file)
       state: ai_female
   - type: NameIdentifier
     group: StationAi
+  - type: ToggleableGhostRole
+    roleName: station-ai-ghost-role-name
+    roleDescription: station-ai-ghost-role-description
+    roleRules: ghost-role-information-silicon-rules
+    mindRoles:
+    - MindRoleGhostRoleSilicon
+    job: StationAi
 
 # Hologram projection that the AI's eye tracks.
 - type: entity