Role Types (#33420)
* mindcomponent namespace * wip MindRole stuff * admin player tab * mindroletype comment * mindRolePrototype redesign * broken param * wip RoleType implementation * basic role type switching for antags * traitor fix * fix AdminPanel update * the renameningTM * cleanup * feature uncreeping * roletypes on mind roles * update MindComponent.RoleType when MindRoles change * ghostrole configuration * ghostrole config improvements * live update of roleType on the character window * logging stuff and notes * remove thing no one asked for * weh * Mind Role Entities wip * headrev count fix * silicon stuff, cleanup * exclusive antag config, cleanup * jobroleadd overwerite * logging stuff * MindHasRole cleanup, admin log stuff * last second cleanup * ocd * move roletypeprototype to its own file, minor note stuff * remove Roletype.Created * log stuff * roletype setup for ghostroles and autotraitor reinforcements * ghostrole type configs * adjustable admin overlay * cleanup * fix this in its own PR * silicon antagonist * borg stuff * mmi roletype handling * spawnable borg roletype handling * weh * ghost role cleanup * weh * RoleEvent update * polish * log stuff * admin overlay config * ghostrolecomponent cleanup * weh * admin overlay code cleanup * minor cleanup * Obsolete MindRoleAddedEvent * comment * minor code cleanup * MindOnDoGreeting fix * Role update message * fix duplicate job greeting for cyborgs * fix emag job message dupe * nicer-looking role type update * crew aligned * syndicate assault borg role fix * fix test fail * fix a merge mistake * fix LoneOp role type * Update Content.Client/Administration/AdminNameOverlay.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Content.Shared/Roles/SharedRoleSystem.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * comment formatting Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * change logging category Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * fix a space Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * use MindAddRoles Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * get MindComponent from TryGetMind Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * move var declaration outside loop * remove TryComp * take RoleEnum behind the barn * don't use ensurecomp unnecessarily * cvar comments * toggleableghostrolecomponent documentation * skrek * use EntProtoId * mindrole config * merge baserolecomponent into basemindrolecomponent * ai and borg silicon role tweaks * formatting Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * I will end you (the color) Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * use LocId type for a locale id * update RoleEvent documentation * update RoleEvent documentation * remove obsolete MindRoleAddedEvent * refine MindRolesUpdate() * use dependency Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * inject dependency Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * roleType.Name no longer required * reformatted draw code logic * GhostRoleMarkerRoleComponent comment * minor SharedRoleSystem cleanup * StartingMindRoleComponent, unhardcode roundstart silicon * Update Content.Shared/Roles/SharedRoleSystem.cs * remove a whitespace --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
This commit is contained in:
@@ -17,7 +17,6 @@ using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Inventory;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.PDA;
|
||||
using Content.Shared.Players;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Roles;
|
||||
@@ -32,6 +31,7 @@ using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Administration.Systems;
|
||||
|
||||
@@ -48,6 +48,7 @@ public sealed class AdminSystem : EntitySystem
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly PhysicsSystem _physics = default!;
|
||||
[Dependency] private readonly PlayTimeTrackingManager _playTime = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly SharedRoleSystem _role = default!;
|
||||
[Dependency] private readonly GameTicker _gameTicker = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
@@ -165,7 +166,8 @@ public sealed class AdminSystem : EntitySystem
|
||||
private void OnRoleEvent(RoleEvent ev)
|
||||
{
|
||||
var session = _minds.GetSession(ev.Mind);
|
||||
if (!ev.Antagonist || session == null)
|
||||
|
||||
if (!ev.RoleTypeUpdate || session == null)
|
||||
return;
|
||||
|
||||
UpdatePlayerList(session);
|
||||
@@ -239,9 +241,16 @@ public sealed class AdminSystem : EntitySystem
|
||||
}
|
||||
|
||||
var antag = false;
|
||||
|
||||
RoleTypePrototype roleType = new();
|
||||
var startingRole = string.Empty;
|
||||
if (_minds.TryGetMind(session, out var mindId, out _))
|
||||
if (_minds.TryGetMind(session, out var mindId, out var mindComp))
|
||||
{
|
||||
if (_proto.TryIndex(mindComp.RoleType, out var role))
|
||||
roleType = role;
|
||||
else
|
||||
Log.Error($"{ToPrettyString(mindId)} has invalid Role Type '{mindComp.RoleType}'. Displaying '{Loc.GetString(roleType.Name)}' instead");
|
||||
|
||||
antag = _role.MindIsAntagonist(mindId);
|
||||
startingRole = _jobs.MindTryGetJobName(mindId);
|
||||
}
|
||||
@@ -255,7 +264,7 @@ public sealed class AdminSystem : EntitySystem
|
||||
overallPlaytime = playTime;
|
||||
}
|
||||
|
||||
return new PlayerInfo(name, entityName, identityName, startingRole, antag, GetNetEntity(session?.AttachedEntity), data.UserId,
|
||||
return new PlayerInfo(name, entityName, identityName, startingRole, antag, roleType, GetNetEntity(session?.AttachedEntity), data.UserId,
|
||||
connected, _roundActivePlayers.Contains(data.UserId), overallPlaytime);
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ public partial struct AntagSelectionDefinition()
|
||||
/// List of Mind Role Prototypes to be added to the player's mind.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<ProtoId<EntityPrototype>>? MindRoles;
|
||||
public List<EntProtoId>? MindRoles;
|
||||
|
||||
/// <summary>
|
||||
/// A set of starting gear that's equipped to the player.
|
||||
|
||||
@@ -222,8 +222,6 @@ namespace Content.Server.GameTicking
|
||||
_mind.SetUserId(newMind, data.UserId);
|
||||
|
||||
var jobPrototype = _prototypeManager.Index<JobPrototype>(jobId);
|
||||
_roles.MindAddJobRole(newMind, silent: silent, jobPrototype:jobId);
|
||||
var jobName = _jobs.MindTryGetJobName(newMind);
|
||||
|
||||
_playTimeTrackings.PlayerRolesChanged(player);
|
||||
|
||||
@@ -233,6 +231,9 @@ namespace Content.Server.GameTicking
|
||||
|
||||
_mind.TransferTo(newMind, mob);
|
||||
|
||||
_roles.MindAddJobRole(newMind, silent: silent, jobPrototype:jobId);
|
||||
var jobName = _jobs.MindTryGetJobName(newMind);
|
||||
|
||||
if (lateJoin && !silent)
|
||||
{
|
||||
if (jobPrototype.JoinNotifyCrew)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
namespace Content.Server.Ghost;
|
||||
using Content.Shared.Roles;
|
||||
|
||||
namespace Content.Server.Ghost;
|
||||
|
||||
/// <summary>
|
||||
/// This is used to mark Observers properly, as they get Minds
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class ObserverRoleComponent : Component
|
||||
public sealed partial class ObserverRoleComponent : BaseMindRoleComponent
|
||||
{
|
||||
public string Name => Loc.GetString("observer-role-name");
|
||||
}
|
||||
|
||||
@@ -72,12 +72,16 @@ public sealed partial class GhostRoleComponent : Component
|
||||
}
|
||||
}
|
||||
|
||||
[DataField("allowSpeech")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
/// <summary>
|
||||
/// The mind roles that will be added to the mob's mind entity
|
||||
/// </summary>
|
||||
[DataField, Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // Don't make eye contact
|
||||
public List<EntProtoId> MindRoles = new() { "MindRoleGhostRoleNeutral" };
|
||||
|
||||
[DataField]
|
||||
public bool AllowSpeech { get; set; } = true;
|
||||
|
||||
[DataField("allowMovement")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public bool AllowMovement { get; set; }
|
||||
|
||||
[ViewVariables(VVAccess.ReadOnly)]
|
||||
@@ -107,3 +111,4 @@ public sealed partial class GhostRoleComponent : Component
|
||||
[Access(typeof(GhostRoleSystem), Other = AccessPermissions.ReadWriteExecute)] // also FIXME Friends
|
||||
public ProtoId<JobPrototype>? JobProto = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,39 +9,81 @@ namespace Content.Server.Ghost.Roles.Components;
|
||||
[RegisterComponent, Access(typeof(ToggleableGhostRoleSystem))]
|
||||
public sealed partial class ToggleableGhostRoleComponent : Component
|
||||
{
|
||||
[DataField("examineTextMindPresent")]
|
||||
/// <summary>
|
||||
/// The text shown on the entity's Examine when it is controlled by a player
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string ExamineTextMindPresent = string.Empty;
|
||||
|
||||
[DataField("examineTextMindSearching")]
|
||||
/// <summary>
|
||||
/// The text shown on the entity's Examine when it is waiting for a controlling player
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string ExamineTextMindSearching = string.Empty;
|
||||
|
||||
[DataField("examineTextNoMind")]
|
||||
/// <summary>
|
||||
/// The text shown on the entity's Examine when it has no controlling player
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string ExamineTextNoMind = string.Empty;
|
||||
|
||||
[DataField("beginSearchingText")]
|
||||
/// <summary>
|
||||
/// The popup text when the entity (PAI/positronic brain) it is activated to seek a controlling player
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string BeginSearchingText = string.Empty;
|
||||
|
||||
[DataField("roleName")]
|
||||
/// <summary>
|
||||
/// The name shown on the Ghost Role list
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string RoleName = string.Empty;
|
||||
|
||||
[DataField("roleDescription")]
|
||||
/// <summary>
|
||||
/// The description shown on the Ghost Role list
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string RoleDescription = string.Empty;
|
||||
|
||||
[DataField("roleRules")]
|
||||
/// <summary>
|
||||
/// The introductory message shown when trying to take the ghost role/join the raffle
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string RoleRules = string.Empty;
|
||||
|
||||
[DataField("wipeVerbText")]
|
||||
/// <summary>
|
||||
/// A list of mind roles that will be added to the entity's mind
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public List<EntProtoId> MindRoles;
|
||||
|
||||
/// <summary>
|
||||
/// The displayed name of the verb to wipe the controlling player
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string WipeVerbText = string.Empty;
|
||||
|
||||
[DataField("wipeVerbPopup")]
|
||||
/// /// <summary>
|
||||
/// The popup message when wiping the controlling player
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string WipeVerbPopup = string.Empty;
|
||||
|
||||
[DataField("stopSearchVerbText")]
|
||||
/// <summary>
|
||||
/// The displayed name of the verb to stop searching for a controlling player
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string StopSearchVerbText = string.Empty;
|
||||
|
||||
[DataField("stopSearchVerbPopup")]
|
||||
/// /// <summary>
|
||||
/// The popup message when stopping to search for a controlling player
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string StopSearchVerbPopup = string.Empty;
|
||||
|
||||
/// /// <summary>
|
||||
/// The prototype ID of the job that will be given to the controlling mind
|
||||
/// </summary>
|
||||
[DataField("job")]
|
||||
public ProtoId<JobPrototype>? JobProto = null;
|
||||
public ProtoId<JobPrototype>? JobProto;
|
||||
}
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
namespace Content.Server.Ghost.Roles;
|
||||
|
||||
/// <summary>
|
||||
/// This is used for round end display of ghost roles.
|
||||
/// It may also be used to ensure some ghost roles count as antagonists in future.
|
||||
/// Added to mind role entities to tag that they are a ghostrole.
|
||||
/// It also holds the name for the round end display
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class GhostRoleMarkerRoleComponent : BaseMindRoleComponent
|
||||
{
|
||||
[DataField("name")] public string? Name;
|
||||
//TODO does anything still use this? It gets populated by GhostRolesystem but I don't see anything ever reading it
|
||||
[DataField] public string? Name;
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ using Content.Server.Popups;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Collections;
|
||||
using Content.Shared.Ghost.Roles.Components;
|
||||
using Content.Shared.Roles.Jobs;
|
||||
|
||||
namespace Content.Server.Ghost.Roles;
|
||||
|
||||
@@ -514,13 +513,13 @@ public sealed class GhostRoleSystem : EntitySystem
|
||||
var newMind = _mindSystem.CreateMind(player.UserId,
|
||||
EntityManager.GetComponent<MetaDataComponent>(mob).EntityName);
|
||||
|
||||
_roleSystem.MindAddRole(newMind, "MindRoleGhostMarker");
|
||||
|
||||
if(_roleSystem.MindHasRole<GhostRoleMarkerRoleComponent>(newMind!, out var markerRole))
|
||||
markerRole.Value.Comp2.Name = role.RoleName;
|
||||
|
||||
_mindSystem.SetUserId(newMind, player.UserId);
|
||||
_mindSystem.TransferTo(newMind, mob);
|
||||
|
||||
_roleSystem.MindAddRoles(newMind.Owner, role.MindRoles, newMind.Comp);
|
||||
|
||||
if (_roleSystem.MindHasRole<GhostRoleMarkerRoleComponent>(newMind!, out var markerRole))
|
||||
markerRole.Value.Comp2.Name = role.RoleName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -51,10 +51,13 @@ public sealed class ToggleableGhostRoleSystem : EntitySystem
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
private void OnExamined(EntityUid uid, ToggleableGhostRoleComponent component, ExaminedEvent args)
|
||||
|
||||
@@ -49,8 +49,8 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(OnRoundEnd);
|
||||
SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttached);
|
||||
SubscribeLocalEvent<PlayerDetachedEvent>(OnPlayerDetached);
|
||||
SubscribeLocalEvent<RoleAddedEvent>(OnRoleAdd);
|
||||
SubscribeLocalEvent<RoleRemovedEvent>(OnRoleRemove);
|
||||
SubscribeLocalEvent<RoleAddedEvent>(OnRoleEvent);
|
||||
SubscribeLocalEvent<RoleRemovedEvent>(OnRoleEvent);
|
||||
SubscribeLocalEvent<AFKEvent>(OnAFK);
|
||||
SubscribeLocalEvent<UnAFKEvent>(OnUnAFK);
|
||||
SubscribeLocalEvent<MobStateChangedEvent>(OnMobStateChanged);
|
||||
@@ -121,13 +121,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem
|
||||
return GetTimedRoles(contentData.Mind.Value);
|
||||
}
|
||||
|
||||
private void OnRoleRemove(RoleRemovedEvent ev)
|
||||
{
|
||||
if (_minds.TryGetSession(ev.Mind, out var session))
|
||||
_tracking.QueueRefreshTrackers(session);
|
||||
}
|
||||
|
||||
private void OnRoleAdd(RoleAddedEvent ev)
|
||||
private void OnRoleEvent(RoleEvent ev)
|
||||
{
|
||||
if (_minds.TryGetSession(ev.Mind, out var session))
|
||||
_tracking.QueueRefreshTrackers(session);
|
||||
|
||||
@@ -19,10 +19,25 @@ public sealed class JobSystem : SharedJobSystem
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<MindComponent, MindRoleAddedEvent>(MindOnDoGreeting);
|
||||
SubscribeLocalEvent<RoleAddedEvent>(OnRoleAddedEvent);
|
||||
SubscribeLocalEvent<RoleRemovedEvent>(OnRoleRemovedEvent);
|
||||
}
|
||||
|
||||
private void MindOnDoGreeting(EntityUid mindId, MindComponent component, ref MindRoleAddedEvent args)
|
||||
private void OnRoleAddedEvent(RoleAddedEvent args)
|
||||
{
|
||||
MindOnDoGreeting(args.MindId, args.Mind, args);
|
||||
|
||||
if (args.RoleTypeUpdate)
|
||||
_roles.RoleUpdateMessage(args.Mind);
|
||||
}
|
||||
|
||||
private void OnRoleRemovedEvent(RoleRemovedEvent args)
|
||||
{
|
||||
if (args.RoleTypeUpdate)
|
||||
_roles.RoleUpdateMessage(args.Mind);
|
||||
}
|
||||
|
||||
private void MindOnDoGreeting(EntityUid mindId, MindComponent component, RoleAddedEvent args)
|
||||
{
|
||||
if (args.Silent)
|
||||
return;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
namespace Content.Server.Roles;
|
||||
using Content.Shared.Roles;
|
||||
|
||||
namespace Content.Server.Roles;
|
||||
|
||||
/// <summary>
|
||||
/// Adds a briefing to the character info menu, does nothing else.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public sealed partial class RoleBriefingComponent : Component
|
||||
public sealed partial class RoleBriefingComponent : BaseMindRoleComponent
|
||||
{
|
||||
[DataField("briefing"), ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField]
|
||||
public string Briefing;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
using Content.Server.Chat.Managers;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Mind;
|
||||
using Content.Shared.Roles;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Roles;
|
||||
|
||||
public sealed class RoleSystem : SharedRoleSystem
|
||||
{
|
||||
[Dependency] private readonly IChatManager _chat = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
|
||||
public string? MindGetBriefing(EntityUid? mindId)
|
||||
{
|
||||
if (mindId == null)
|
||||
@@ -37,6 +43,32 @@ public sealed class RoleSystem : SharedRoleSystem
|
||||
|
||||
return ev.Briefing;
|
||||
}
|
||||
|
||||
public void RoleUpdateMessage(MindComponent mind)
|
||||
{
|
||||
if (mind.Session is null)
|
||||
return;
|
||||
|
||||
if (!_proto.TryIndex(mind.RoleType, out var proto))
|
||||
return;
|
||||
|
||||
var roleText = Loc.GetString(proto.Name);
|
||||
var color = proto.Color;
|
||||
|
||||
var session = mind.Session;
|
||||
|
||||
//TODO add audio? Would need to be optional so it does not play on role changes that already come with their own audio
|
||||
// _audio.PlayGlobal(Sound, session);
|
||||
|
||||
var message = Loc.GetString("role-type-update-message", ("color", color), ("role", roleText));
|
||||
var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", message));
|
||||
_chat.ChatMessageToOne(ChatChannel.Server,
|
||||
message,
|
||||
wrappedMessage,
|
||||
default,
|
||||
false,
|
||||
session.Channel);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Server.Roles;
|
||||
using Content.Shared.Containers.ItemSlots;
|
||||
using Content.Shared.Mind.Components;
|
||||
using Content.Shared.Roles;
|
||||
using Content.Shared.Silicons.Borgs.Components;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
@@ -8,6 +10,9 @@ namespace Content.Server.Silicons.Borgs;
|
||||
/// <inheritdoc/>
|
||||
public sealed partial class BorgSystem
|
||||
{
|
||||
|
||||
[Dependency] private readonly SharedRoleSystem _roles = default!;
|
||||
|
||||
public void InitializeMMI()
|
||||
{
|
||||
SubscribeLocalEvent<MMIComponent, ComponentInit>(OnMMIInit);
|
||||
@@ -41,8 +46,13 @@ public sealed partial class BorgSystem
|
||||
Dirty(uid, component);
|
||||
|
||||
if (_mind.TryGetMind(ent, out var mindId, out var mind))
|
||||
{
|
||||
_mind.TransferTo(mindId, uid, true, mind: mind);
|
||||
|
||||
if (!_roles.MindHasRole<SiliconBrainRoleComponent>(mindId))
|
||||
_roles.MindAddRole(mindId, "MindRoleSiliconBrain", silent: true);
|
||||
}
|
||||
|
||||
_appearance.SetData(uid, MMIVisuals.BrainPresent, true);
|
||||
}
|
||||
|
||||
@@ -75,7 +85,12 @@ public sealed partial class BorgSystem
|
||||
RemComp(uid, component);
|
||||
|
||||
if (_mind.TryGetMind(linked, out var mindId, out var mind))
|
||||
{
|
||||
if (_roles.MindHasRole<SiliconBrainRoleComponent>(mindId))
|
||||
_roles.MindRemoveRole<SiliconBrainRoleComponent>(mindId);
|
||||
|
||||
_mind.TransferTo(mindId, uid, true, mind: mind);
|
||||
}
|
||||
|
||||
_appearance.SetData(linked, MMIVisuals.BrainPresent, false);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using Content.Server.DeviceNetwork.Systems;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Hands.Systems;
|
||||
using Content.Server.PowerCell;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.IdentityManagement;
|
||||
|
||||
@@ -193,7 +193,7 @@ public sealed class SiliconLawSystem : SharedSiliconLawSystem
|
||||
private void EnsureSubvertedSiliconRole(EntityUid mindId)
|
||||
{
|
||||
if (!_roles.MindHasRole<SubvertedSiliconRoleComponent>(mindId))
|
||||
_roles.MindAddRole(mindId, "MindRoleSubvertedSilicon");
|
||||
_roles.MindAddRole(mindId, "MindRoleSubvertedSilicon", silent: true);
|
||||
}
|
||||
|
||||
private void RemoveSubvertedSiliconRole(EntityUid mindId)
|
||||
|
||||
Reference in New Issue
Block a user