Skip to content

Commit

Permalink
Loadout
Browse files Browse the repository at this point in the history
  • Loading branch information
Schrodinger71 committed Nov 18, 2023
1 parent 5a98841 commit 7487b29
Show file tree
Hide file tree
Showing 40 changed files with 4,695 additions and 29 deletions.
13 changes: 13 additions & 0 deletions Content.Client/Lobby/UI/LobbyCharacterPreviewPanel.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
using System.Linq;
using System.Numerics;
using Content.Client.Alerts;
using Content.Client.Hands.Systems;
using Content.Client.Humanoid;
using Content.Client.Inventory;
using Content.Client.Preferences;
using Content.Client.UserInterface.Controls;
using Content.Shared.Clothing;
using Content.Shared.Clothing.Components;
using Content.Shared.GameTicking;
using Content.Shared.Humanoid.Prototypes;
using Content.Shared.Inventory;
using Content.Shared.Loadouts;
using Content.Shared.Preferences;
using Content.Shared.Roles;
using Robust.Client.GameObjects;
Expand Down Expand Up @@ -126,6 +130,7 @@ public void UpdateUI()
_summaryLabel.Text = selectedCharacter.Summary;
_entityManager.System<HumanoidAppearanceSystem>().LoadProfile(_previewDummy.Value, selectedCharacter);
GiveDummyJobClothes(_previewDummy.Value, selectedCharacter);
GiveDummyLoadoutItems(_previewDummy.Value, selectedCharacter);
}
}
}
Expand Down Expand Up @@ -161,5 +166,13 @@ public static void GiveDummyJobClothes(EntityUid dummy, HumanoidCharacterProfile
}
}
}
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);
}

}
}
1 change: 1 addition & 0 deletions Content.Client/Preferences/UI/CharacterSetupGui.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ public CharacterPickerButton(
if (humanoid != null)
{
LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy, humanoid);
LobbyCharacterPreviewPanel.GiveDummyLoadoutItems(_previewDummy, humanoid);
}

var isSelectedCharacter = profile == preferencesManager.Preferences?.SelectedCharacter;
Expand Down
13 changes: 13 additions & 0 deletions Content.Client/Preferences/UI/HumanoidProfileEditor.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@
<Control HorizontalExpand="True"/>
<Button Name="ShowClothes" Pressed="True" ToggleMode="True" Text="{Loc 'humanoid-profile-editor-clothing-show'}" HorizontalAlignment="Right" />
</BoxContainer>
<!-- Show loadouts -->
<BoxContainer HorizontalExpand="True">
<Label Text="{Loc 'humanoid-profile-editor-loadouts'}" />
<Control HorizontalExpand="True"/>
<Button Name="ShowLoadouts" Pressed="True" ToggleMode="True" Text="{Loc 'Show'}" HorizontalAlignment="Right" />
</BoxContainer>
<!-- Clothing -->
<BoxContainer HorizontalExpand="True">
<Label Text="{Loc 'humanoid-profile-editor-clothing-label'}" />
Expand Down Expand Up @@ -143,6 +149,13 @@
<BoxContainer Name="CTraitsList" Orientation="Vertical" />
</ScrollContainer>
</BoxContainer>
<BoxContainer Name="CLoadoutsTab" Orientation="Vertical" Margin="10">
<!-- Loadouts -->
<ProgressBar Name="LoadoutPoints" MaxValue="1" Value="1" />
<ScrollContainer VerticalExpand="True">
<TabContainer Name="CLoadoutsTabs" VerticalExpand="True" />
</ScrollContainer>
</BoxContainer>
<BoxContainer Name="CMarkingsTab" Orientation="Vertical" Margin="10">
<!-- Markings -->
<ScrollContainer VerticalExpand="True">
Expand Down
225 changes: 223 additions & 2 deletions Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System.Linq;
using System.Numerics;
using System.Text;
using Content.Client.Humanoid;
using Content.Client.Lobby.UI;
using Content.Client.Message;
using Content.Client.Players.PlayTimeTracking;
using Content.Client.Stylesheets;
using Content.Client.UserInterface.Controls;
using Content.Shared.CCVar;
using Content.Shared.Clothing;
using Content.Shared.GameTicking;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
Expand All @@ -16,6 +18,7 @@
using Content.Shared.Roles;
using Content.Shared.Sirena;
using Content.Shared.StatusIcon;
using Content.Shared.Loadouts;
using Content.Shared.Traits;
using Robust.Client.AutoGenerated;
using Robust.Client.GameObjects;
Expand Down Expand Up @@ -61,7 +64,7 @@ public sealed partial class HumanoidProfileEditor : Control
private readonly IConfigurationManager _configurationManager;
private readonly MarkingManager _markingManager;
private readonly JobRequirementsManager _requirements;

