mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 10:21:18 +03:00
allow changelings to drop stored disguises (#43487)
* drop option * popup and better icon
This commit is contained in:
parent
4f35ac5686
commit
a6ec5e7d3e
5 changed files with 115 additions and 29 deletions
|
|
@ -4,6 +4,7 @@ using Content.Shared.Changeling.Components;
|
|||
using Content.Shared.Changeling.Systems;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Changeling.UI;
|
||||
|
||||
|
|
@ -12,7 +13,9 @@ public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owne
|
|||
{
|
||||
private SimpleRadialMenu? _menu;
|
||||
private static readonly Color SelectedOptionBackground = Palettes.Green.Element.WithAlpha(128);
|
||||
private static readonly Color DisabledOptionBackground = Palettes.Slate.Element.WithAlpha(128);
|
||||
private static readonly Color SelectedOptionHoverBackground = Palettes.Green.HoveredElement.WithAlpha(128);
|
||||
private static readonly Color DisabledOptionHoverBackground = Palettes.Slate.HoveredElement.WithAlpha(128);
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
|
|
@ -42,21 +45,41 @@ public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owne
|
|||
)
|
||||
{
|
||||
var buttons = new List<RadialMenuOptionBase>();
|
||||
var dropButtons = new List<RadialMenuOptionBase>();
|
||||
|
||||
foreach (var identity in identities)
|
||||
{
|
||||
if (!EntMan.TryGetComponent<MetaDataComponent>(identity, out var metadata))
|
||||
continue;
|
||||
|
||||
// Options for selecting identities.
|
||||
var option = new RadialMenuActionOption<NetEntity>(SendIdentitySelect, EntMan.GetNetEntity(identity))
|
||||
{
|
||||
IconSpecifier = RadialMenuIconSpecifier.With(identity),
|
||||
ToolTip = metadata.EntityName,
|
||||
BackgroundColor = (currentIdentity == identity) ? SelectedOptionBackground : null,
|
||||
ToolTip = Loc.GetString("changeling-transform-bui-select-entity", ("entity", identity)),
|
||||
BackgroundColor = (currentIdentity == identity) ? SelectedOptionBackground : null, // mark as selected
|
||||
HoverBackgroundColor = (currentIdentity == identity) ? SelectedOptionHoverBackground : null
|
||||
};
|
||||
buttons.Add(option);
|
||||
|
||||
// Options for dropping identities.
|
||||
var dropOption = new RadialMenuActionOption<NetEntity>(SendIdentityDrop, EntMan.GetNetEntity(identity))
|
||||
{
|
||||
IconSpecifier = RadialMenuIconSpecifier.With(identity),
|
||||
ToolTip = (currentIdentity == identity)
|
||||
? Loc.GetString("changeling-transform-bui-drop-identity-cannot-drop")
|
||||
: Loc.GetString("changeling-transform-bui-drop-identity-entity", ("entity", identity)),
|
||||
BackgroundColor = (currentIdentity == identity) ? DisabledOptionBackground : null, // cannot drop your current identity
|
||||
HoverBackgroundColor = (currentIdentity == identity) ? DisabledOptionHoverBackground : null
|
||||
};
|
||||
dropButtons.Add(dropOption);
|
||||
}
|
||||
|
||||
// Menu category for dropping identities.
|
||||
var dropMenuButton = new RadialMenuNestedLayerOption(dropButtons)
|
||||
{
|
||||
IconSpecifier = RadialMenuIconSpecifier.With(new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/delete.svg.192dpi.png"))),
|
||||
ToolTip = Loc.GetString("changeling-transform-bui-drop-identity-menu")
|
||||
};
|
||||
buttons.Add(dropMenuButton);
|
||||
|
||||
return buttons;
|
||||
}
|
||||
|
||||
|
|
@ -64,4 +87,9 @@ public sealed partial class ChangelingTransformBoundUserInterface(EntityUid owne
|
|||
{
|
||||
SendPredictedMessage(new ChangelingTransformIdentitySelectMessage(identityId));
|
||||
}
|
||||
|
||||
private void SendIdentityDrop(NetEntity identityId)
|
||||
{
|
||||
SendPredictedMessage(new ChangelingTransformIdentityDropMessage(identityId));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,25 @@
|
|||
namespace Content.Shared.Changeling.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// Send when a player selects an intentity to transform into in the radial menu.
|
||||
/// Send when a player selects an identity to transform into in the radial menu.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ChangelingTransformIdentitySelectMessage(NetEntity targetIdentity) : BoundUserInterfaceMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// The uid of the cloned identity.
|
||||
/// The uid of the stored identity.
|
||||
/// </summary>
|
||||
public readonly NetEntity TargetIdentity = targetIdentity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send when a player selects an identity to drop from their storage.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class ChangelingTransformIdentityDropMessage(NetEntity targetIdentity) : BoundUserInterfaceMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// The uid of the stored identity.
|
||||
/// </summary>
|
||||
public readonly NetEntity TargetIdentity = targetIdentity;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
|
|||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly IdentitySystem _identity = default!;
|
||||
[Dependency] private readonly SharedChangelingIdentitySystem _changelingIdentity = default!;
|
||||
|
||||
private const string ChangelingBuiXmlGeneratedName = "ChangelingTransformBoundUserInterface";
|
||||
public override void Initialize()
|
||||
|
|
@ -38,8 +39,9 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
|
|||
|
||||
SubscribeLocalEvent<ChangelingTransformComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<ChangelingTransformComponent, ChangelingTransformActionEvent>(OnTransformAction);
|
||||
SubscribeLocalEvent<ChangelingTransformComponent, ChangelingTransformDoAfterEvent>(OnSuccessfulTransform);
|
||||
SubscribeLocalEvent<ChangelingTransformComponent, ChangelingTransformIdentitySelectMessage>(OnTransformSelected);
|
||||
SubscribeLocalEvent<ChangelingTransformComponent, ChangelingTransformIdentityDropMessage>(OnTransformDrop);
|
||||
SubscribeLocalEvent<ChangelingTransformComponent, ChangelingTransformDoAfterEvent>(OnSuccessfulTransform);
|
||||
SubscribeLocalEvent<ChangelingTransformComponent, ComponentShutdown>(OnShutdown);
|
||||
|
||||
// Components that need special handling outside of cloning.
|
||||
|
|
@ -79,6 +81,43 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
|
|||
// but pressing the number does.
|
||||
}
|
||||
|
||||
private void OnTransformSelected(Entity<ChangelingTransformComponent> ent,
|
||||
ref ChangelingTransformIdentitySelectMessage args)
|
||||
{
|
||||
if (!TryGetEntity(args.TargetIdentity, out var targetIdentity))
|
||||
return;
|
||||
|
||||
if (!TryComp<ChangelingIdentityComponent>(ent, out var identity))
|
||||
return;
|
||||
|
||||
if (identity.CurrentIdentity == targetIdentity)
|
||||
return; // don't transform into ourselves
|
||||
|
||||
if (!identity.ConsumedIdentities.ContainsKey(targetIdentity.Value))
|
||||
return; // this identity does not belong to this player
|
||||
|
||||
TransformInto(ent.AsNullable(), targetIdentity.Value);
|
||||
}
|
||||
|
||||
private void OnTransformDrop(Entity<ChangelingTransformComponent> ent,
|
||||
ref ChangelingTransformIdentityDropMessage args)
|
||||
{
|
||||
if (!TryGetEntity(args.TargetIdentity, out var targetIdentity))
|
||||
return;
|
||||
|
||||
if (!TryComp<ChangelingIdentityComponent>(ent, out var identity))
|
||||
return;
|
||||
|
||||
if (identity.CurrentIdentity == targetIdentity)
|
||||
return; // don't drop our current identity
|
||||
|
||||
if (!identity.ConsumedIdentities.ContainsKey(targetIdentity.Value))
|
||||
return; // this identity does not belong to this player
|
||||
|
||||
_popup.PopupClient(Loc.GetString("changeling-transform-bui-drop-identity-entity-popup", ("entity", targetIdentity.Value)), ent.Owner, PopupType.Large);
|
||||
_changelingIdentity.DropStoredIdentity(ent.Owner, targetIdentity.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform the changeling into another identity.
|
||||
/// This can be any cloneable humanoid and doesn't have to be stored in the ChangelingIdentityComponent,
|
||||
|
|
@ -125,26 +164,6 @@ public sealed partial class ChangelingTransformSystem : EntitySystem
|
|||
});
|
||||
}
|
||||
|
||||
private void OnTransformSelected(Entity<ChangelingTransformComponent> ent,
|
||||
ref ChangelingTransformIdentitySelectMessage args)
|
||||
{
|
||||
_ui.CloseUi(ent.Owner, ChangelingTransformUiKey.Key, ent);
|
||||
|
||||
if (!TryGetEntity(args.TargetIdentity, out var targetIdentity))
|
||||
return;
|
||||
|
||||
if (!TryComp<ChangelingIdentityComponent>(ent, out var identity))
|
||||
return;
|
||||
|
||||
if (identity.CurrentIdentity == targetIdentity)
|
||||
return; // don't transform into ourselves
|
||||
|
||||
if (!identity.ConsumedIdentities.ContainsKey(targetIdentity.Value))
|
||||
return; // this identity does not belong to this player
|
||||
|
||||
TransformInto(ent.AsNullable(), targetIdentity.Value);
|
||||
}
|
||||
|
||||
private void OnSuccessfulTransform(Entity<ChangelingTransformComponent> ent,
|
||||
ref ChangelingTransformDoAfterEvent args)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -184,6 +184,22 @@ public abstract class SharedChangelingIdentitySystem : EntitySystem
|
|||
return clone;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drop a stored identity from the changeling's storage.
|
||||
/// </summary>
|
||||
public void DropStoredIdentity(Entity<ChangelingIdentityComponent?> ent, EntityUid identity)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp))
|
||||
return;
|
||||
|
||||
if (!HasComp<ChangelingStoredIdentityComponent>(identity))
|
||||
return; // Not a stored identity.
|
||||
|
||||
PredictedQueueDel(identity);
|
||||
if (ent.Comp.ConsumedIdentities.Remove(identity))
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple helper to add a PVS override to a nullspace identity.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
roles-antag-changeling-name = Changeling
|
||||
# antag selection
|
||||
roles-antag-changeling-name = Changeling
|
||||
roles-antag-changeling-objective = A intelligent predator that assumes the identities of its victims.
|
||||
|
||||
# devour
|
||||
changeling-devour-attempt-failed-cannot-devour = We cannot devour this!
|
||||
changeling-devour-attempt-failed-already-devoured = We already consumed this body!
|
||||
changeling-devour-attempt-failed-not-dead = This body yet lives! We cannot consume it alive!
|
||||
|
|
@ -14,7 +16,16 @@ changeling-devour-begin-consume-others = { CAPITALIZE(POSS-ADJ($user)) } uncanny
|
|||
changeling-devour-consume-complete-self = Our uncanny mouth retreats, biomass consumed.
|
||||
changeling-devour-consume-complete-others = { CAPITALIZE(POSS-ADJ($user)) } uncanny mouth retreats.
|
||||
|
||||
# transformation
|
||||
changeling-transform-attempt-self = Our bones snap, muscles tear, one flesh becomes another.
|
||||
changeling-transform-attempt-others = { CAPITALIZE(POSS-ADJ($user)) } bones snap, muscles tear, body shifts into another.
|
||||
|
||||
# transformation BUI
|
||||
changeling-transform-bui-select-entity = {$entity}
|
||||
changeling-transform-bui-drop-identity-menu = Drop a devoured identity from your memory.
|
||||
changeling-transform-bui-drop-identity-entity = Drop {$entity}
|
||||
changeling-transform-bui-drop-identity-entity-popup = You dropped {$entity} from your memory.
|
||||
changeling-transform-bui-drop-identity-cannot-drop = You cannot drop your current identity.
|
||||
|
||||
# other
|
||||
changeling-paused-map-name = Changeling identity storage map
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue