Equip clothing to preview dummies in the lobby.
This commit is contained in:
@@ -108,24 +108,44 @@ namespace Content.Client.GameObjects
|
||||
|
||||
private void _setSlot(Slots slot, IEntity entity)
|
||||
{
|
||||
if (_sprite != null && entity.TryGetComponent(out ClothingComponent clothing))
|
||||
SetSlotVisuals(slot, entity);
|
||||
|
||||
InterfaceController?.AddToSlot(slot, entity);
|
||||
}
|
||||
|
||||
internal void SetSlotVisuals(Slots slot, IEntity entity)
|
||||
{
|
||||
if (_sprite == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity != null && entity.TryGetComponent(out ClothingComponent clothing))
|
||||
{
|
||||
var flag = SlotMasks[slot];
|
||||
var data = clothing.GetEquippedStateInfo(flag);
|
||||
if (data == null)
|
||||
{
|
||||
_sprite.LayerSetVisible(slot, false);
|
||||
}
|
||||
else
|
||||
if (data != null)
|
||||
{
|
||||
var (rsi, state) = data.Value;
|
||||
_sprite.LayerSetVisible(slot, true);
|
||||
_sprite.LayerSetRSI(slot, rsi);
|
||||
_sprite.LayerSetState(slot, state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
InterfaceController?.AddToSlot(slot, entity);
|
||||
_sprite.LayerSetVisible(slot, false);
|
||||
}
|
||||
|
||||
internal void ClearAllSlotVisuals()
|
||||
{
|
||||
foreach (var slot in InventoryInstance.SlotMasks)
|
||||
{
|
||||
if (slot != Slots.NONE)
|
||||
{
|
||||
_sprite.LayerSetVisible(slot, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void _clearSlot(Slots slot)
|
||||
|
||||
@@ -209,6 +209,10 @@ namespace Content.Client.UserInterface
|
||||
_previewDummy = entityManager.SpawnEntityAt("HumanMob_Dummy",
|
||||
new MapCoordinates(Vector2.Zero, MapId.Nullspace));
|
||||
_previewDummy.GetComponent<HumanoidAppearanceComponent>().UpdateFromProfile(profile);
|
||||
if (profile is HumanoidCharacterProfile humanoid)
|
||||
{
|
||||
LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy, humanoid);
|
||||
}
|
||||
|
||||
var isSelectedCharacter = profile == preferencesManager.Preferences.SelectedCharacter;
|
||||
|
||||
@@ -239,7 +243,7 @@ namespace Content.Client.UserInterface
|
||||
{
|
||||
Text = "Delete",
|
||||
Visible = !isSelectedCharacter,
|
||||
SizeFlagsHorizontal = SizeFlags.ShrinkEnd
|
||||
SizeFlagsHorizontal = SizeFlags.ShrinkEnd | SizeFlags.Expand
|
||||
};
|
||||
deleteButton.OnPressed += args =>
|
||||
{
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
using Content.Client.GameObjects.Components.Mobs;
|
||||
using System.Linq;
|
||||
using Content.Client.GameObjects;
|
||||
using Content.Client.GameObjects.Components.Mobs;
|
||||
using Content.Client.Interfaces;
|
||||
using Content.Shared;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using Content.Shared.Jobs;
|
||||
using Content.Shared.Preferences;
|
||||
using Robust.Client.Interfaces.GameObjects.Components;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Interfaces.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
@@ -94,6 +101,33 @@ namespace Content.Client.UserInterface
|
||||
_summaryLabel.Text = selectedCharacter.Summary;
|
||||
var component = _previewDummy.GetComponent<HumanoidAppearanceComponent>();
|
||||
component.UpdateFromProfile(selectedCharacter);
|
||||
|
||||
GiveDummyJobClothes(_previewDummy, selectedCharacter);
|
||||
}
|
||||
}
|
||||
|
||||
public static void GiveDummyJobClothes(IEntity dummy, HumanoidCharacterProfile profile)
|
||||
{
|
||||
var protoMan = IoCManager.Resolve<IPrototypeManager>();
|
||||
var entityMan = IoCManager.Resolve<IEntityManager>();
|
||||
|
||||
var inventory = dummy.GetComponent<ClientInventoryComponent>();
|
||||
|
||||
var highPriorityJob = profile.JobPriorities.SingleOrDefault(p => p.Value == JobPriority.High).Key;
|
||||
|
||||
var job = protoMan.Index<JobPrototype>(highPriorityJob ?? SharedGameTicker.OverflowJob);
|
||||
var gear = protoMan.Index<StartingGearPrototype>(job.StartingGear);
|
||||
|
||||
inventory.ClearAllSlotVisuals();
|
||||
|
||||
foreach (var (slot, itemType) in gear.Equipment)
|
||||
{
|
||||
var item = entityMan
|
||||
.SpawnEntityAt(itemType, new MapCoordinates(Vector2.Zero, MapId.Nullspace));
|
||||
|
||||
inventory.SetSlotVisuals(slot, item);
|
||||
|
||||
item.Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,14 +265,8 @@ namespace Content.Server.GameTicking
|
||||
{
|
||||
var gear = _prototypeManager.Index<StartingGearPrototype>(job.StartingGear).Equipment;
|
||||
|
||||
foreach (var (slotStr, equipmentStr) in gear)
|
||||
foreach (var (slot, equipmentStr) in gear)
|
||||
{
|
||||
if (!Enum.TryParse(slotStr.ToUpper(), out EquipmentSlotDefines.Slots slot))
|
||||
{
|
||||
Logger.Error("{0} is an invalid equipment slot.", slotStr);
|
||||
continue;
|
||||
}
|
||||
|
||||
var equipmentEntity = _entityManager.SpawnEntity(equipmentStr, entity.Transform.GridPosition);
|
||||
inventory.Equip(slot, equipmentEntity.GetComponent<ClothingComponent>());
|
||||
}
|
||||
|
||||
@@ -6,13 +6,28 @@ namespace Content.Shared.GameObjects.Components.Inventory
|
||||
{
|
||||
public static class EquipmentSlotDefines
|
||||
{
|
||||
public static IReadOnlyCollection<Slots> AllSlots { get; }
|
||||
|
||||
static EquipmentSlotDefines()
|
||||
{
|
||||
var output = new Slots[(int)Slots.LAST - (int)Slots.HEAD];
|
||||
|
||||
// The index stuff is to jump over NONE.
|
||||
for (var i = 0; i < output.Length; i++)
|
||||
{
|
||||
output[i] = (Slots)(i+1);
|
||||
}
|
||||
|
||||
AllSlots = output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uniquely identifies a single slot in an inventory.
|
||||
/// </summary>
|
||||
[Serializable, NetSerializable]
|
||||
public enum Slots
|
||||
{
|
||||
NONE,
|
||||
NONE = 0,
|
||||
HEAD,
|
||||
EYES,
|
||||
EARS,
|
||||
@@ -29,7 +44,12 @@ namespace Content.Shared.GameObjects.Components.Inventory
|
||||
POCKET3,
|
||||
POCKET4,
|
||||
EXOSUITSLOT1,
|
||||
EXOSUITSLOT2
|
||||
EXOSUITSLOT2,
|
||||
|
||||
/// <summary>
|
||||
/// Not a real slot.
|
||||
/// </summary>
|
||||
LAST
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using YamlDotNet.RepresentationModel;
|
||||
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
|
||||
|
||||
namespace Content.Shared.Jobs
|
||||
{
|
||||
@@ -11,20 +13,30 @@ namespace Content.Shared.Jobs
|
||||
public class StartingGearPrototype : IPrototype, IIndexedPrototype
|
||||
{
|
||||
private string _id;
|
||||
private Dictionary<string, string> _equipment;
|
||||
private Dictionary<Slots, string> _equipment;
|
||||
|
||||
[ViewVariables]
|
||||
public string ID => _id;
|
||||
[ViewVariables] public string ID => _id;
|
||||
|
||||
[ViewVariables]
|
||||
public Dictionary<string, string> Equipment => _equipment;
|
||||
[ViewVariables] public IReadOnlyDictionary<Slots, string> Equipment => _equipment;
|
||||
|
||||
public void LoadFrom(YamlMappingNode mapping)
|
||||
{
|
||||
var serializer = YamlObjectSerializer.NewReader(mapping);
|
||||
|
||||
serializer.DataField(ref _id, "id", string.Empty);
|
||||
serializer.DataField(ref _equipment, "equipment", new Dictionary<string, string>());
|
||||
|
||||
var equipment = serializer.ReadDataField<Dictionary<string, string>>("equipment");
|
||||
|
||||
_equipment = equipment.ToDictionary(slotStr =>
|
||||
{
|
||||
var (key, _) = slotStr;
|
||||
if (!Enum.TryParse(key, true, out Slots slot))
|
||||
{
|
||||
throw new Exception($"{key} is an invalid equipment slot.");
|
||||
}
|
||||
|
||||
return slot;
|
||||
}, type => type.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
Content.Tests/Shared/EquipmentSlotDefinesTest.cs
Normal file
58
Content.Tests/Shared/EquipmentSlotDefinesTest.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Content.Shared.GameObjects.Components.Inventory;
|
||||
using NUnit.Framework;
|
||||
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
|
||||
|
||||
namespace Content.Tests.Shared
|
||||
{
|
||||
[TestFixture]
|
||||
[Parallelizable(ParallelScope.All)]
|
||||
[TestOf(typeof(EquipmentSlotDefines))]
|
||||
public class EquipmentSlotDefinesTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Test that all slots are contained in <see cref="AllSlots" />
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestAllSlotsContainsAll()
|
||||
{
|
||||
foreach (var slotObj in Enum.GetValues(typeof(Slots)))
|
||||
{
|
||||
var slot = (Slots) slotObj;
|
||||
|
||||
if (slot == Slots.NONE || slot == Slots.LAST)
|
||||
{
|
||||
// Not real slots, skip these.
|
||||
continue;
|
||||
}
|
||||
|
||||
Assert.That(AllSlots.Contains(slot));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that every slot has an entry in <see cref="SlotNames" />.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSlotNamesContainsAll()
|
||||
{
|
||||
foreach (var slot in AllSlots)
|
||||
{
|
||||
Assert.That(SlotNames, Contains.Key(slot));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test that every slot has an entry in <see cref="SlotMasks" />.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestSlotMasksContainsAll()
|
||||
{
|
||||
foreach (var slot in AllSlots)
|
||||
{
|
||||
Assert.That(SlotMasks, Contains.Key(slot));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user