From 12766fe6e37bb600a53693cfa5392892bc100685 Mon Sep 17 00:00:00 2001 From: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Date: Tue, 16 Apr 2024 22:57:43 +1000 Subject: [PATCH] Loadouts redux (#25715) * Loadouts redux * Loadout window mockup * More workout * rent * validation * Developments * bcs * More cleanup * Rebuild working * Fix model and loading * obsession * efcore * We got a stew goin * Cleanup * Optional + SeniorEngineering fix * Fixes * Update science.yml * add add * Automatic naming * Update nukeops * Coming together * Right now * stargate * rejig the UI * weh * Loadouts tweaks * Merge conflicts + ordering fix * yerba mate * chocolat * More updates * Add multi-selection support * test h * fikss * a * add tech assistant and hazard suit * huh * Latest changes * add medical loadouts * and science * finish security loadouts * cargo * service done * added wildcards * add command * Move restrictions * Finalising * Fix existing work * Localise next batch * clothing fix * Fix storage names * review * the scooping room * Test fixes * Xamlify * Xamlify this too * Update Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/Jobs/Security/detective.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * Update Resources/Prototypes/Loadouts/loadout_groups.yml Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> * ben * Margins --------- Co-authored-by: Firewatch <54725557+musicmanvr@users.noreply.github.com> Co-authored-by: Mr. 27 Co-authored-by: Mr. 27 <45323883+Dutch-VanDerLinde@users.noreply.github.com> --- .../SpawnEquipDeleteBenchmark.cs | 2 +- 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 | 471 +---- .../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 +- .../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 | 28 +- .../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 - .../Fills/Backpacks/StarterGear/backpack.yml | 11 + .../Loadouts/Jobs/Cargo/cargo_technician.yml | 56 + .../Loadouts/Jobs/Cargo/quartermaster.yml | 111 + .../Jobs/Cargo/salvage_specialist.yml | 27 + .../Loadouts/Jobs/Civilian/bartender.yml | 65 + .../Loadouts/Jobs/Civilian/botanist.yml | 84 + .../Loadouts/Jobs/Civilian/chaplain.yml | 158 ++ .../Loadouts/Jobs/Civilian/chef.yml | 57 + .../Loadouts/Jobs/Civilian/clown.yml | 75 + .../Loadouts/Jobs/Civilian/janitor.yml | 28 + .../Loadouts/Jobs/Civilian/lawyer.yml | 100 + .../Loadouts/Jobs/Civilian/librarian.yml | 36 + .../Loadouts/Jobs/Civilian/mime.yml | 102 + .../Loadouts/Jobs/Civilian/musician.yml | 27 + .../Loadouts/Jobs/Civilian/passenger.yml | 82 + .../Loadouts/Jobs/Command/captain.yml | 111 + .../Jobs/Command/head_of_personnel.yml | 97 + .../Engineering/atmospheric_technician.yml | 55 + .../Jobs/Engineering/chief_engineer.yml | 97 + .../Jobs/Engineering/station_engineer.yml | 189 ++ .../Jobs/Engineering/technical_assistant.yml | 18 + .../Loadouts/Jobs/Medical/chemist.yml | 56 + .../Jobs/Medical/chief_medical_officer.yml | 85 + .../Loadouts/Jobs/Medical/medical_doctor.yml | 239 +++ .../Loadouts/Jobs/Medical/medical_intern.yml | 18 + .../Loadouts/Jobs/Medical/paramedic.yml | 66 + .../Jobs/Science/research_director.yml | 82 + .../Loadouts/Jobs/Science/scientist.yml | 194 ++ .../Loadouts/Jobs/Security/detective.yml | 112 + .../Jobs/Security/head_of_security.yml | 111 + .../Loadouts/Jobs/Security/security_cadet.yml | 18 + .../Jobs/Security/security_officer.yml | 171 ++ .../Loadouts/Jobs/Security/warden.yml | 56 + .../Loadouts/Jobs/Wildcards/boxer.yml | 55 + .../Loadouts/Jobs/Wildcards/reporter.yml | 18 + .../Loadouts/Miscellaneous/trinkets.yml | 99 + .../Prototypes/Loadouts/loadout_groups.yml | 934 ++++++++ .../Prototypes/Loadouts/role_loadouts.yml | 327 +++ Resources/Prototypes/Roles/Antags/pirate.yml | 9 - .../Roles/Jobs/Cargo/cargo_technician.yml | 8 +- .../Roles/Jobs/Cargo/quartermaster.yml | 8 +- .../Roles/Jobs/Cargo/salvage_specialist.yml | 5 +- .../Roles/Jobs/Civilian/assistant.yml | 5 - .../Roles/Jobs/Civilian/bartender.yml | 7 - .../Roles/Jobs/Civilian/botanist.yml | 6 - .../Roles/Jobs/Civilian/chaplain.yml | 5 - .../Prototypes/Roles/Jobs/Civilian/chef.yml | 8 - .../Prototypes/Roles/Jobs/Civilian/clown.yml | 7 +- .../Roles/Jobs/Civilian/janitor.yml | 10 - .../Prototypes/Roles/Jobs/Civilian/lawyer.yml | 5 - .../Roles/Jobs/Civilian/librarian.yml | 5 - .../Prototypes/Roles/Jobs/Civilian/mime.yml | 9 +- .../Roles/Jobs/Civilian/musician.yml | 5 +- .../Roles/Jobs/Civilian/service_worker.yml | 5 - .../Prototypes/Roles/Jobs/Command/captain.yml | 6 - .../Roles/Jobs/Command/head_of_personnel.yml | 6 - .../Engineering/atmospheric_technician.yml | 5 - .../Roles/Jobs/Engineering/chief_engineer.yml | 6 - .../Jobs/Engineering/station_engineer.yml | 8 - .../Jobs/Engineering/technical_assistant.yml | 7 +- .../Roles/Jobs/Fun/cult_startinggear.yml | 6 - .../Roles/Jobs/Fun/misc_startinggear.yml | 40 - .../Roles/Jobs/Fun/wizard_startinggear.yml | 12 - .../Prototypes/Roles/Jobs/Medical/chemist.yml | 7 +- .../Jobs/Medical/chief_medical_officer.yml | 6 - .../Roles/Jobs/Medical/medical_doctor.yml | 7 - .../Roles/Jobs/Medical/medical_intern.yml | 7 +- .../Roles/Jobs/Medical/paramedic.yml | 5 - .../Roles/Jobs/Science/research_assistant.yml | 4 - .../Roles/Jobs/Science/research_director.yml | 8 +- .../Roles/Jobs/Science/scientist.yml | 8 +- .../Roles/Jobs/Security/detective.yml | 7 - .../Roles/Jobs/Security/head_of_security.yml | 9 +- .../Roles/Jobs/Security/security_cadet.yml | 7 +- .../Roles/Jobs/Security/security_officer.yml | 7 - .../Prototypes/Roles/Jobs/Security/warden.yml | 9 +- .../Roles/Jobs/Ship_VS_Ship/nanotrasen.yml | 69 - .../Roles/Jobs/Ship_VS_Ship/syndicate.yml | 68 - .../Prototypes/Roles/Jobs/Wildcards/boxer.yml | 6 - .../Roles/Jobs/Wildcards/psychologist.yml | 4 - .../Roles/Jobs/Wildcards/reporter.yml | 5 - .../Roles/Jobs/Wildcards/zookeeper.yml | 4 - 155 files changed, 14274 insertions(+), 1267 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 create mode 100644 Resources/Prototypes/Loadouts/Jobs/Cargo/cargo_technician.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Cargo/quartermaster.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Cargo/salvage_specialist.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/bartender.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/botanist.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/chaplain.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/chef.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/clown.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/janitor.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/lawyer.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/librarian.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/mime.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/musician.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Civilian/passenger.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Command/captain.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Command/head_of_personnel.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Engineering/atmospheric_technician.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Engineering/chief_engineer.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Engineering/station_engineer.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Engineering/technical_assistant.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Medical/chemist.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Medical/chief_medical_officer.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Medical/medical_doctor.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Medical/medical_intern.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Medical/paramedic.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Science/research_director.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Science/scientist.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Security/detective.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Security/head_of_security.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Security/security_cadet.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Security/security_officer.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Security/warden.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Wildcards/boxer.yml create mode 100644 Resources/Prototypes/Loadouts/Jobs/Wildcards/reporter.yml create mode 100644 Resources/Prototypes/Loadouts/Miscellaneous/trinkets.yml create mode 100644 Resources/Prototypes/Loadouts/loadout_groups.yml create mode 100644 Resources/Prototypes/Loadouts/role_loadouts.yml delete mode 100644 Resources/Prototypes/Roles/Jobs/Ship_VS_Ship/nanotrasen.yml delete mode 100644 Resources/Prototypes/Roles/Jobs/Ship_VS_Ship/syndicate.yml diff --git a/Content.Benchmarks/SpawnEquipDeleteBenchmark.cs b/Content.Benchmarks/SpawnEquipDeleteBenchmark.cs index de51b2fb19..8512107b69 100644 --- a/Content.Benchmarks/SpawnEquipDeleteBenchmark.cs +++ b/Content.Benchmarks/SpawnEquipDeleteBenchmark.cs @@ -58,7 +58,7 @@ public class SpawnEquipDeleteBenchmark 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/IoC/ClientContentIoC.cs b/Content.Client/IoC/ClientContentIoC.cs index 70fe191658..65e95b76f0 100644 --- a/Content.Client/IoC/ClientContentIoC.cs +++ b/Content.Client/IoC/ClientContentIoC.cs @@ -21,6 +21,7 @@ using Content.Shared.Module; 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 @@ namespace Content.Client.IoC { 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 fe31dce062..98c109afde 100644 --- a/Content.Client/Lobby/LobbyState.cs +++ b/Content.Client/Lobby/LobbyState.cs @@ -70,7 +70,7 @@ namespace Content.Client.Lobby _characterSetup.SaveButton.OnPressed += _ => { _characterSetup.Save(); - _lobby.CharacterPreview.UpdateUI(); + _userInterfaceManager.GetUIController().UpdateCharacterUI(); }; LayoutContainer.SetAnchorPreset(_lobby, LayoutContainer.LayoutPreset.Wide); @@ -84,10 +84,6 @@ namespace Content.Client.Lobby _gameTicker.InfoBlobUpdated += UpdateLobbyUi; _gameTicker.LobbyStatusUpdated += LobbyStatusUpdated; _gameTicker.LobbyLateJoinStatusUpdated += LobbyLateJoinStatusUpdated; - - _preferencesManager.OnServerDataLoaded += PreferencesDataLoaded; - - _lobby.CharacterPreview.UpdateUI(); } protected override void Shutdown() @@ -109,13 +105,6 @@ namespace Content.Client.Lobby _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 0000000000..19f43e0575 --- /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 f9481caa3b..0000000000 --- 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 0000000000..997507414c --- /dev/null +++ b/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.xaml @@ -0,0 +1,22 @@ + + + + + + +