Files
tbd-station-14/Content.Server/Ghost/Roles/ToggleableGhostRoleSystem.cs
Errant 46d58bf22a 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>
2025-01-11 22:17:26 +01:00

165 lines
6.3 KiB
C#

using Content.Server.Ghost.Roles.Components;
using Content.Shared.Examine;
using Content.Shared.Interaction.Events;
using Content.Shared.Mind;
using Content.Shared.Mind.Components;
using Content.Shared.Popups;
using Content.Shared.Verbs;
namespace Content.Server.Ghost.Roles;
/// <summary>
/// This handles logic and interaction related to <see cref="ToggleableGhostRoleComponent"/>
/// </summary>
public sealed class ToggleableGhostRoleSystem : EntitySystem
{
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedMindSystem _mind = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<ToggleableGhostRoleComponent, UseInHandEvent>(OnUseInHand);
SubscribeLocalEvent<ToggleableGhostRoleComponent, ExaminedEvent>(OnExamined);
SubscribeLocalEvent<ToggleableGhostRoleComponent, MindAddedMessage>(OnMindAdded);
SubscribeLocalEvent<ToggleableGhostRoleComponent, MindRemovedMessage>(OnMindRemoved);
SubscribeLocalEvent<ToggleableGhostRoleComponent, GetVerbsEvent<ActivationVerb>>(AddWipeVerb);
}
private void OnUseInHand(EntityUid uid, ToggleableGhostRoleComponent component, UseInHandEvent args)
{
if (args.Handled)
return;
args.Handled = true;
// check if a mind is present
if (TryComp<MindContainerComponent>(uid, out var mind) && mind.HasMind)
{
_popup.PopupEntity(Loc.GetString(component.ExamineTextMindPresent), uid, args.User, PopupType.Large);
return;
}
if (HasComp<GhostTakeoverAvailableComponent>(uid))
{
_popup.PopupEntity(Loc.GetString(component.ExamineTextMindSearching), uid, args.User);
return;
}
_popup.PopupEntity(Loc.GetString(component.BeginSearchingText), uid, args.User);
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;
}
private void OnExamined(EntityUid uid, ToggleableGhostRoleComponent component, ExaminedEvent args)
{
if (!args.IsInDetailsRange)
return;
if (TryComp<MindContainerComponent>(uid, out var mind) && mind.HasMind)
{
args.PushMarkup(Loc.GetString(component.ExamineTextMindPresent));
}
else if (HasComp<GhostTakeoverAvailableComponent>(uid))
{
args.PushMarkup(Loc.GetString(component.ExamineTextMindSearching));
}
else
{
args.PushMarkup(Loc.GetString(component.ExamineTextNoMind));
}
}
private void OnMindAdded(EntityUid uid, ToggleableGhostRoleComponent pai, MindAddedMessage args)
{
// Mind was added, shutdown the ghost role stuff so it won't get in the way
RemCompDeferred<GhostTakeoverAvailableComponent>(uid);
UpdateAppearance(uid, ToggleableGhostRoleStatus.On);
}
private void OnMindRemoved(EntityUid uid, ToggleableGhostRoleComponent component, MindRemovedMessage args)
{
// Mind was removed, prepare for re-toggle of the role
RemCompDeferred<GhostRoleComponent>(uid);
UpdateAppearance(uid, ToggleableGhostRoleStatus.Off);
}
private void UpdateAppearance(EntityUid uid, ToggleableGhostRoleStatus status)
{
_appearance.SetData(uid, ToggleableGhostRoleVisuals.Status, status);
}
private void AddWipeVerb(EntityUid uid, ToggleableGhostRoleComponent component, GetVerbsEvent<ActivationVerb> args)
{
if (args.Hands == null || !args.CanAccess || !args.CanInteract)
return;
if (TryComp<MindContainerComponent>(uid, out var mind) && mind.HasMind)
{
ActivationVerb verb = new()
{
Text = Loc.GetString(component.WipeVerbText),
Act = () =>
{
if (!_mind.TryGetMind(uid, out var mindId, out var mind))
return;
// Wiping device :(
// The shutdown of the Mind should cause automatic reset of the pAI during OnMindRemoved
_mind.TransferTo(mindId, null, mind: mind);
_popup.PopupEntity(Loc.GetString(component.WipeVerbPopup), uid, args.User, PopupType.Large);
}
};
args.Verbs.Add(verb);
}
else if (HasComp<GhostTakeoverAvailableComponent>(uid))
{
ActivationVerb verb = new()
{
Text = Loc.GetString(component.StopSearchVerbText),
Act = () =>
{
if (component.Deleted || !HasComp<GhostTakeoverAvailableComponent>(uid))
return;
RemCompDeferred<GhostTakeoverAvailableComponent>(uid);
RemCompDeferred<GhostRoleComponent>(uid);
_popup.PopupEntity(Loc.GetString(component.StopSearchVerbPopup), uid, args.User);
UpdateAppearance(uid, ToggleableGhostRoleStatus.Off);
}
};
args.Verbs.Add(verb);
}
}
/// <summary>
/// If there is a player present, kicks it out.
/// If not, prevents future ghosts taking it.
/// No popups are made, but appearance is updated.
/// </summary>
public void Wipe(EntityUid uid)
{
if (TryComp<MindContainerComponent>(uid, out var mindContainer) &&
mindContainer.HasMind &&
_mind.TryGetMind(uid, out var mindId, out var mind))
{
_mind.TransferTo(mindId, null, mind: mind);
}
if (!HasComp<GhostTakeoverAvailableComponent>(uid))
return;
RemCompDeferred<GhostTakeoverAvailableComponent>(uid);
RemCompDeferred<GhostRoleComponent>(uid);
UpdateAppearance(uid, ToggleableGhostRoleStatus.Off);
}
}