private readonly LoadoutSystem _loadoutSystem;
private LineEdit _ageEdit => CAgeEdit;
private LineEdit _nameEdit => CNameEdit;
private TextEdit _flavorTextEdit = null!;
Expand All @@ -85,13 +88,17 @@ public sealed partial class HumanoidProfileEditor : Control
private BoxContainer _jobList => CJobList;
private BoxContainer _antagList => CAntagList;
private BoxContainer _traitsList => CTraitsList;
private ProgressBar _loadoutPoints => LoadoutPoints;
private BoxContainer _loadoutsTab => CLoadoutsTab;
private TabContainer _loadoutsTabs => CLoadoutsTabs;
private readonly List<JobPrioritySelector> _jobPriorities;
private OptionButton _preferenceUnavailableButton => CPreferenceUnavailableButton;
private readonly Dictionary<string, BoxContainer> _jobCategories;
// Mildly hacky, as I don't trust prototype order to stay consistent and don't want the UI to break should a new one get added mid-edit. --moony
private readonly List<SpeciesPrototype> _speciesList;
private readonly List<AntagPreferenceSelector> _antagPreferences;
private readonly List<TraitPreferenceSelector> _traitPreferences;
private readonly List<LoadoutPreferenceSelector>? _loadoutPreferences;

private SpriteView _previewSpriteView => CSpriteView;
private Button _previewRotateLeftButton => CSpriteRotateLeft;
Expand Down Expand Up @@ -120,6 +127,7 @@ public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IProt
_preferencesManager = preferencesManager;
_configurationManager = configurationManager;
_markingManager = IoCManager.Resolve<MarkingManager>();
_loadoutSystem = EntitySystem.Get<LoadoutSystem>();

#region Left

Expand All @@ -141,6 +149,7 @@ public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IProt
_tabContainer.SetTabTitle(0, Loc.GetString("humanoid-profile-editor-appearance-tab"));

ShowClothes.OnPressed += ToggleClothes;
ShowLoadouts.OnPressed += ToggleClothes;

#region Sex

Expand Down Expand Up @@ -457,6 +466,118 @@ public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IProt
});
}

#endregion

#region Loadouts

_tabContainer.SetTabTitle(4, Loc.GetString("humanoid-profile-editor-loadouts-tab"));
_loadoutPreferences = new List<LoadoutPreferenceSelector>();
var loadouts = prototypeManager.EnumeratePrototypes<LoadoutPrototype>().ToList();

var loadoutsEnabled = _configurationManager.GetCVar(CCVars.GameLoadoutsEnabled);
_tabContainer.SetTabVisible(4, loadoutsEnabled);
ShowLoadouts.Visible = loadoutsEnabled;
_configurationManager.OnValueChanged(CCVars.GameLoadoutsEnabled, enabled =>
{
_tabContainer.SetTabVisible(4, enabled);
ShowLoadouts.Visible = enabled;
});
var points = _configurationManager.GetCVar(CCVars.GameLoadoutsPoints);
_loadoutPoints.MaxValue = points;
_loadoutPoints.Value = points;

