From d49eabc1a5e2aeb3b450eda6af9b488ef2d34609 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Mon, 22 Apr 2024 03:28:58 +0200 Subject: [PATCH 01/67] Partial cherry-pick: Loadouts redux (#25715) Signed-off-by: NullWanderer <56081759+NullWanderer@users.noreply.github.com> --- .../SpawnEquipDeleteBenchmark.cs | 2 +- Content.Client/Content.Client.csproj | 3 + Content.Client/IoC/ClientContentIoC.cs | 44 +- Content.Client/Lobby/LobbyState.cs | 13 +- Content.Client/Lobby/LobbyUIController.cs | 223 ++ .../Lobby/UI/LobbyCharacterPreviewPanel.cs | 166 -- .../Lobby/UI/LobbyCharacterPreviewPanel.xaml | 22 + .../UI/LobbyCharacterPreviewPanel.xaml.cs | 45 + Content.Client/Lobby/UI/LobbyGui.xaml.cs | 14 - .../JobRequirementsManager.cs | 11 +- .../Preferences/ClientPreferencesManager.cs | 10 +- .../Preferences/UI/AntagPreferenceSelector.cs | 41 + .../Preferences/UI/CharacterSetupGui.xaml | 2 +- .../Preferences/UI/CharacterSetupGui.xaml.cs | 34 +- .../Preferences/UI/HighlightedContainer.xaml | 11 + .../UI/HighlightedContainer.xaml.cs | 14 + .../UI/HumanoidProfileEditor.Random.cs | 2 - .../Preferences/UI/HumanoidProfileEditor.xaml | 29 +- .../UI/HumanoidProfileEditor.xaml.cs | 472 +---- .../Preferences/UI/JobPrioritySelector.cs | 46 + .../Preferences/UI/LoadoutContainer.xaml | 15 + .../Preferences/UI/LoadoutContainer.xaml.cs | 74 + .../Preferences/UI/LoadoutGroupContainer.xaml | 10 + .../UI/LoadoutGroupContainer.xaml.cs | 93 + .../Preferences/UI/LoadoutWindow.xaml | 10 + .../Preferences/UI/LoadoutWindow.xaml.cs | 60 + .../Preferences/UI/RequirementsSelector.cs | 222 ++ .../Minds/MindTest.DeleteAllThenGhost.cs | 14 +- .../Tests/Preferences/LoadoutTests.cs | 44 + .../Tests/Preferences/ServerDbSqliteTests.cs | 7 +- ...20240301130641_ClothingRemoval.Designer.cs | 1838 ++++++++++++++++ .../20240301130641_ClothingRemoval.cs | 40 + .../20240403072242_Loadouts.Designer.cs | 1884 +++++++++++++++++ .../Postgres/20240403072242_Loadouts.cs | 103 + .../PostgresServerDbContextModelSnapshot.cs | 136 +- ...20240301130602_ClothingRemoval.Designer.cs | 1765 +++++++++++++++ .../Sqlite/20240301130602_ClothingRemoval.cs | 40 + .../20240403072258_Loadouts.Designer.cs | 1809 ++++++++++++++++ .../Sqlite/20240403072258_Loadouts.cs | 102 + .../SqliteServerDbContextModelSnapshot.cs | 130 +- Content.Server.Database/Model.cs | 99 +- .../Commands/SetOutfitCommand.cs | 2 +- Content.Server/Database/ServerDbBase.cs | 75 +- .../GameTicking/Rules/NukeopsRuleSystem.cs | 2 +- .../GameTicking/Rules/PiratesRuleSystem.cs | 2 +- Content.Server/IoC/ServerContentIoC.cs | 2 + .../PlayTimeTrackingManager.cs | 7 +- .../Managers/ServerPreferencesManager.cs | 15 +- .../EntitySystems/SpawnPointSystem.cs | 2 +- .../Station/Systems/StationSpawningSystem.cs | 40 +- Content.Shared/Clothing/LoadoutSystem.cs | 86 +- Content.Shared/Content.Shared.csproj | 4 + .../Humanoid/Prototypes/SpeciesPrototype.cs | 14 +- .../ISharedPlaytimeManager.cs | 12 + .../Preferences/BackpackPreference.cs | 12 - .../Preferences/ClothingPreference.cs | 11 - .../Preferences/HumanoidCharacterProfile.cs | 144 +- .../Preferences/ICharacterProfile.cs | 5 +- .../Loadouts/Effects/GroupLoadoutEffect.cs | 29 + .../Effects/JobRequirementLoadoutEffect.cs | 26 + .../Loadouts/Effects/LoadoutEffect.cs | 20 + .../Effects/LoadoutEffectGroupPrototype.cs | 16 + .../Effects/PointsCostLoadoutEffect.cs | 40 + .../Preferences/Loadouts/Loadout.cs | 13 + .../Loadouts/LoadoutGroupPrototype.cs | 34 + .../Preferences/Loadouts/LoadoutPrototype.cs | 25 + .../Preferences/Loadouts/RoleLoadout.cs | 248 +++ .../Loadouts/RoleLoadoutPrototype.cs | 29 + Content.Shared/Roles/JobRequirements.cs | 4 +- Content.Shared/Roles/StartingGearPrototype.cs | 29 +- .../Station/SharedStationSpawningSystem.cs | 56 +- Resources/Locale/en-US/job/loadouts.ftl | 2 + .../en-US/preferences/loadout-groups.ftl | 159 ++ .../Locale/en-US/preferences/loadouts.ftl | 7 + .../ui/humanoid-profile-editor.ftl | 2 - 75 files changed, 10040 insertions(+), 833 deletions(-) create mode 100644 Content.Client/Lobby/LobbyUIController.cs delete mode 100644 Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs create mode 100644 Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml create mode 100644 Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml.cs create mode 100644 Content.Client/Preferences/UI/AntagPreferenceSelector.cs create mode 100644 Content.Client/Preferences/UI/HighlightedContainer.xaml create mode 100644 Content.Client/Preferences/UI/HighlightedContainer.xaml.cs create mode 100644 Content.Client/Preferences/UI/JobPrioritySelector.cs create mode 100644 Content.Client/Preferences/UI/LoadoutContainer.xaml create mode 100644 Content.Client/Preferences/UI/LoadoutContainer.xaml.cs create mode 100644 Content.Client/Preferences/UI/LoadoutGroupContainer.xaml create mode 100644 Content.Client/Preferences/UI/LoadoutGroupContainer.xaml.cs create mode 100644 Content.Client/Preferences/UI/LoadoutWindow.xaml create mode 100644 Content.Client/Preferences/UI/LoadoutWindow.xaml.cs create mode 100644 Content.Client/Preferences/UI/RequirementsSelector.cs create mode 100644 Content.IntegrationTests/Tests/Preferences/LoadoutTests.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20240301130641_ClothingRemoval.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20240301130641_ClothingRemoval.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20240403072242_Loadouts.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20240403072242_Loadouts.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20240301130602_ClothingRemoval.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20240301130602_ClothingRemoval.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20240403072258_Loadouts.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20240403072258_Loadouts.cs create mode 100644 Content.Shared/Players/PlayTimeTracking/ISharedPlaytimeManager.cs delete mode 100644 Content.Shared/Preferences/BackpackPreference.cs delete mode 100644 Content.Shared/Preferences/ClothingPreference.cs create mode 100644 Content.Shared/Preferences/Loadouts/Effects/GroupLoadoutEffect.cs create mode 100644 Content.Shared/Preferences/Loadouts/Effects/JobRequirementLoadoutEffect.cs create mode 100644 Content.Shared/Preferences/Loadouts/Effects/LoadoutEffect.cs create mode 100644 Content.Shared/Preferences/Loadouts/Effects/LoadoutEffectGroupPrototype.cs create mode 100644 Content.Shared/Preferences/Loadouts/Effects/PointsCostLoadoutEffect.cs create mode 100644 Content.Shared/Preferences/Loadouts/Loadout.cs create mode 100644 Content.Shared/Preferences/Loadouts/LoadoutGroupPrototype.cs create mode 100644 Content.Shared/Preferences/Loadouts/LoadoutPrototype.cs create mode 100644 Content.Shared/Preferences/Loadouts/RoleLoadout.cs create mode 100644 Content.Shared/Preferences/Loadouts/RoleLoadoutPrototype.cs create mode 100644 Resources/Locale/en-US/job/loadouts.ftl create mode 100644 Resources/Locale/en-US/preferences/loadout-groups.ftl create mode 100644 Resources/Locale/en-US/preferences/loadouts.ftl diff --git a/Content.Benchmarks/SpawnEquipDeleteBenchmark.cs b/Content.Benchmarks/SpawnEquipDeleteBenchmark.cs index de51b2fb192..8512107b69d 100644 --- a/Content.Benchmarks/SpawnEquipDeleteBenchmark.cs +++ b/Content.Benchmarks/SpawnEquipDeleteBenchmark.cs @@ -58,7 +58,7 @@ await _pair.Server.WaitPost(() => for (var i = 0; i < N; i++) { _entity = server.EntMan.SpawnAttachedTo(Mob, _coords); - _spawnSys.EquipStartingGear(_entity, _gear, null); + _spawnSys.EquipStartingGear(_entity, _gear); server.EntMan.DeleteEntity(_entity); } }); diff --git a/Content.Client/Content.Client.csproj b/Content.Client/Content.Client.csproj index 956f2fd0351..02fefa5cf20 100644 --- a/Content.Client/Content.Client.csproj +++ b/Content.Client/Content.Client.csproj @@ -26,6 +26,9 @@ + + + diff --git a/Content.Client/IoC/ClientContentIoC.cs b/Content.Client/IoC/ClientContentIoC.cs index 70fe1916584..65e95b76f08 100644 --- a/Content.Client/IoC/ClientContentIoC.cs +++ b/Content.Client/IoC/ClientContentIoC.cs @@ -21,6 +21,7 @@ using Content.Client.Guidebook; using Content.Client.Replay; using Content.Shared.Administration.Managers; +using Content.Shared.Players.PlayTimeTracking; namespace Content.Client.IoC @@ -29,26 +30,29 @@ internal static class ClientContentIoC { public static void Register() { - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); + var collection = IoCManager.Instance!; + + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); + collection.Register(); } } } diff --git a/Content.Client/Lobby/LobbyState.cs b/Content.Client/Lobby/LobbyState.cs index fe31dce0629..98c109afde1 100644 --- a/Content.Client/Lobby/LobbyState.cs +++ b/Content.Client/Lobby/LobbyState.cs @@ -70,7 +70,7 @@ protected override void Startup() _characterSetup.SaveButton.OnPressed += _ => { _characterSetup.Save(); - _lobby.CharacterPreview.UpdateUI(); + _userInterfaceManager.GetUIController().UpdateCharacterUI(); }; LayoutContainer.SetAnchorPreset(_lobby, LayoutContainer.LayoutPreset.Wide); @@ -84,10 +84,6 @@ protected override void Startup() _gameTicker.InfoBlobUpdated += UpdateLobbyUi; _gameTicker.LobbyStatusUpdated += LobbyStatusUpdated; _gameTicker.LobbyLateJoinStatusUpdated += LobbyLateJoinStatusUpdated; - - _preferencesManager.OnServerDataLoaded += PreferencesDataLoaded; - - _lobby.CharacterPreview.UpdateUI(); } protected override void Shutdown() @@ -109,13 +105,6 @@ protected override void Shutdown() _characterSetup?.Dispose(); _characterSetup = null; - - _preferencesManager.OnServerDataLoaded -= PreferencesDataLoaded; - } - - private void PreferencesDataLoaded() - { - _lobby?.CharacterPreview.UpdateUI(); } private void OnSetupPressed(BaseButton.ButtonEventArgs args) diff --git a/Content.Client/Lobby/LobbyUIController.cs b/Content.Client/Lobby/LobbyUIController.cs new file mode 100644 index 00000000000..19f43e05752 --- /dev/null +++ b/Content.Client/Lobby/LobbyUIController.cs @@ -0,0 +1,223 @@ +using System.Linq; +using Content.Client.Humanoid; +using Content.Client.Inventory; +using Content.Client.Lobby.UI; +using Content.Client.Preferences; +using Content.Client.Station; +using Content.Shared.Clothing; +using Content.Shared.GameTicking; +using Content.Shared.Humanoid.Prototypes; +using Content.Shared.Preferences; +using Content.Shared.Preferences.Loadouts; +using Content.Shared.Preferences.Loadouts.Effects; +using Content.Shared.Roles; +using Robust.Client.State; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controllers; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; + +namespace Content.Client.Lobby; + +public sealed class LobbyUIController : UIController, IOnStateEntered, IOnStateExited +{ + [Dependency] private readonly IClientPreferencesManager _preferencesManager = default!; + [Dependency] private readonly IStateManager _stateManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + [UISystemDependency] private readonly HumanoidAppearanceSystem _humanoid = default!; + [UISystemDependency] private readonly ClientInventorySystem _inventory = default!; + [UISystemDependency] private readonly StationSpawningSystem _spawn = default!; + + private LobbyCharacterPreviewPanel? _previewPanel; + + /* + * Each character profile has its own dummy. There is also a dummy for the lobby screen + character editor + * that is shared too. + */ + + /// + /// Preview dummy for role gear. + /// + private EntityUid? _previewDummy; + + /// + /// If we currently have a loadout selected. + /// + private JobPrototype? _dummyJob; + + // TODO: Load the species directly and don't update entity ever. + public event Action? PreviewDummyUpdated; + + public override void Initialize() + { + base.Initialize(); + _preferencesManager.OnServerDataLoaded += PreferencesDataLoaded; + } + + private void PreferencesDataLoaded() + { + UpdateCharacterUI(); + } + + public void OnStateEntered(LobbyState state) + { + } + + public void OnStateExited(LobbyState state) + { + EntityManager.DeleteEntity(_previewDummy); + _previewDummy = null; + } + + public void SetPreviewPanel(LobbyCharacterPreviewPanel? panel) + { + _previewPanel = panel; + UpdateCharacterUI(); + } + + public void SetDummyJob(JobPrototype? job) + { + _dummyJob = job; + UpdateCharacterUI(); + } + + public void UpdateCharacterUI() + { + // Test moment + if (_stateManager.CurrentState is not LobbyState) + return; + + if (!_preferencesManager.ServerDataLoaded) + { + _previewPanel?.SetLoaded(false); + return; + } + + _previewPanel?.SetLoaded(true); + + if (_preferencesManager.Preferences?.SelectedCharacter is not HumanoidCharacterProfile selectedCharacter) + { + _previewPanel?.SetSummaryText(string.Empty); + } + else + { + EntityManager.DeleteEntity(_previewDummy); + _previewDummy = EntityManager.SpawnEntity(_prototypeManager.Index(selectedCharacter.Species).DollPrototype, MapCoordinates.Nullspace); + _previewPanel?.SetSprite(_previewDummy.Value); + _previewPanel?.SetSummaryText(selectedCharacter.Summary); + _humanoid.LoadProfile(_previewDummy.Value, selectedCharacter); + + GiveDummyJobClothesLoadout(_previewDummy.Value, selectedCharacter); + PreviewDummyUpdated?.Invoke(_previewDummy.Value); + } + } + + /// + /// Applies the highest priority job's clothes to the dummy. + /// + public void GiveDummyJobClothesLoadout(EntityUid dummy, HumanoidCharacterProfile profile) + { + var job = _dummyJob ?? GetPreferredJob(profile); + GiveDummyJobClothes(dummy, profile, job); + + if (_prototypeManager.HasIndex(LoadoutSystem.GetJobPrototype(job.ID))) + { + var loadout = profile.GetLoadoutOrDefault(LoadoutSystem.GetJobPrototype(job.ID), EntityManager, _prototypeManager); + GiveDummyLoadout(dummy, loadout); + } + } + + /// + /// Gets the highest priority job for the profile. + /// + public JobPrototype GetPreferredJob(HumanoidCharacterProfile profile) + { + var highPriorityJob = profile.JobPriorities.FirstOrDefault(p => p.Value == JobPriority.High).Key; + // ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract (what is resharper smoking?) + return _prototypeManager.Index(highPriorityJob ?? SharedGameTicker.FallbackOverflowJob); + } + + public void GiveDummyLoadout(EntityUid uid, RoleLoadout? roleLoadout) + { + if (roleLoadout == null) + return; + + foreach (var group in roleLoadout.SelectedLoadouts.Values) + { + foreach (var loadout in group) + { + if (!_prototypeManager.TryIndex(loadout.Prototype, out var loadoutProto)) + continue; + + _spawn.EquipStartingGear(uid, _prototypeManager.Index(loadoutProto.Equipment)); + } + } + } + + /// + /// Applies the specified job's clothes to the dummy. + /// + public void GiveDummyJobClothes(EntityUid dummy, HumanoidCharacterProfile profile, JobPrototype job) + { + if (!_inventory.TryGetSlots(dummy, out var slots)) + return; + + // Apply loadout + if (profile.Loadouts.TryGetValue(job.ID, out var jobLoadout)) + { + foreach (var loadouts in jobLoadout.SelectedLoadouts.Values) + { + foreach (var loadout in loadouts) + { + if (!_prototypeManager.TryIndex(loadout.Prototype, out var loadoutProto)) + continue; + + // TODO: Need some way to apply starting gear to an entity coz holy fucking shit dude. + var loadoutGear = _prototypeManager.Index(loadoutProto.Equipment); + + foreach (var slot in slots) + { + var itemType = loadoutGear.GetGear(slot.Name); + + if (_inventory.TryUnequip(dummy, slot.Name, out var unequippedItem, silent: true, force: true, reparent: false)) + { + EntityManager.DeleteEntity(unequippedItem.Value); + } + + if (itemType != string.Empty) + { + var item = EntityManager.SpawnEntity(itemType, MapCoordinates.Nullspace); + _inventory.TryEquip(dummy, item, slot.Name, true, true); + } + } + } + } + } + + if (job.StartingGear == null) + return; + + var gear = _prototypeManager.Index(job.StartingGear); + + foreach (var slot in slots) + { + var itemType = gear.GetGear(slot.Name); + + if (_inventory.TryUnequip(dummy, slot.Name, out var unequippedItem, silent: true, force: true, reparent: false)) + { + EntityManager.DeleteEntity(unequippedItem.Value); + } + + if (itemType != string.Empty) + { + var item = EntityManager.SpawnEntity(itemType, MapCoordinates.Nullspace); + _inventory.TryEquip(dummy, item, slot.Name, true, true); + } + } + } + + public EntityUid? GetPreviewDummy() + { + return _previewDummy; + } +} diff --git a/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs b/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs deleted file mode 100644 index f9481caa3bb..00000000000 --- a/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs +++ /dev/null @@ -1,166 +0,0 @@ -using System.Linq; -using System.Numerics; -using Content.Client.Alerts; -using Content.Client.Humanoid; -using Content.Client.Inventory; -using Content.Client.Preferences; -using Content.Client.UserInterface.Controls; -using Content.Shared.GameTicking; -using Content.Shared.Humanoid.Prototypes; -using Content.Shared.Inventory; -using Content.Shared.Preferences; -using Content.Shared.Roles; -using Robust.Client.GameObjects; -using Robust.Client.UserInterface; -using Robust.Client.UserInterface.Controls; -using Robust.Shared.Map; -using Robust.Shared.Prototypes; -using static Robust.Client.UserInterface.Controls.BoxContainer; - -namespace Content.Client.Lobby.UI -{ - public sealed class LobbyCharacterPreviewPanel : Control - { - [Dependency] private readonly IEntityManager _entityManager = default!; - [Dependency] private readonly IClientPreferencesManager _preferencesManager = default!; - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - - - private EntityUid? _previewDummy; - private readonly Label _summaryLabel; - private readonly BoxContainer _loaded; - private readonly BoxContainer _viewBox; - private readonly Label _unloaded; - - public LobbyCharacterPreviewPanel() - { - IoCManager.InjectDependencies(this); - var header = new NanoHeading - { - Text = Loc.GetString("lobby-character-preview-panel-header") - }; - - CharacterSetupButton = new Button - { - Text = Loc.GetString("lobby-character-preview-panel-character-setup-button"), - HorizontalAlignment = HAlignment.Center, - Margin = new Thickness(0, 5, 0, 0), - }; - - _summaryLabel = new Label - { - HorizontalAlignment = HAlignment.Center, - Margin = new Thickness(3, 3), - }; - - var vBox = new BoxContainer - { - Orientation = LayoutOrientation.Vertical - }; - _unloaded = new Label { Text = Loc.GetString("lobby-character-preview-panel-unloaded-preferences-label") }; - - _loaded = new BoxContainer - { - Orientation = LayoutOrientation.Vertical, - Visible = false - }; - _viewBox = new BoxContainer - { - Orientation = LayoutOrientation.Horizontal, - HorizontalAlignment = HAlignment.Center, - }; - var _vSpacer = new VSpacer(); - - _loaded.AddChild(_summaryLabel); - _loaded.AddChild(_viewBox); - _loaded.AddChild(_vSpacer); - _loaded.AddChild(CharacterSetupButton); - - vBox.AddChild(header); - vBox.AddChild(_loaded); - vBox.AddChild(_unloaded); - AddChild(vBox); - - UpdateUI(); - } - - public Button CharacterSetupButton { get; } - - protected override void Dispose(bool disposing) - { - base.Dispose(disposing); - - if (!disposing) return; - if (_previewDummy != null) _entityManager.DeleteEntity(_previewDummy.Value); - _previewDummy = default; - } - - public void UpdateUI() - { - if (!_preferencesManager.ServerDataLoaded) - { - _loaded.Visible = false; - _unloaded.Visible = true; - } - else - { - _loaded.Visible = true; - _unloaded.Visible = false; - if (_preferencesManager.Preferences?.SelectedCharacter is not HumanoidCharacterProfile selectedCharacter) - { - _summaryLabel.Text = string.Empty; - } - else - { - _previewDummy = _entityManager.SpawnEntity(_prototypeManager.Index(selectedCharacter.Species).DollPrototype, MapCoordinates.Nullspace); - _viewBox.DisposeAllChildren(); - var spriteView = new SpriteView - { - OverrideDirection = Direction.South, - Scale = new Vector2(4f, 4f), - MaxSize = new Vector2(112, 112), - Stretch = SpriteView.StretchMode.Fill, - }; - spriteView.SetEntity(_previewDummy.Value); - _viewBox.AddChild(spriteView); - _summaryLabel.Text = selectedCharacter.Summary; - _entityManager.System().LoadProfile(_previewDummy.Value, selectedCharacter); - GiveDummyJobClothes(_previewDummy.Value, selectedCharacter); - } - } - } - - public static void GiveDummyJobClothes(EntityUid dummy, HumanoidCharacterProfile profile) - { - var protoMan = IoCManager.Resolve(); - var entMan = IoCManager.Resolve(); - var invSystem = EntitySystem.Get(); - - var highPriorityJob = profile.JobPriorities.FirstOrDefault(p => p.Value == JobPriority.High).Key; - - // ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract (what is resharper smoking?) - var job = protoMan.Index(highPriorityJob ?? SharedGameTicker.FallbackOverflowJob); - - if (job.StartingGear != null && invSystem.TryGetSlots(dummy, out var slots)) - { - var gear = protoMan.Index(job.StartingGear); - - foreach (var slot in slots) - { - var itemType = gear.GetGear(slot.Name, profile); - - if (invSystem.TryUnequip(dummy, slot.Name, out var unequippedItem, silent: true, force: true, reparent: false)) - { - entMan.DeleteEntity(unequippedItem.Value); - } - - if (itemType != string.Empty) - { - var item = entMan.SpawnEntity(itemType, MapCoordinates.Nullspace); - invSystem.TryEquip(dummy, item, slot.Name, true, true); - } - } - } - } - } -} diff --git a/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml b/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml new file mode 100644 index 00000000000..997507414cd --- /dev/null +++ b/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml @@ -0,0 +1,22 @@ + + + + + + +