Skip to content

Commit 5e458e1

Browse files
ProximitronRinary1
andauthored
Intellicard fixes to transfer, unified naming conventions and name transfers with posi/mmi (#5776)
## Short description Fixing dead-end error that makes it impossible to move an AI to anything else than an intellicard. Unify naming convention of AI core and Intellicard with silicon ID-generation. Letting (posi/mmi)brains be base for naming of silicons like borgs. ## Why we need to add this This is mostly a fix and cleanup. Balancing impact would be: - The fixed possibility to transfer intelligences from but also to posi/mmi ## Media (Video/Screenshots) <img width="713" height="556" alt="image" src="https://github.com/user-attachments/assets/7b389fcc-584f-4380-9ceb-23214db611ae" /> <img width="364" height="183" alt="image" src="https://github.com/user-attachments/assets/6dffec50-e43f-4a5c-a8e7-090e838c194f" /> <img width="202" height="71" alt="image" src="https://github.com/user-attachments/assets/41e81179-01e7-4146-aebf-0e177794877e" /> <img width="471" height="258" alt="image" src="https://github.com/user-attachments/assets/9326ef29-4840-48ba-9e93-fa2caa8c98c7" /> <img width="508" height="353" alt="image" src="https://github.com/user-attachments/assets/6f51736e-3bae-4245-b56c-ce6aa36fcc05" /> <img width="460" height="264" alt="image" src="https://github.com/user-attachments/assets/9afa1019-ef59-4485-9e5e-2370b5a61b48" /> ## Checks - [x] I do not require assistance to complete the PR. - [x] Before posting/requesting review of a PR, I have verified that the changes work. - [x] I have added screenshots/videos of the changes, or this PR does not change in-game mechanics. - [x] I affirm that my changes are licensed under the [MIT License](https://github.com/ss14Starlight/space-station-14/blob/Starlight/LICENSE.TXT) and grant permission for use in this repository under its conditions. **Changelog** :cl: STARLIGHT TEAM - add: Borg chassis names now synchronize with inserted brains - tweak: Entity naming (Intellicard/AI core) was unified and fixed - tweak: Entitys that have their intelligence removed by intellicard, reset to default names - fix: Intellicard entities can now be transfered to borg/borg brains/MMI as intended --------- Co-authored-by: Rinary <rinary.super@gmail.com>
1 parent 4c562d7 commit 5e458e1

8 files changed

Lines changed: 147 additions & 28 deletions

File tree

Content.Server/Silicons/StationAi/StationAiSystem.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
using Content.Shared.Follower.Components;
4444
using Content.Shared.Follower;
4545
using Content.Shared.Humanoid;
46+
using Content.Shared.Intellicard;
4647
using Content.Shared.Medical.SuitSensor;
4748
using Content.Shared.Medical.SuitSensors;
4849
using Content.Shared.Mobs.Components;
@@ -120,6 +121,7 @@ public override void Initialize()
120121
SubscribeLocalEvent<StationAiCoreComponent, DestructionEventArgs>(OnDestruction);
121122
SubscribeLocalEvent<StationAiCoreComponent, DoAfterAttemptEvent<IntellicardDoAfterEvent>>(OnDoAfterAttempt);
122123
SubscribeLocalEvent<StationAiCoreComponent, RejuvenateEvent>(OnRejuvenate);
124+
SubscribeLocalEvent<GhostAttemptHandleEvent>(OnGhostAttempt); // Starlight
123125

124126
SubscribeLocalEvent<ExpandICChatRecipientsEvent>(OnExpandICChatRecipients);
125127
SubscribeLocalEvent<StationAiTurretComponent, AmmoShotEvent>(OnAmmoShot);
@@ -129,6 +131,19 @@ public override void Initialize()
129131
SubscribeNetworkEvent<StationAiWarpToTargetEvent>(OnStationAiWarpToTarget); // Starlight
130132
}
131133

134+
// Starlight Start: The intellicard/AI should immediatly eject the ghost if the command ghost is used to free it for further use.
135+
private void OnGhostAttempt(GhostAttemptHandleEvent args)
136+
{
137+
if (args.Mind.CurrentEntity is not { } entity ||
138+
!_container.TryGetContainingContainer(entity, out var container) ||
139+
container.ID != StationAiHolderComponent.Container ||
140+
!TryComp<StationAiHolderComponent>(container.Owner, out var holder))
141+
return;
142+
143+
_slots.TryEject(container.Owner, holder.Slot, null, out _);
144+
}
145+
// Starlight-end
146+
132147
// Starlight Start: AI warping
133148
#region Starlight
134149
public override void Update(float frameTime)