if (loadouts.Count >= 0)
{
// Make Uncategorized category
var uncategorized = new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
Name = "Uncategorized_0"
};

_loadoutsTabs.AddChild(uncategorized);
_loadoutsTabs.SetTabTitle(0, Loc.GetString("humanoid-profile-editor-loadouts-uncategorized-tab"));

// Make categories
var currentCategory = 1;
foreach (var loadout in loadouts.OrderBy(l => l.Category))
{
// Check for existing category
BoxContainer? match = null;
foreach (var child in _loadoutsTabs.Children)
{
if (match != null || child.Name == null)
continue;
if (child.Name.Split("_")[0] == loadout.Category)
match = (BoxContainer) child;
}

// If there is a category do nothing
if (match != null)
continue;

// If not, make it
var box = new BoxContainer
{
Orientation = LayoutOrientation.Vertical,
VerticalExpand = true,
Name = $"{loadout.Category}_{currentCategory}"
};

_loadoutsTabs.AddChild(box);
_loadoutsTabs.SetTabTitle(currentCategory, Loc.GetString($"loadout-category-{loadout.Category}"));
currentCategory++;
}

// Fill categories
foreach (var loadout in loadouts.OrderBy(l => l.ID))
{
var selector = new LoadoutPreferenceSelector(loadout, _entMan, _loadoutSystem);

// Look for an existing loadout category
BoxContainer? match = null;
foreach (var child in _loadoutsTabs.Children)
{
if (match != null || child.Name == null)
continue;
if (child.Name.Split("_")[0] == loadout.Category)
match = (BoxContainer) child;
}

if (match?.Name == null)
uncategorized.AddChild(selector);
else
match.AddChild(selector);

_loadoutPreferences.Add(selector);
selector.PreferenceChanged += preference =>
{
// Make sure they have enough loadout points
if (preference)
{
var temp = _loadoutPoints.Value - loadout.Cost;
if (temp < 0)
preference = false;
else
_loadoutPoints.Value = temp;
}
else
_loadoutPoints.Value += loadout.Cost;
// Update Preference
Profile = Profile?.WithLoadoutPreference(loadout.ID, preference);
IsDirty = true;
UpdateLoadoutPreferences();
};
}

if (!uncategorized.Children.Any())
_loadoutsTabs.SetTabVisible(0, false);
}
else
_loadoutsTab.AddChild(new Label { Text = Loc.GetString("humanoid-profile-editor-loadouts-no-loadouts") });


#endregion

#region Save
Expand All @@ -466,7 +587,7 @@ public HumanoidProfileEditor(IClientPreferencesManager preferencesManager, IProt
#endregion Save

#region Markings
_tabContainer.SetTabTitle(4, Loc.GetString("humanoid-profile-editor-markings-tab"));
_tabContainer.SetTabTitle(5, Loc.GetString("humanoid-profile-editor-markings-tab"));

CMarkings.OnMarkingAdded += OnMarkingChange;
CMarkings.OnMarkingRemoved += OnMarkingChange;
Expand Down Expand Up @@ -1145,6 +1266,8 @@ private void UpdatePreview()

if (ShowClothes.Pressed)
LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy!.Value, Profile);
if (ShowLoadouts.Pressed)
LobbyCharacterPreviewPanel.GiveDummyLoadoutItems(_previewDummy!.Value, Profile);

