Equip clothing to preview dummies in the lobby.

This commit is contained in:
Pieter-Jan Briers
2020-01-20 09:20:36 +01:00
parent 03bfb22559
commit 75aa9541e0
7 changed files with 166 additions and 24 deletions

View File

@@ -108,24 +108,44 @@ namespace Content.Client.GameObjects
private void _setSlot(Slots slot, IEntity entity) 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 flag = SlotMasks[slot];
var data = clothing.GetEquippedStateInfo(flag); var data = clothing.GetEquippedStateInfo(flag);
if (data == null) if (data != null)
{
_sprite.LayerSetVisible(slot, false);
}
else
{ {
var (rsi, state) = data.Value; var (rsi, state) = data.Value;
_sprite.LayerSetVisible(slot, true); _sprite.LayerSetVisible(slot, true);
_sprite.LayerSetRSI(slot, rsi); _sprite.LayerSetRSI(slot, rsi);
_sprite.LayerSetState(slot, state); _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) private void _clearSlot(Slots slot)

View File

@@ -209,6 +209,10 @@ namespace Content.Client.UserInterface
_previewDummy = entityManager.SpawnEntityAt("HumanMob_Dummy", _previewDummy = entityManager.SpawnEntityAt("HumanMob_Dummy",
new MapCoordinates(Vector2.Zero, MapId.Nullspace)); new MapCoordinates(Vector2.Zero, MapId.Nullspace));
_previewDummy.GetComponent<HumanoidAppearanceComponent>().UpdateFromProfile(profile); _previewDummy.GetComponent<HumanoidAppearanceComponent>().UpdateFromProfile(profile);
if (profile is HumanoidCharacterProfile humanoid)
{
LobbyCharacterPreviewPanel.GiveDummyJobClothes(_previewDummy, humanoid);
}
var isSelectedCharacter = profile == preferencesManager.Preferences.SelectedCharacter; var isSelectedCharacter = profile == preferencesManager.Preferences.SelectedCharacter;
@@ -239,7 +243,7 @@ namespace Content.Client.UserInterface
{ {
Text = "Delete", Text = "Delete",
Visible = !isSelectedCharacter, Visible = !isSelectedCharacter,
SizeFlagsHorizontal = SizeFlags.ShrinkEnd SizeFlagsHorizontal = SizeFlags.ShrinkEnd | SizeFlags.Expand
}; };
deleteButton.OnPressed += args => deleteButton.OnPressed += args =>
{ {

View File

@@ -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.Client.Interfaces;
using Content.Shared;
using Content.Shared.GameObjects.Components.Inventory;
using Content.Shared.Jobs;
using Content.Shared.Preferences; using Content.Shared.Preferences;
using Robust.Client.Interfaces.GameObjects.Components; using Robust.Client.Interfaces.GameObjects.Components;
using Robust.Client.UserInterface; using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.Controls;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Map; using Robust.Shared.Map;
using Robust.Shared.Maths; using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
namespace Content.Client.UserInterface namespace Content.Client.UserInterface
{ {
@@ -94,6 +101,33 @@ namespace Content.Client.UserInterface
_summaryLabel.Text = selectedCharacter.Summary; _summaryLabel.Text = selectedCharacter.Summary;
var component = _previewDummy.GetComponent<HumanoidAppearanceComponent>(); var component = _previewDummy.GetComponent<HumanoidAppearanceComponent>();
component.UpdateFromProfile(selectedCharacter); 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();
} }
} }
} }

View File

@@ -265,14 +265,8 @@ namespace Content.Server.GameTicking
{ {
var gear = _prototypeManager.Index<StartingGearPrototype>(job.StartingGear).Equipment; 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); var equipmentEntity = _entityManager.SpawnEntity(equipmentStr, entity.Transform.GridPosition);
inventory.Equip(slot, equipmentEntity.GetComponent<ClothingComponent>()); inventory.Equip(slot, equipmentEntity.GetComponent<ClothingComponent>());
} }

View File

@@ -6,13 +6,28 @@ namespace Content.Shared.GameObjects.Components.Inventory
{ {
public static class EquipmentSlotDefines 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> /// <summary>
/// Uniquely identifies a single slot in an inventory. /// Uniquely identifies a single slot in an inventory.
/// </summary> /// </summary>
[Serializable, NetSerializable] [Serializable, NetSerializable]
public enum Slots public enum Slots
{ {
NONE, NONE = 0,
HEAD, HEAD,
EYES, EYES,
EARS, EARS,
@@ -29,7 +44,12 @@ namespace Content.Shared.GameObjects.Components.Inventory
POCKET3, POCKET3,
POCKET4, POCKET4,
EXOSUITSLOT1, EXOSUITSLOT1,
EXOSUITSLOT2 EXOSUITSLOT2,
/// <summary>
/// Not a real slot.
/// </summary>
LAST
} }
/// <summary> /// <summary>

View File

@@ -1,9 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using YamlDotNet.RepresentationModel; using YamlDotNet.RepresentationModel;
using static Content.Shared.GameObjects.Components.Inventory.EquipmentSlotDefines;
namespace Content.Shared.Jobs namespace Content.Shared.Jobs
{ {
@@ -11,20 +13,30 @@ namespace Content.Shared.Jobs
public class StartingGearPrototype : IPrototype, IIndexedPrototype public class StartingGearPrototype : IPrototype, IIndexedPrototype
{ {
private string _id; private string _id;
private Dictionary<string, string> _equipment; private Dictionary<Slots, string> _equipment;
[ViewVariables] [ViewVariables] public string ID => _id;
public string ID => _id;
[ViewVariables] [ViewVariables] public IReadOnlyDictionary<Slots, string> Equipment => _equipment;
public Dictionary<string, string> Equipment => _equipment;
public void LoadFrom(YamlMappingNode mapping) public void LoadFrom(YamlMappingNode mapping)
{ {
var serializer = YamlObjectSerializer.NewReader(mapping); var serializer = YamlObjectSerializer.NewReader(mapping);
serializer.DataField(ref _id, "id", string.Empty); 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);
} }
} }
} }

View 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));
}
}
}
}