Content.Shared/Silicons/Borgs/SharedBorgSystem.Ui.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ private void OnSetNameBuiMessage(Entity<BorgChassisComponent> chassis, ref BorgS
5858
return;
5959

6060
_adminLog.Add(LogType.Action, LogImpact.High, $"{args.Actor} set borg \"{chassis.Owner}\"'s name to: {name}");
61-
_metaData.SetEntityName(chassis, name, metaData, false);
61+
// Starlight-start: Keep the Borg brain synchronized with the chassis name.
62+
_metaData.SetEntityName(chassis, name, metaData);
63+
if (chassis.Comp.BrainEntity is { } brain)
64+
_metaData.SetEntityName(brain, name);
65+
// Starlight-end
6266
}
6367

6468
private void OnRemoveModuleBuiMessage(Entity<BorgChassisComponent> chassis, ref BorgRemoveModuleBuiMessage args)

Content.Shared/Silicons/Borgs/SharedBorgSystem.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@
3535
using Content.Shared.Radio.Components;
3636
using Content.Shared._Starlight.Silicons.Borgs;
3737
using Content.Shared.Actions.Components;
38-
// Starlight begin
38+
using Content.Shared.NameModifier.EntitySystems;
39+
using Robust.Shared.Prototypes;
3940
using Content.Shared._Starlight.TextToSpeech;
4041
using Content.Shared.Tag;
41-
// Starlight end
4242

4343
namespace Content.Shared.Silicons.Borgs;
4444

@@ -70,6 +70,7 @@ public abstract partial class SharedBorgSystem : EntitySystem
7070
[Dependency] private SharedHandheldLightSystem _handheldLight = default!;
7171
[Dependency] private SharedAccessSystem _access = default!;
7272
[Dependency] private SharedAudioSystem _audio = default!;
73+
[Dependency] private NameModifierSystem _nameModifier = default!; // Starlight
7374
[Dependency] private TagSystem _tag = default!; // Starlight
7475

