[Feat] Внешний вид и название канистр можно изменить прямо в игре (#317)
* feat: Теперь можно менять внешний вид канистр газов * fix: русский язык (я его не знаю)
This commit is contained in:
@@ -0,0 +1,36 @@
|
|||||||
|
using Content.Shared._White.PolymorphableCanister;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client._White.PolymorphableCanister;
|
||||||
|
|
||||||
|
public sealed class PolymorphableCanisterSystem : SharedPolymorphableCanisterSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IComponentFactory _componentFactory = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<PolymorphableCanisterComponent, AfterAutoHandleStateEvent>(HandleState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleState(EntityUid uid,
|
||||||
|
PolymorphableCanisterComponent component,
|
||||||
|
ref AfterAutoHandleStateEvent args)
|
||||||
|
{
|
||||||
|
UpdateAppearance(uid, component.CurrentPrototype);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void UpdateSprite(EntityUid uid, EntityPrototype proto)
|
||||||
|
{
|
||||||
|
base.UpdateSprite(uid, proto);
|
||||||
|
|
||||||
|
if (!TryComp(uid, out SpriteComponent? sprite) ||
|
||||||
|
!proto.TryGetComponent(out SpriteComponent? otherSprite, _componentFactory))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite.CopyFrom(otherSprite);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Content.Shared._White.PolymorphableCanister;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
|
namespace Content.Client._White.PolymorphableCanister.UI;
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
public sealed class PolymorphableCanisterBUI : BoundUserInterface
|
||||||
|
{
|
||||||
|
private PolymorphableCanisterMenu? _menu;
|
||||||
|
|
||||||
|
public PolymorphableCanisterBUI(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Open()
|
||||||
|
{
|
||||||
|
_menu = new PolymorphableCanisterMenu(Owner, this);
|
||||||
|
_menu.OnClose += Close;
|
||||||
|
_menu.OpenCentered();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SendMessage(string protoId)
|
||||||
|
{
|
||||||
|
SendMessage(new PolymorphableCanisterMessage(protoId));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
base.Dispose(disposing);
|
||||||
|
if (!disposing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_menu?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<ui:RadialMenu xmlns="https://spacestation14.io"
|
||||||
|
xmlns:ui="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
|
BackButtonStyleClass="RadialMenuBackButton"
|
||||||
|
CloseButtonStyleClass="RadialMenuCloseButton"
|
||||||
|
VerticalExpand="True"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
MinSize="450 450">
|
||||||
|
|
||||||
|
<!-- Main container to hold all canister states-->
|
||||||
|
<ui:RadialContainer Name="Main" VerticalExpand="True" HorizontalExpand="True" Radius="140"
|
||||||
|
ReserveSpaceForHiddenChildren="False" />
|
||||||
|
</ui:RadialMenu>
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
using Content.Client.UserInterface.Controls;
|
||||||
|
using Content.Shared._White.PolymorphableCanister;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client._White.PolymorphableCanister.UI;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class PolymorphableCanisterMenu : RadialMenu
|
||||||
|
{
|
||||||
|
[Dependency] private readonly EntityManager _entManager = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||||
|
|
||||||
|
public PolymorphableCanisterMenu(EntityUid owner, PolymorphableCanisterBUI bui)
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
|
if (!_entManager.TryGetComponent<PolymorphableCanisterComponent>(owner, out var canister))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var spriteSystem = _entManager.System<SpriteSystem>();
|
||||||
|
|
||||||
|
var main = FindControl<RadialContainer>("Main");
|
||||||
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||||
|
if (main is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var protoId in canister.Prototypes)
|
||||||
|
{
|
||||||
|
if (canister.CurrentPrototype == protoId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!_protoManager.TryIndex(protoId, out var proto))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var button = new RadialMenuTextureButton
|
||||||
|
{
|
||||||
|
ToolTip = Loc.GetString(proto.Name),
|
||||||
|
TextureNormal = spriteSystem.GetPrototypeIcon(protoId).Default,
|
||||||
|
StyleClasses = { "RadialMenuButton" },
|
||||||
|
SetSize = new Vector2(64f, 64f)
|
||||||
|
};
|
||||||
|
|
||||||
|
button.OnButtonUp += _ =>
|
||||||
|
{
|
||||||
|
bui.SendMessage(protoId);
|
||||||
|
Close();
|
||||||
|
};
|
||||||
|
|
||||||
|
main.AddChild(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
using Content.Server.Atmos.Piping.Unary.Components;
|
||||||
|
using Content.Shared._White.PolymorphableCanister;
|
||||||
|
using Content.Shared.Lock;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server._White.PolymorphableCanister;
|
||||||
|
|
||||||
|
public sealed class PolymorphableCanisterSystem : SharedPolymorphableCanisterSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly UserInterfaceSystem _ui = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<PolymorphableCanisterComponent, GetVerbsEvent<Verb>>(GetVerb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GetVerb(EntityUid uid, PolymorphableCanisterComponent component, GetVerbsEvent<Verb> args)
|
||||||
|
{
|
||||||
|
if (TryComp(uid, out LockComponent? lockComponent) && lockComponent.Locked)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryComp(uid, out GasCanisterComponent? gasCanister) && gasCanister.Air.Pressure > 100)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var changeAppearanceVerb = new Verb
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("polymorphable-canister-change-appearance-verb"),
|
||||||
|
Icon = new SpriteSpecifier.Rsi(new ResPath("Structures/Storage/canister.rsi"), "yellow"),
|
||||||
|
Act = () => TryOpenUi(uid, args.User, component)
|
||||||
|
};
|
||||||
|
|
||||||
|
args.Verbs.Add(changeAppearanceVerb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryOpenUi(EntityUid uid, EntityUid user, PolymorphableCanisterComponent? component = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TryComp(user, out ActorComponent? actor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_ui.TryToggleUi(uid, PolymorphableCanisterUiKey.Key, actor.PlayerSession);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Shared._White.PolymorphableCanister;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||||
|
public sealed partial class PolymorphableCanisterComponent : Component
|
||||||
|
{
|
||||||
|
[DataField]
|
||||||
|
public ResPath ResPath = new("Structures/Storage/canister.rsi");
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public ProtoId<EntityPrototype>? CurrentPrototype;
|
||||||
|
|
||||||
|
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int DoAfterTime = 3;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public List<ProtoId<EntityPrototype>> Prototypes = new()
|
||||||
|
{
|
||||||
|
"GasCanister",
|
||||||
|
"StorageCanister",
|
||||||
|
"AirCanister",
|
||||||
|
"OxygenCanister",
|
||||||
|
"NitrogenCanister",
|
||||||
|
"CarbonDioxideCanister",
|
||||||
|
"PlasmaCanister",
|
||||||
|
"TritiumCanister",
|
||||||
|
"WaterVaporCanister",
|
||||||
|
"AmmoniaCanister",
|
||||||
|
"NitrousOxideCanister",
|
||||||
|
"FrezonCanister",
|
||||||
|
"BZCanister",
|
||||||
|
"PluoxiumCanister",
|
||||||
|
"HydrogenCanister",
|
||||||
|
"NitriumCanister",
|
||||||
|
"HealiumCanister",
|
||||||
|
"HyperNobliumCanister",
|
||||||
|
"ProtoNitrateCanister",
|
||||||
|
"ZaukerCanister",
|
||||||
|
"HalonCanister",
|
||||||
|
"HeliumCanister",
|
||||||
|
"AntiNobliumCanister",
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
using Content.Shared.DoAfter;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared._White.PolymorphableCanister;
|
||||||
|
|
||||||
|
public abstract class SharedPolymorphableCanisterSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||||
|
[Dependency] private readonly MetaDataSystem _metaData = default!;
|
||||||
|
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<PolymorphableCanisterComponent, ComponentInit>(OnInit);
|
||||||
|
SubscribeLocalEvent<PolymorphableCanisterComponent, PolymorphableCanisterMessage>(OnMessage);
|
||||||
|
SubscribeLocalEvent<PolymorphableCanisterComponent, PolymorphableCanisterDoAfterEvent>(OnDoAfter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(Entity<PolymorphableCanisterComponent> ent, ref ComponentInit args)
|
||||||
|
{
|
||||||
|
var proto = MetaData(ent.Owner).EntityPrototype;
|
||||||
|
if (proto is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent.Comp.CurrentPrototype = proto.ID;
|
||||||
|
Dirty(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMessage(Entity<PolymorphableCanisterComponent> ent, ref PolymorphableCanisterMessage args)
|
||||||
|
{
|
||||||
|
if (!args.Session.AttachedEntity.HasValue)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var doAfterArgs = new DoAfterArgs(EntityManager,
|
||||||
|
args.Session.AttachedEntity.Value,
|
||||||
|
ent.Comp.DoAfterTime,
|
||||||
|
new PolymorphableCanisterDoAfterEvent(args.ProtoId),
|
||||||
|
ent.Owner
|
||||||
|
)
|
||||||
|
{
|
||||||
|
BreakOnMove = true,
|
||||||
|
NeedHand = true
|
||||||
|
};
|
||||||
|
|
||||||
|
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDoAfter(Entity<PolymorphableCanisterComponent> ent, ref PolymorphableCanisterDoAfterEvent args)
|
||||||
|
{
|
||||||
|
if (args.Cancelled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ent.Comp.CurrentPrototype = args.ProtoId;
|
||||||
|
UpdateAppearance(ent, args.ProtoId);
|
||||||
|
Dirty(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateAppearance(EntityUid uid, ProtoId<EntityPrototype>? protoId)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(protoId) || !_proto.TryIndex(protoId, out var proto))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadata = MetaData(uid);
|
||||||
|
_metaData.SetEntityName(uid, proto.Name, metadata);
|
||||||
|
_metaData.SetEntityDescription(uid, proto.Description, metadata);
|
||||||
|
|
||||||
|
UpdateSprite(uid, proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void UpdateSprite(EntityUid uid, EntityPrototype proto)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NetSerializable, Serializable]
|
||||||
|
public enum PolymorphableCanisterUiKey : byte
|
||||||
|
{
|
||||||
|
Key
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class PolymorphableCanisterMessage(string protoId) : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public readonly ProtoId<EntityPrototype> ProtoId = protoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed partial class PolymorphableCanisterDoAfterEvent : SimpleDoAfterEvent
|
||||||
|
{
|
||||||
|
public readonly ProtoId<EntityPrototype> ProtoId;
|
||||||
|
|
||||||
|
public PolymorphableCanisterDoAfterEvent(string protoId)
|
||||||
|
{
|
||||||
|
ProtoId = protoId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
polymorphable-canister-change-appearance-verb = Change appearance
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
polymorphable-canister-change-appearance-verb = Перекрасить
|
||||||
@@ -34,10 +34,12 @@
|
|||||||
1: { state: can-o1, shader: "unshaded" }
|
1: { state: can-o1, shader: "unshaded" }
|
||||||
2: { state: can-o2, shader: "unshaded" }
|
2: { state: can-o2, shader: "unshaded" }
|
||||||
3: { state: can-o3, shader: "unshaded" }
|
3: { state: can-o3, shader: "unshaded" }
|
||||||
- type: UserInterface
|
- type: UserInterface # WhiteDream - Added PolymorphableCanisterUiKey
|
||||||
interfaces:
|
interfaces:
|
||||||
- key: enum.GasCanisterUiKey.Key
|
- key: enum.GasCanisterUiKey.Key
|
||||||
type: GasCanisterBoundUserInterface
|
type: GasCanisterBoundUserInterface
|
||||||
|
- key: enum.PolymorphableCanisterUiKey.Key
|
||||||
|
type: PolymorphableCanisterBUI
|
||||||
- type: Destructible
|
- type: Destructible
|
||||||
thresholds:
|
thresholds:
|
||||||
- trigger:
|
- trigger:
|
||||||
@@ -104,6 +106,7 @@
|
|||||||
access: [["Atmospherics"], ["Engineering"], ["Research"]]
|
access: [["Atmospherics"], ["Engineering"], ["Research"]]
|
||||||
- type: Lock
|
- type: Lock
|
||||||
locked: false
|
locked: false
|
||||||
|
- type: PolymorphableCanister # WhiteDream
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: GasCanister
|
parent: GasCanister
|
||||||
|
|||||||
Reference in New Issue
Block a user