Add group for loadouts (#36951)
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
This commit is contained in:
@@ -20,6 +20,12 @@ public sealed partial class LoadoutContainer : BoxContainer
|
|||||||
|
|
||||||
public Button Select => SelectButton;
|
public Button Select => SelectButton;
|
||||||
|
|
||||||
|
public string? Text
|
||||||
|
{
|
||||||
|
get => SelectButton.Text;
|
||||||
|
set => SelectButton.Text = value;
|
||||||
|
}
|
||||||
|
|
||||||
public LoadoutContainer(ProtoId<LoadoutPrototype> proto, bool disabled, FormattedMessage? reason)
|
public LoadoutContainer(ProtoId<LoadoutPrototype> proto, bool disabled, FormattedMessage? reason)
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
@@ -54,22 +60,9 @@ public sealed partial class LoadoutContainer : BoxContainer
|
|||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
base.Dispose(disposing);
|
base.Dispose(disposing);
|
||||||
|
|
||||||
if (!disposing)
|
if (!disposing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_entManager.DeleteEntity(_entity);
|
_entManager.DeleteEntity(_entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Pressed
|
|
||||||
{
|
|
||||||
get => SelectButton.Pressed;
|
|
||||||
set => SelectButton.Pressed = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string? Text
|
|
||||||
{
|
|
||||||
get => SelectButton.Text;
|
|
||||||
set => SelectButton.Text = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
<BoxContainer xmlns="https://spacestation14.io"
|
<BoxContainer xmlns="https://spacestation14.io"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
Orientation="Vertical">
|
Orientation="Vertical">
|
||||||
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True">
|
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True" Margin="5">
|
||||||
<BoxContainer Name="LoadoutsContainer" Orientation="Vertical"/>
|
<BoxContainer Name="LoadoutsContainer" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True"/>
|
||||||
</PanelContainer>
|
</PanelContainer>
|
||||||
<!-- Buffer space so we have 10 margin between controls but also 10 to the borders -->
|
<!-- Buffer space so we have 10 margin between controls but also 10 to the borders -->
|
||||||
<Label Text="{Loc 'loadout-restrictions'}" Margin="5 0 5 5"/>
|
<PanelContainer StyleClasses="AngleRect" HorizontalExpand="True" Margin="5">
|
||||||
|
<BoxContainer Orientation="Vertical">
|
||||||
|
<Label Text="{Loc 'loadout-restrictions'}"/>
|
||||||
<BoxContainer Name="RestrictionsContainer" Orientation="Vertical" HorizontalExpand="True" />
|
<BoxContainer Name="RestrictionsContainer" Orientation="Vertical" HorizontalExpand="True" />
|
||||||
|
</BoxContainer>
|
||||||
|
</PanelContainer>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Shared.Clothing;
|
using Content.Shared.Clothing;
|
||||||
using Content.Shared.Preferences;
|
using Content.Shared.Preferences;
|
||||||
using Content.Shared.Preferences.Loadouts;
|
using Content.Shared.Preferences.Loadouts;
|
||||||
@@ -7,12 +6,21 @@ using Robust.Client.UserInterface.Controls;
|
|||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Content.Client.Lobby.UI.Loadouts;
|
namespace Content.Client.Lobby.UI.Loadouts;
|
||||||
|
|
||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public sealed partial class LoadoutGroupContainer : BoxContainer
|
public sealed partial class LoadoutGroupContainer : BoxContainer
|
||||||
{
|
{
|
||||||
|
private const string ClosedGroupMark = "▶";
|
||||||
|
private const string OpenedGroupMark = "▼";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A dictionary that stores open groups
|
||||||
|
/// </summary>
|
||||||
|
private Dictionary<string, bool> _openedGroups = new();
|
||||||
|
|
||||||
private readonly LoadoutGroupPrototype _groupProto;
|
private readonly LoadoutGroupPrototype _groupProto;
|
||||||
|
|
||||||
public event Action<ProtoId<LoadoutPrototype>>? OnLoadoutPressed;
|
public event Action<ProtoId<LoadoutPrototype>>? OnLoadoutPressed;
|
||||||
@@ -21,6 +29,7 @@ public sealed partial class LoadoutGroupContainer : BoxContainer
|
|||||||
public LoadoutGroupContainer(HumanoidCharacterProfile profile, RoleLoadout loadout, LoadoutGroupPrototype groupProto, ICommonSession session, IDependencyCollection collection)
|
public LoadoutGroupContainer(HumanoidCharacterProfile profile, RoleLoadout loadout, LoadoutGroupPrototype groupProto, ICommonSession session, IDependencyCollection collection)
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
_groupProto = groupProto;
|
_groupProto = groupProto;
|
||||||
|
|
||||||
RefreshLoadouts(profile, loadout, session, collection);
|
RefreshLoadouts(profile, loadout, session, collection);
|
||||||
@@ -63,32 +72,165 @@ public sealed partial class LoadoutGroupContainer : BoxContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
LoadoutsContainer.DisposeAllChildren();
|
LoadoutsContainer.DisposeAllChildren();
|
||||||
// Didn't use options because this is more robust in future.
|
|
||||||
|
|
||||||
var selected = loadout.SelectedLoadouts[_groupProto.ID];
|
// Get all loadout prototypes for this group.
|
||||||
|
var validProtos = _groupProto.Loadouts.Select(id => protoMan.Index(id));
|
||||||
|
|
||||||
foreach (var loadoutProto in _groupProto.Loadouts)
|
/*
|
||||||
|
* Group the prototypes based on their GroupBy field.
|
||||||
|
* - If GroupBy is null or empty, fallback to grouping by the prototype ID itself.
|
||||||
|
* - The result is a dictionary where:
|
||||||
|
* - The key is either GroupBy or ID (if GroupBy is not set).
|
||||||
|
* - The value is the list of prototypes that belong to that group.
|
||||||
|
*
|
||||||
|
* This allows grouping loadouts into sub-categories within the group.
|
||||||
|
*/
|
||||||
|
var groups = validProtos
|
||||||
|
.GroupBy(p => string.IsNullOrEmpty(p.GroupBy)
|
||||||
|
? p.ID
|
||||||
|
: p.GroupBy)
|
||||||
|
.ToDictionary(g => g.Key, g => g.ToList());
|
||||||
|
|
||||||
|
foreach (var kvp in groups)
|
||||||
{
|
{
|
||||||
if (!protoMan.TryIndex(loadoutProto, out var loadProto))
|
var protos = kvp.Value;
|
||||||
continue;
|
|
||||||
|
|
||||||
var matchingLoadout = selected.FirstOrDefault(e => e.Prototype == loadoutProto);
|
if (protos.Count > 1)
|
||||||
var pressed = matchingLoadout != null;
|
|
||||||
|
|
||||||
var enabled = loadout.IsValid(profile, session, loadoutProto, collection, out var reason);
|
|
||||||
var loadoutContainer = new LoadoutContainer(loadoutProto, !enabled, reason);
|
|
||||||
loadoutContainer.Select.Pressed = pressed;
|
|
||||||
loadoutContainer.Text = loadoutSystem.GetName(loadProto);
|
|
||||||
|
|
||||||
loadoutContainer.Select.OnPressed += args =>
|
|
||||||
{
|
{
|
||||||
if (args.Button.Pressed)
|
/*
|
||||||
OnLoadoutPressed?.Invoke(loadoutProto);
|
* Build the list of UI elements for each loadout prototype:
|
||||||
|
* - For each prototype, create its corresponding LoadoutContainer UI element.
|
||||||
|
* - Set HorizontalExpand to true so elements properly stretch in layout.
|
||||||
|
* - Collect all UI elements into a list for further processing.
|
||||||
|
*/
|
||||||
|
var uiElements = protos
|
||||||
|
.Select(proto =>
|
||||||
|
{
|
||||||
|
var elem = CreateLoadoutUI(proto, profile, loadout, session, collection, loadoutSystem);
|
||||||
|
elem.HorizontalExpand = true;
|
||||||
|
return elem;
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine which element should be displayed first:
|
||||||
|
* - If any element is currently selected (its button is pressed), use it.
|
||||||
|
* - Otherwise, fallback to the first element in the list.
|
||||||
|
*
|
||||||
|
* This moves the selected item outside of the sublist for better usability,
|
||||||
|
* making it easier for players to quickly toggle loadout options (e.g. clothing, accessories)
|
||||||
|
* without having to search inside expanded subgroups.
|
||||||
|
*/
|
||||||
|
var firstElement = uiElements.FirstOrDefault(e => e.Select.Pressed) ?? uiElements[0];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get all remaining elements except the first one:
|
||||||
|
* - Use ReferenceEquals to ensure we exclude the exact instance used as firstElement.
|
||||||
|
*/
|
||||||
|
var otherElements = uiElements.Where(e => !ReferenceEquals(e, firstElement)).ToList();
|
||||||
|
|
||||||
|
firstElement.HorizontalExpand = true;
|
||||||
|
var subContainer = new SubLoadoutContainer()
|
||||||
|
{
|
||||||
|
Visible = _openedGroups.GetValueOrDefault(kvp.Key, false)
|
||||||
|
};
|
||||||
|
var toggle = CreateToggleButton(kvp, firstElement, subContainer);
|
||||||
|
|
||||||
|
LoadoutsContainer.AddChild(firstElement);
|
||||||
|
LoadoutsContainer.AddChild(subContainer);
|
||||||
|
|
||||||
|
var subList = subContainer.Grid;
|
||||||
|
foreach (var proto in otherElements)
|
||||||
|
{
|
||||||
|
subList.AddChild(proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateToggleColor(toggle, subList);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
OnLoadoutUnpressed?.Invoke(loadoutProto);
|
{
|
||||||
|
LoadoutsContainer.AddChild(
|
||||||
|
CreateLoadoutUI(protos[0], profile, loadout, session, collection, loadoutSystem)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ToggleLoadoutButton CreateToggleButton(KeyValuePair<string, List<LoadoutPrototype>> kvp, LoadoutContainer firstElement, SubLoadoutContainer subContainer)
|
||||||
|
{
|
||||||
|
var toggle = new ToggleLoadoutButton
|
||||||
|
{
|
||||||
|
Text = ClosedGroupMark
|
||||||
};
|
};
|
||||||
|
|
||||||
LoadoutsContainer.AddChild(loadoutContainer);
|
toggle.Text = subContainer.Visible ? OpenedGroupMark : ClosedGroupMark;
|
||||||
|
|
||||||
|
toggle.OnPressed += _ =>
|
||||||
|
{
|
||||||
|
var willOpen = !subContainer.Visible;
|
||||||
|
subContainer.Visible = willOpen;
|
||||||
|
toggle.Text = willOpen ? OpenedGroupMark : ClosedGroupMark;
|
||||||
|
_openedGroups[kvp.Key] = willOpen;
|
||||||
|
};
|
||||||
|
|
||||||
|
firstElement.AddChild(toggle);
|
||||||
|
toggle.SetPositionFirst();
|
||||||
|
return toggle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateToggleColor(Button toggle, BoxContainer subList)
|
||||||
|
{
|
||||||
|
var anyActive = subList.Children
|
||||||
|
.OfType<LoadoutContainer>()
|
||||||
|
.Any(c => c.Select.Pressed);
|
||||||
|
|
||||||
|
toggle.Modulate = anyActive
|
||||||
|
? Color.Green
|
||||||
|
: Color.White;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a UI container for a single Loadout item.
|
||||||
|
///
|
||||||
|
/// This method was extracted from RefreshLoadouts because the logic for creating
|
||||||
|
/// individual loadout items is used multiple times inside that method, and duplicating
|
||||||
|
/// the code made it harder to maintain.
|
||||||
|
///
|
||||||
|
/// Logic:
|
||||||
|
/// - Checks if the item is currently selected in the loadout.
|
||||||
|
/// - Checks if the item is valid for selection (IsValid).
|
||||||
|
/// - Creates a LoadoutContainer with the appropriate status (disabled / active).
|
||||||
|
/// - Subscribes to button press events to handle selection and deselection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="proto">The loadout item prototype.</param>
|
||||||
|
/// <param name="profile">The humanoid character profile.</param>
|
||||||
|
/// <param name="loadout">The current role loadout for the user.</param>
|
||||||
|
/// <param name="session">The user's session.</param>
|
||||||
|
/// <param name="collection">The dependency injection container.</param>
|
||||||
|
/// <param name="loadoutSystem">The loadout system instance.</param>
|
||||||
|
/// <returns>A fully initialized LoadoutContainer for UI display.</returns>
|
||||||
|
private LoadoutContainer CreateLoadoutUI(LoadoutPrototype proto, HumanoidCharacterProfile profile, RoleLoadout loadout, ICommonSession session, IDependencyCollection collection, LoadoutSystem loadoutSystem)
|
||||||
|
{
|
||||||
|
var selected = loadout.SelectedLoadouts[_groupProto.ID];
|
||||||
|
|
||||||
|
var pressed = selected.Any(e => e.Prototype == proto.ID);
|
||||||
|
|
||||||
|
var enabled = loadout.IsValid(profile, session, proto.ID, collection, out var reason);
|
||||||
|
|
||||||
|
var cont = new LoadoutContainer(proto, !enabled, reason);
|
||||||
|
|
||||||
|
cont.Text = loadoutSystem.GetName(proto);
|
||||||
|
|
||||||
|
cont.Select.Pressed = pressed;
|
||||||
|
|
||||||
|
cont.Select.OnPressed += args =>
|
||||||
|
{
|
||||||
|
if (args.Button.Pressed)
|
||||||
|
OnLoadoutPressed?.Invoke(proto.ID);
|
||||||
|
else
|
||||||
|
OnLoadoutUnpressed?.Invoke(proto.ID);
|
||||||
|
};
|
||||||
|
|
||||||
|
return cont;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<PanelContainer Name="SubContainer"
|
||||||
|
xmlns="https://spacestation14.io"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<BoxContainer Name="SubGridContainer"
|
||||||
|
Orientation="Vertical"
|
||||||
|
HorizontalExpand="true"/>
|
||||||
|
|
||||||
|
</PanelContainer>
|
||||||
21
Content.Client/Lobby/UI/Loadouts/SubLoadoutContainer.xaml.cs
Normal file
21
Content.Client/Lobby/UI/Loadouts/SubLoadoutContainer.xaml.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
|
||||||
|
namespace Content.Client.Lobby.UI.Loadouts;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A simple container used to group additional loadout UI elements
|
||||||
|
/// that are part of the same GroupBy subgroup.
|
||||||
|
///
|
||||||
|
/// - Used when a loadout group contains multiple prototypes.
|
||||||
|
/// - The first prototype is shown directly; the remaining ones are placed inside this container.
|
||||||
|
/// - Allows toggling visibility of the subgroup via expandable UI (collapsible behavior).
|
||||||
|
///
|
||||||
|
/// Internally inherits from PanelContainer to allow for border/background styling if needed.
|
||||||
|
/// Exposes its internal BoxContainer (SubGridContainer) via the <see cref="Grid"/> property for adding children.
|
||||||
|
/// </summary>
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class SubLoadoutContainer : PanelContainer
|
||||||
|
{
|
||||||
|
public BoxContainer Grid => SubGridContainer;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<Button Name="ToggleButton"
|
||||||
|
xmlns="https://spacestation14.io"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
VerticalExpand="False"
|
||||||
|
HorizontalExpand="False"
|
||||||
|
SetSize="64 64"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0 0 5 0"/>
|
||||||
10
Content.Client/Lobby/UI/Loadouts/ToggleLoadoutButton.xaml.cs
Normal file
10
Content.Client/Lobby/UI/Loadouts/ToggleLoadoutButton.xaml.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
|
||||||
|
namespace Content.Client.Lobby.UI.Loadouts;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A button that toggles the loadout groups. Needs for override default styles.
|
||||||
|
/// </summary>
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class ToggleLoadoutButton : Button;
|
||||||
@@ -13,6 +13,11 @@ public sealed partial class LoadoutPrototype : IPrototype, IEquipmentLoadout
|
|||||||
[IdDataField]
|
[IdDataField]
|
||||||
public string ID { get; private set; } = string.Empty;
|
public string ID { get; private set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A text identifier used to group loadouts.
|
||||||
|
/// </summary>
|
||||||
|
[DataField]
|
||||||
|
public string? GroupBy;
|
||||||
/*
|
/*
|
||||||
* You can either use an existing StartingGearPrototype or specify it inline to avoid bloating yaml.
|
* You can either use an existing StartingGearPrototype or specify it inline to avoid bloating yaml.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -13,31 +13,37 @@
|
|||||||
id: HeadofSecurityJumpsuit
|
id: HeadofSecurityJumpsuit
|
||||||
equipment:
|
equipment:
|
||||||
jumpsuit: ClothingUniformJumpsuitHoS
|
jumpsuit: ClothingUniformJumpsuitHoS
|
||||||
|
groupBy: "jumpsuit"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: HeadofSecurityJumpskirt
|
id: HeadofSecurityJumpskirt
|
||||||
equipment:
|
equipment:
|
||||||
jumpsuit: ClothingUniformJumpskirtHoS
|
jumpsuit: ClothingUniformJumpskirtHoS
|
||||||
|
groupBy: "jumpskirt"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: HeadofSecurityTurtleneck
|
id: HeadofSecurityTurtleneck
|
||||||
equipment:
|
equipment:
|
||||||
jumpsuit: ClothingUniformJumpsuitHoSAlt
|
jumpsuit: ClothingUniformJumpsuitHoSAlt
|
||||||
|
groupBy: "jumpsuit"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: HeadofSecurityTurtleneckSkirt
|
id: HeadofSecurityTurtleneckSkirt
|
||||||
equipment:
|
equipment:
|
||||||
jumpsuit: ClothingUniformJumpskirtHoSAlt
|
jumpsuit: ClothingUniformJumpskirtHoSAlt
|
||||||
|
groupBy: "jumpskirt"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: HeadofSecurityFormalSuit
|
id: HeadofSecurityFormalSuit
|
||||||
equipment:
|
equipment:
|
||||||
jumpsuit: ClothingUniformJumpsuitHosFormal
|
jumpsuit: ClothingUniformJumpsuitHosFormal
|
||||||
|
groupBy: "jumpsuit"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: HeadofSecurityFormalSkirt
|
id: HeadofSecurityFormalSkirt
|
||||||
equipment:
|
equipment:
|
||||||
jumpsuit: ClothingUniformJumpskirtHosFormal
|
jumpsuit: ClothingUniformJumpskirtHosFormal
|
||||||
|
groupBy: "jumpskirt"
|
||||||
|
|
||||||
# Head
|
# Head
|
||||||
- type: loadout
|
- type: loadout
|
||||||
|
|||||||
@@ -56,30 +56,35 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- Lighter
|
- Lighter
|
||||||
|
groupBy: "smokeables"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: CigPackGreen
|
id: CigPackGreen
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- CigPackGreen
|
- CigPackGreen
|
||||||
|
groupBy: "smokeables"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: CigPackRed
|
id: CigPackRed
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- CigPackRed
|
- CigPackRed
|
||||||
|
groupBy: "smokeables"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: CigPackBlue
|
id: CigPackBlue
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- CigPackBlue
|
- CigPackBlue
|
||||||
|
groupBy: "smokeables"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: CigPackBlack
|
id: CigPackBlack
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- CigPackBlack
|
- CigPackBlack
|
||||||
|
groupBy: "smokeables"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: CigarCase
|
id: CigarCase
|
||||||
@@ -89,6 +94,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- CigarCase
|
- CigarCase
|
||||||
|
groupBy: "smokeables"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: CigarGold
|
id: CigarGold
|
||||||
@@ -98,6 +104,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- CigarGold
|
- CigarGold
|
||||||
|
groupBy: "smokeables"
|
||||||
|
|
||||||
# Pins
|
# Pins
|
||||||
- type: loadout
|
- type: loadout
|
||||||
@@ -105,108 +112,126 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckLGBTPin
|
- ClothingNeckLGBTPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckAllyPin
|
id: ClothingNeckAllyPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckAllyPin
|
- ClothingNeckAllyPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckAromanticPin
|
id: ClothingNeckAromanticPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckAromanticPin
|
- ClothingNeckAromanticPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckAsexualPin
|
id: ClothingNeckAsexualPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckAsexualPin
|
- ClothingNeckAsexualPin
|
||||||
|
groupBy: "pin"
|
||||||
- type: loadout
|
|
||||||
id: ClothingNeckAroacePin
|
|
||||||
storage:
|
|
||||||
back:
|
|
||||||
- ClothingNeckAroacePin
|
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckBisexualPin
|
id: ClothingNeckBisexualPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckBisexualPin
|
- ClothingNeckBisexualPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckGayPin
|
id: ClothingNeckGayPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckGayPin
|
- ClothingNeckGayPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckIntersexPin
|
id: ClothingNeckIntersexPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckIntersexPin
|
- ClothingNeckIntersexPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckLesbianPin
|
id: ClothingNeckLesbianPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckLesbianPin
|
- ClothingNeckLesbianPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckNonBinaryPin
|
id: ClothingNeckNonBinaryPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckNonBinaryPin
|
- ClothingNeckNonBinaryPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckPansexualPin
|
id: ClothingNeckPansexualPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckPansexualPin
|
- ClothingNeckPansexualPin
|
||||||
|
groupBy: "pin"
|
||||||
- type: loadout
|
|
||||||
id: ClothingNeckPluralPin
|
|
||||||
storage:
|
|
||||||
back:
|
|
||||||
- ClothingNeckPluralPin
|
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckOmnisexualPin
|
id: ClothingNeckOmnisexualPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckOmnisexualPin
|
- ClothingNeckOmnisexualPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckGenderqueerPin
|
id: ClothingNeckGenderqueerPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckGenderqueerPin
|
- ClothingNeckGenderqueerPin
|
||||||
|
groupBy: "pin"
|
||||||
- type: loadout
|
|
||||||
id: ClothingNeckGenderfluidPin
|
|
||||||
storage:
|
|
||||||
back:
|
|
||||||
- ClothingNeckGenderfluidPin
|
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckTransPin
|
id: ClothingNeckTransPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckTransPin
|
- ClothingNeckTransPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckAutismPin
|
id: ClothingNeckAutismPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckAutismPin
|
- ClothingNeckAutismPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: ClothingNeckGoldAutismPin
|
id: ClothingNeckGoldAutismPin
|
||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- ClothingNeckGoldAutismPin
|
- ClothingNeckGoldAutismPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
|
- type: loadout
|
||||||
|
id: ClothingNeckAroacePin
|
||||||
|
storage:
|
||||||
|
back:
|
||||||
|
- ClothingNeckAroacePin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
|
- type: loadout
|
||||||
|
id: ClothingNeckPluralPin
|
||||||
|
storage:
|
||||||
|
back:
|
||||||
|
- ClothingNeckPluralPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
|
- type: loadout
|
||||||
|
id: ClothingNeckGenderfluidPin
|
||||||
|
storage:
|
||||||
|
back:
|
||||||
|
- ClothingNeckGenderfluidPin
|
||||||
|
groupBy: "pin"
|
||||||
|
|
||||||
# Towels
|
# Towels
|
||||||
- type: loadout
|
- type: loadout
|
||||||
@@ -219,6 +244,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorWhite
|
- TowelColorWhite
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorSilver
|
id: TowelColorSilver
|
||||||
@@ -230,6 +256,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorSilver
|
- TowelColorSilver
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorGold
|
id: TowelColorGold
|
||||||
@@ -241,6 +268,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorGold
|
- TowelColorGold
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorLightBrown
|
id: TowelColorLightBrown
|
||||||
@@ -253,6 +281,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorLightBrown
|
- TowelColorLightBrown
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorGreen
|
id: TowelColorGreen
|
||||||
@@ -265,6 +294,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorGreen
|
- TowelColorGreen
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorDarkBlue
|
id: TowelColorDarkBlue
|
||||||
@@ -277,6 +307,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorDarkBlue
|
- TowelColorDarkBlue
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorOrange
|
id: TowelColorOrange
|
||||||
@@ -289,6 +320,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorOrange
|
- TowelColorOrange
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorLightBlue
|
id: TowelColorLightBlue
|
||||||
@@ -301,6 +333,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorLightBlue
|
- TowelColorLightBlue
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorPurple
|
id: TowelColorPurple
|
||||||
@@ -313,6 +346,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorPurple
|
- TowelColorPurple
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorRed
|
id: TowelColorRed
|
||||||
@@ -325,6 +359,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorRed
|
- TowelColorRed
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorGray
|
id: TowelColorGray
|
||||||
@@ -337,6 +372,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorGray
|
- TowelColorGray
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorBlack
|
id: TowelColorBlack
|
||||||
@@ -349,6 +385,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorBlack
|
- TowelColorBlack
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorDarkGreen
|
id: TowelColorDarkGreen
|
||||||
@@ -361,6 +398,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorDarkGreen
|
- TowelColorDarkGreen
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorMaroon
|
id: TowelColorMaroon
|
||||||
@@ -373,6 +411,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorMaroon
|
- TowelColorMaroon
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorYellow
|
id: TowelColorYellow
|
||||||
@@ -385,6 +424,7 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorYellow
|
- TowelColorYellow
|
||||||
|
groupBy: "towels"
|
||||||
|
|
||||||
- type: loadout
|
- type: loadout
|
||||||
id: TowelColorMime
|
id: TowelColorMime
|
||||||
@@ -397,3 +437,4 @@
|
|||||||
storage:
|
storage:
|
||||||
back:
|
back:
|
||||||
- TowelColorMime
|
- TowelColorMime
|
||||||
|
groupBy: "towels"
|
||||||
|
|||||||
Reference in New Issue
Block a user