7576
/// <inheritdoc/>
@@ -137,6 +138,31 @@ private void OnStartup(Entity<BorgChassisComponent> chassis, ref ComponentStartu
137138
private void OnMapInit(Entity<BorgChassisComponent> chassis, ref MapInitEvent args)
138139
{
139140
_movementSpeedModifier.RefreshMovementSpeedModifiers(chassis.Owner);
141+
142+
// Starlight-start: If the borg has a brain, synchronize the name of the brain with the chassis.
143+
if (chassis.Comp.BrainEntity is { } brain)
144+
SynchronizeBrainName(chassis, brain);
145+
// Starlight-end
146+
}
147+
148+
// Starlight: function to synchronize the name of the brain with the chassis, and the other way around.
149+
private void SynchronizeBrainName(Entity<BorgChassisComponent> chassis, EntityUid brain)
150+
{
151+
var brainName = _nameModifier.GetBaseName(brain);
152+
var chassisName = _nameModifier.GetBaseName(chassis.Owner);
153+
154+
if (brainName.Equals(chassisName, StringComparison.InvariantCulture))
155+
return;
156+
157+
if (MetaData(brain).EntityPrototype is { } brainPrototype &&
158+
brainName.Equals(brainPrototype.Name, StringComparison.InvariantCulture))
159+
{
160+
_metaData.SetEntityName(brain, chassisName);
161+
}
162+
else
163+
{
164+
_metaData.SetEntityName(chassis, brainName);
165+
}
140166
}
141167

142168
private void OnItemSlotInsertAttempt(Entity<BorgChassisComponent> chassis, ref ItemSlotInsertAttemptEvent args)
@@ -181,6 +207,7 @@ protected virtual void OnInserted(Entity<BorgChassisComponent> chassis, ref EntI
181207
return;
182208

183209
//#region Starlight
210+
SynchronizeBrainName(chassis, args.Entity);
184211
if (TryComp(args.Entity, out BorgBrainComponent? brain) && _mind.TryGetMind(args.Entity, out var mindId, out var mind))
185212
{
186213
//re-target the station-AI's shunt target to the chassis insteaf of the brain

Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs

Lines changed: 82 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
using System.Linq;
4444
using Content.Shared.Silicons.Laws.Components;
4545
using Content.Shared.DeviceLinking;
46-
using System.Numerics;
4746
using Content.Shared._Starlight;
47+
using Content.Shared.NameModifier.EntitySystems;
4848
#endregion Starlight
4949

5050
namespace Content.Shared.Silicons.StationAi;
@@ -79,6 +79,7 @@ public abstract partial class SharedStationAiSystem : EntitySystem
7979
[Dependency] private MobStateSystem _mobState = default!;
8080
[Dependency] private SharedDeviceLinkSystem _deviceLinkSystem = default!; // Starlight
8181
[Dependency] private StarlightEntitySystem _entitySystem = default!; // Starlight
82+
[Dependency] private NameModifierSystem _nameModifier = default!; // Starlight-edit
8283

8384
// StationAiHeld is added to anything inside of an AI core.
8485
// StationAiHolder indicates it can hold an AI positronic brain (e.g. holocard / core).
@@ -284,15 +285,24 @@ private void IntellicardTransfer(EntityUid uid, StationAiHolderComponent? compon
284285
if (args.Args.Target == null) // Starlight-edit
285286
return;
286287

287-
if (!TryComp(args.Args.Target.Value, out StationAiHolderComponent? targetHolder)) // Starlight-edit
288+
var target = args.Args.Target.Value;
289+
if (TryComp<BorgChassisComponent>(target, out var chassis) && chassis.BrainEntity is { } chassisBrain)
290+
target = chassisBrain;
291+
292+
if (!TryComp(target, out StationAiHolderComponent? targetHolder) &&
293+
!HasComp<BorgBrainComponent>(target)) // Starlight-edit
288294
return;
289295

290296
// Starlight-start
291297

292298
var isBorg = HasComp<BorgBrainComponent>(uid);
293-
var borgHaveMind = TryComp<MindContainerComponent>(uid, out var mindContainer) && _mind.GetMind(uid, mindContainer) != null;
294-
var isBorgTarget = HasComp<BorgBrainComponent>(args.Args.Target.Value);
295-
var borgHaveMindTarget = TryComp<MindContainerComponent>(args.Args.Target.Value, out var targetMindContainer) && _mind.GetMind(args.Args.Target.Value, targetMindContainer) != null;
299+
var borgMind = uid; // Starlight-edit
300+
if (isBorg && _containers.TryGetContainingContainer(uid, out var borgContainer) &&
301+
TryComp<BorgChassisComponent>(borgContainer.Owner, out _)) // Starlight-edit
302+
borgMind = borgContainer.Owner; // Starlight-edit
303+
var borgHaveMind = TryComp<MindContainerComponent>(borgMind, out var mindContainer) && _mind.GetMind(borgMind, mindContainer) != null; // Starlight-edit
304+
var isBorgTarget = HasComp<BorgBrainComponent>(target);
305+
var borgHaveMindTarget = TryComp<MindContainerComponent>(target, out var targetMindContainer) && _mind.GetMind(target, targetMindContainer) != null;
296306

297307
// basically if the AI is off shunting we wanna force them BACK. simplest way to do that is to fake the event to send them back.
298308
var slot = component?.Slot;
@@ -301,43 +311,74 @@ private void IntellicardTransfer(EntityUid uid, StationAiHolderComponent? compon
301311
// Starlight-end
302312

303313
// Try to insert our thing into them
304-
if (slot != null && _slots.CanEject(uid, args.User, slot)) // Starlight-edit
314+
if (targetHolder != null && slot != null && _slots.CanEject(uid, args.User, slot)) // Starlight-edit
305315
{
306-
if (!_slots.TryInsert(args.Args.Target.Value, targetHolder.Slot, slot.Item!.Value, args.User, excludeUserAudio: true)) // Starlight-edit
307-
{
316+
if (!_slots.TryInsert(target, targetHolder.Slot, slot.Item!.Value, args.User, excludeUserAudio: true)) // Starlight-edit
308317
return;
309-
}
310318

311319
args.Handled = true;
312320
return;
313321
}
314322
// Starlight-start: borgs can be downloaded/uploaded
315-
else if (isBorgTarget && borgHaveMindTarget && slot?.ContainerSlot is { } containerSlot && containerSlot.ContainedEntity != null)
323+
else if (isBorgTarget && !borgHaveMindTarget && slot?.ContainerSlot is { } containerSlot &&
324+
containerSlot.ContainedEntity is { } aiEntity)
316325
{
317-
_mind.ControlMob(args.Args.Target.Value, uid);
318-
Del(containerSlot.ContainedEntity);
326+
if (!_mind.TryGetMind(aiEntity, out var mindId, out var mind))
327+
return;
328+
329+
_mind.TransferTo(mindId, target, ghostCheckOverride: true, mind: mind);
330+
Del(aiEntity);
331+
args.Handled = true;
332+
return;
319333
}
320334
// Starlight-end
321335

322-
// Otherwise try to take from them
323-
if (slot != null && _slots.CanEject(args.Args.Target.Value, args.User, targetHolder.Slot)) // Starlight-edit
336+
// Starlight-start: Otherwise try to take from them
337+
if (targetHolder != null && slot != null && _slots.CanEject(target, args.User, targetHolder.Slot))
338+
{
339+
var held = targetHolder.Slot.Item!.Value;
340+
_metadata.SetEntityName(held, _nameModifier.GetBaseName(held), raiseEvents: false);
341+
if (!_slots.TryInsert(uid, slot, held, args.User, excludeUserAudio: true))
342+
return;
343+
args.Handled = true;
344+
}
345+
// Starlight: borgs can be downloaded/uploaded
346+
else if (targetHolder != null && isBorg && !borgHaveMind && targetHolder.Slot.Item is { } aiEntity)
324347
{
325-
if (!_slots.TryInsert(uid, slot, targetHolder.Slot.Item!.Value, args.User, excludeUserAudio: true)) // Starlight-edit
348+
if (!_mind.TryGetMind(aiEntity, out var mindId, out var mind))
326349
{
327350
return;
328351
}
329352

353+
var name = _nameModifier.GetBaseName(aiEntity);
354+
_metadata.SetEntityName(uid, name);
355+
_metadata.SetEntityName(borgMind, name);
356+
_mind.TransferTo(mindId, uid, ghostCheckOverride: true, mind: mind);
357+
Del(aiEntity);
330358
args.Handled = true;
359+
return;
331360
}
332-
// Starlight-start: borgs can be downloaded/uploaded
333-
else if (isBorg && borgHaveMind && targetHolder.Slot.ContainerSlot != null)
361+
else if (targetHolder != null && isBorg && borgHaveMind && targetHolder.Slot.ContainerSlot != null)
334362
{
335-
var brain = SpawnInContainerOrDrop(DefaultAi, args.Args.Target.Value, targetHolder.Slot.ContainerSlot.ID);
336-
_mind.ControlMob(uid, brain);
363+
var brain = SpawnInContainerOrDrop(DefaultAi, target, targetHolder.Slot.ContainerSlot.ID);
364+
if (!_mind.TryGetMind(borgMind, out var mindId, out var mind))
365+
return;
366+
var name = _nameModifier.GetBaseName(borgMind);
367+
_metadata.SetEntityName(brain, name);
368+
_metadata.SetEntityName(target, name);
369+
_mind.TransferTo(mindId, brain, ghostCheckOverride: true, mind: mind);
370+
ResetNameToPrototype(uid);
337371
}
338372
// Starlight-end
339373
}
340374

375+
// Starlight: wipe the name of the entity to the prototype name, used for entities when they are downloaded/uploaded
376+
private void ResetNameToPrototype(EntityUid entity)
377+
{
378+
if (MetaData(entity).EntityPrototype is { } prototype)
379+
_metadata.SetEntityName(entity, prototype.Name);
380+
}
381+
341382
private void OnHolderInteract(Entity<StationAiHolderComponent> ent, ref AfterInteractEvent args)
342383
{
343384
if (args.Handled || !args.CanReach || args.Target == null)
@@ -359,9 +400,22 @@ private void OnHolderInteract(Entity<StationAiHolderComponent> ent, ref AfterInt
359400

360401
// Starlight-start: Downloadable borgs
361402

362-
var isBorg = HasComp<BorgBrainComponent>(args.Target.Value);
363-
var isShunted = TryComp<StationAIShuntComponent>(args.Target.Value, out var shunt) && shunt.Return != null;
364-
var borgHaveMind = TryComp<MindContainerComponent>(args.Target.Value, out var mindContainer) && mindContainer.HasMind;
403+
var borgTarget = args.Target.Value;
404+
var borgMindTarget = borgTarget; // Starlight-edit
405+
if (TryComp<BorgChassisComponent>(borgTarget, out var chassis) && chassis.BrainEntity is { } chassisBrain)
406+
borgTarget = chassisBrain;
407+
408+
var isBorg = HasComp<BorgBrainComponent>(borgTarget);
409+
var isShunted = TryComp<StationAIShuntComponent>(borgTarget, out var shunt) && shunt.Return != null;
410+
var borgHaveMind = TryComp<MindContainerComponent>(borgMindTarget, out var mindContainer) && mindContainer.HasMind; // Starlight-edit
411+
412+
if (targetHolder == null && !isBorg)
413+
{
414+
var message = cardHasAi ? "intellicard-cannot-transfer-to" : "intellicard-core-empty";
415+
_popup.PopupClient(Loc.GetString(message), args.User, args.User, PopupType.Medium);
416+
args.Handled = true;
417+
return;
418+
}
365419

366420
// Starlight-end
367421

@@ -399,7 +453,11 @@ private void OnHolderInteract(Entity<StationAiHolderComponent> ent, ref AfterInt
399453
}
400454
// Starlight-end
401455

402-
var doAfterArgs = new DoAfterArgs(EntityManager, args.User, cardHasAi ? intelliComp.UploadTime : intelliComp.DownloadTime, new IntellicardDoAfterEvent(), args.Target, ent.Owner)
456+
var doAfterTarget = args.Target.Value;
457+
if (TryComp<BorgChassisComponent>(doAfterTarget, out var doAfterChassis) && doAfterChassis.BrainEntity is { } doAfterBrain)
458+
doAfterTarget = doAfterBrain;
459+
460+
var doAfterArgs = new DoAfterArgs(EntityManager, args.User, cardHasAi ? intelliComp.UploadTime : intelliComp.DownloadTime, new IntellicardDoAfterEvent(), doAfterTarget, ent.Owner)
403461
{
404462
BreakOnDamage = true,
405463
BreakOnMove = true,
@@ -433,7 +491,7 @@ private void OnHolderConInsert(Entity<StationAiHolderComponent> ent, ref EntInse
433491
UpdateAppearance((ent.Owner, ent.Comp));
434492

435493
if (ent.Comp.RenameOnInsert)
436-
_metadata.SetEntityName(ent.Owner, MetaData(args.Entity).EntityName);
494+
_metadata.SetEntityName(ent.Owner, _nameModifier.GetBaseName(args.Entity)); // Starlight-edit
437495
}
438496

439497
private void OnHolderConRemove(Entity<StationAiHolderComponent> ent, ref EntRemovedFromContainerMessage args)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
intellicard-cannot-transfer-to = Target cannot receive a digital consciousness.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
name-identifier-format-intellicard = IC-{$number}

Resources/Prototypes/Entities/Mobs/Player/silicon.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,11 @@
174174
Rebooting: { state: dead }
175175
Dead: { state: dead }
176176
- type: Intellicard
177-
- type: ForceQuickDraw #Starlight don't pull the posi-brain out when the intelecard is in a pocket and hotkey used to bring it to a player hand
177+
# Starlight-start
178+
- type: NameIdentifier # Added to give intellicards unique identifiers
179+
group: Intellicard
180+
- type: ForceQuickDraw # Don't pull the posi-brain out when the intelecard is in a pocket and hotkey used to bring it to a player hand
181+
# Starlight-end
178182

179183
- type: entity
180184
id: PlayerStationAiPreview
@@ -360,6 +364,10 @@
360364
- type: ContainerSpawnPoint
361365
containerId: station_ai_mind_slot
362366
job: StationAi
367+
# Starlight-start
368+
- type: NameIdentifier
369+
group: StationAi
370+
# Starlight-end
363371

364372
# The station AI core assembly
365373
- type: entity
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
- type: nameIdentifierGroup
2+
id: Intellicard #Starlight: Adding Intellicard name identifier
3+
format: name-identifier-format-intellicard
4+
minValue: 100
5+
maxValue: 999

0 commit comments

Comments
 (0)