Files
wwdpublic/Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs
DEATHB4DEFEAT 528557383a Loadouts (#45)
Description copied from my Wizard's Den PR
Resolves https://github.com/Simple-Station/Einstein-Engines/issues/32

# TODO

- [x] CVars
- [x] Server side loadout point validation
- Make tabContainer less bad
- [x] Move head clothes to loadouts from lockers
- [x] Move job starting equipment to loadouts
- [x] Loadout item preview
- [x] Fix loadouts duplicating on server restart
- [x] Make sure everything is localized -- Components and Tags are an
odd thing to display to the player in the whitelist and are very
unrealistic to make localizations for, so.. not doing that, what do I
do?
- [x] Fix all items going into the bag no matter their size
- [x] Add min/cur/max points to the bar
- [x] Use buttons instead of checkboxes
- [x] "Show Unusable" button to hide things your character currently
doesn't match the whitelists for
- [x] Time whitelist option
- [x] Species whitelist option
- [x] Trait whitelist option instead of EntityWhitelist for the sake of
localization
- [ ] More loadouts (filler things while waiting for review)
- [ ] - Golden or themed items for Command roles with an undecided
amount of playtime on their respective jobs
- [x] - Goliath cloak for playing a lot of Salvage
- [x] - Senior items for playing a lot of its respective role
- [ ] - Varying materials of pocket watches for people with varying
overall playtime
- [x] Fix loadout selectors not updating to match current preferences

<details><summary><h1>Media (Click Me!)</h1></summary>
<p>

I need to rerecord these


https://github.com/space-wizards/space-station-14/assets/77995199/59713874-b043-4813-848e-56b2951b6935


https://github.com/space-wizards/space-station-14/assets/77995199/40180aee-bfe3-4f30-9df8-0f628e7e4514

</p>
</details> 

# Changelog

🆑
- add: Added a new character customization tab for selecting items to
start your shift with, loadouts!
- remove: Removed some default job equipment in favor of loadouts
- remove: Removed several clothing items from Command lockers in favor
of loadouts

---------

Co-authored-by: VMSolidus <evilexecutive@gmail.com>
2024-05-13 00:46:57 -04:00

174 lines
6.7 KiB
C#

using System.Linq;
using System.Numerics;
using Content.Client.Humanoid;
using Content.Client.Inventory;
using Content.Client.Preferences;
using Content.Client.UserInterface.Controls;
using Content.Shared.Clothing.Loadouts.Systems;
using Content.Shared.GameTicking;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Preferences;
using Content.Shared.Roles;
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<SpeciesPrototype>(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<HumanoidAppearanceSystem>().LoadProfile(_previewDummy.Value, selectedCharacter);
GiveDummyJobClothes(_previewDummy.Value, selectedCharacter);
GiveDummyLoadoutItems(_previewDummy.Value, selectedCharacter);
}
}
}
public static void GiveDummyJobClothes(EntityUid dummy, HumanoidCharacterProfile profile)
{
var protoMan = IoCManager.Resolve<IPrototypeManager>();
var entMan = IoCManager.Resolve<IEntityManager>();
var invSystem = EntitySystem.Get<ClientInventorySystem>();
var highPriorityJob = profile.JobPriorities.FirstOrDefault(p => p.Value == JobPriority.High).Key;
// ReSharper disable once NullCoalescingConditionIsAlwaysNotNullAccordingToAPIContract (what is resharper smoking?)
var job = protoMan.Index<JobPrototype>(highPriorityJob ?? SharedGameTicker.FallbackOverflowJob);
if (job.StartingGear != null && invSystem.TryGetSlots(dummy, out var slots))
{
var gear = protoMan.Index<StartingGearPrototype>(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);
}
}
}
}
public static void GiveDummyLoadoutItems(EntityUid dummy, HumanoidCharacterProfile profile)
{
var highPriorityJobId = profile.JobPriorities.FirstOrDefault(j => j.Value == JobPriority.High).Key;
var highPriorityJob = IoCManager.Resolve<IPrototypeManager>().Index<JobPrototype>(highPriorityJobId ?? SharedGameTicker.FallbackOverflowJob);
EntitySystem.Get<LoadoutSystem>().ApplyCharacterLoadout(dummy, highPriorityJob, profile);
}
}
}