_previewSpriteView.OverrideDirection = (Direction) ((int) _previewRotation % 4 * 2);
}
Expand All @@ -1167,6 +1290,7 @@ public void UpdateControls()
UpdateJobPriorities();
UpdateAntagPreferences();
UpdateTraitPreferences();
UpdateLoadoutPreferences();
UpdateMarkings();
RebuildSpriteView();
UpdateTTSVoicesControls(); // Corvax-TTS
Expand Down Expand Up @@ -1360,7 +1484,28 @@ private void UpdateTraitPreferences()
preferenceSelector.Preference = preference;
}
}
private void UpdateLoadoutPreferences()
{
var points = _configurationManager.GetCVar(CCVars.GameLoadoutsPoints);
_loadoutPoints.Value = points;

if (_loadoutPreferences == null)
return;

foreach (var preferenceSelector in _loadoutPreferences)
{
var loadoutId = preferenceSelector.Loadout.ID;
var preference = Profile?.LoadoutPreferences.Contains(loadoutId) ?? false;

preferenceSelector.Preference = preference;

if (preference)
{
points -= preferenceSelector.Loadout.Cost;
_loadoutPoints.Value = points;
}
}
}
private sealed class AntagPreferenceSelector : RequirementsSelector<AntagPrototype>
{
// 0 is yes and 1 is no
Expand Down Expand Up @@ -1433,5 +1578,81 @@ private void OnCheckBoxToggled(BaseButton.ButtonToggledEventArgs args)
PreferenceChanged?.Invoke(Preference);
}
}
private sealed class LoadoutPreferenceSelector : Control
{
public LoadoutPrototype Loadout { get; }
private readonly CheckBox _checkBox;

public bool Preference
{
get => _checkBox.Pressed;
set => _checkBox.Pressed = value;
}

public event Action<bool>? PreferenceChanged;

public LoadoutPreferenceSelector(LoadoutPrototype loadout, IEntityManager entityManager, LoadoutSystem loadoutSystem)
{
Loadout = loadout;

// Display the first item in the loadout as a preview
// TODO: Maybe allow custom icons to be specified in the prototype?
var dummyLoadoutItem = entityManager.SpawnEntity(loadout.Items.First(), MapCoordinates.Nullspace);

// Create a sprite preview of the loadout item
var previewLoadout = new SpriteView
{
Scale = new Vector2(1, 1),
OverrideDirection = Direction.South,
VerticalAlignment = VAlignment.Center,
SizeFlagsStretchRatio = 1
};
previewLoadout.SetEntity(dummyLoadoutItem);


// Create a checkbox to get the loadout
_checkBox = new CheckBox
{
Text = $"[{loadout.Cost}] {(Loc.GetString($"loadout-name-{loadout.ID}") == $"loadout-name-{loadout.ID}" ? entityManager.GetComponent<MetaDataComponent>(dummyLoadoutItem).EntityName : Loc.GetString($"loadout-name-{loadout.ID}"))}",
VerticalAlignment = VAlignment.Center
};
_checkBox.OnToggled += OnCheckBoxToggled;

var tooltip = new StringBuilder();
// Add the loadout description to the tooltip if there is one
var desc = Loc.GetString($"loadout-description-{loadout.ID}") == $"loadout-description-{loadout.ID}" ? entityManager.GetComponent<MetaDataComponent>(dummyLoadoutItem).EntityDescription : Loc.GetString($"loadout-description-{loadout.ID}");
if (!string.IsNullOrEmpty(desc))
{
tooltip.Append($"{Loc.GetString(desc)}");
if (loadoutSystem.LoadoutWhitelistExists(loadout) || loadoutSystem.LoadoutBlacklistExists(loadout))
tooltip.AppendLine();
}

// Add the loadout whitelist and blacklist descriptions to the tooltip if there are any
tooltip.Append(loadoutSystem.GetLoadoutWhitelistString(loadout));
tooltip.Append(loadoutSystem.GetLoadoutBlacklistString(loadout));

// If the tooltip has any content, add it to the checkbox
if (!string.IsNullOrEmpty(tooltip.ToString()))
{
_checkBox.ToolTip = tooltip.ToString();
_checkBox.TooltipDelay = 0.2f;
}


// Add the loadout preview and the checkbox to the control
AddChild(new BoxContainer
{
Orientation = LayoutOrientation.Horizontal,
Children = { previewLoadout, _checkBox },
});
}

private void OnCheckBoxToggled(BaseButton.ButtonToggledEventArgs args)
{
PreferenceChanged?.Invoke(Preference);
}
}

}
}
Loading

0 comments on commit 7487b29

Please sign in to comment.