using Content.Server.Hands.Systems; using Content.Server.Preferences.Managers; using Content.Server.Storage.EntitySystems; using Content.Shared.Access.Components; using Content.Shared.Clothing; using Content.Shared.Hands.Components; using Content.Shared.Humanoid; using Content.Shared.Interaction.Components; using Content.Shared.Inventory; using Content.Shared.PDA; using Content.Shared.Preferences; using Content.Shared.Preferences.Loadouts; using Content.Shared.Roles; using Content.Shared.Station; using Content.Shared.Containers.ItemSlots; using Content.Shared.Station.Systems; using Content.Shared.Storage; using Robust.Shared.Player; namespace Content.Server.Clothing.Systems; public sealed partial class OutfitSystem : EntitySystem { [Dependency] private IServerPreferencesManager _preferenceManager = default!; [Dependency] private HandsSystem _handSystem = default!; [Dependency] private InventorySystem _invSystem = default!; [Dependency] private StationSpawningSystem _spawningSystem = default!; [Dependency] private ItemSlotsSystem _itemSlotsSystem = default!; [Dependency] private StorageSystem _storageSystem = default!; public bool SetOutfit(EntityUid target, string gear, Action? onEquipped = null, bool unremovable = false) { if (!TryComp(target, out InventoryComponent? inventoryComponent)) return false; if (!ProtoMan.TryIndex(gear, out var startingGear)) return false; HumanoidCharacterProfile? profile = null; ICommonSession? session = null; // Check if we are setting the outfit of a player to respect the preferences if (TryComp(target, out ActorComponent? actorComponent)) { session = actorComponent.PlayerSession; var userId = actorComponent.PlayerSession.UserId; var prefs = _preferenceManager.GetPreferences(userId); profile = prefs.SelectedCharacter; } if (_invSystem.TryGetSlots(target, out var slots)) { foreach (var slot in slots) { _invSystem.TryUnequip(target, slot.Name, true, true, false, inventoryComponent); var gearStr = ((IEquipmentLoadout) startingGear).GetGear(slot.Name); if (gearStr == string.Empty) continue; var equipmentEntity = Spawn(gearStr, Comp(target).Coordinates); if (slot.Name == "id" && TryComp(equipmentEntity, out PdaComponent? pdaComponent) && TryComp(pdaComponent.ContainedId, out var id)) { id.FullName = Comp(target).EntityName; } _invSystem.TryEquip(target, equipmentEntity, slot.Name, silent: true, force: true, inventory: inventoryComponent); if (unremovable) EnsureComp(equipmentEntity); onEquipped?.Invoke(target, equipmentEntity); } } var coords = Transform(target).Coordinates; foreach (var (slotName, storageContainers) in startingGear.Storage) { if (storageContainers.Count == 0) continue; if (!_invSystem.TryGetSlotEntity(target, slotName, out var slotEnt)) continue; if (TryComp(slotEnt, out var storage)) { foreach (var entProto in storageContainers) { var spawnedEntity = SpawnAtPosition(entProto, coords); _storageSystem.Insert(slotEnt.Value, spawnedEntity, out _, user: null, storageComp: storage, playSound: false); } } else if (TryComp(slotEnt, out var itemSlots)) { foreach (var entProto in storageContainers) { var spawnedEntity = SpawnAtPosition(entProto, coords); _itemSlotsSystem.TryInsertEmpty((slotEnt.Value, itemSlots), spawnedEntity, null, excludeUserAudio: true); } } } if (TryComp(target, out HandsComponent? handsComponent)) { foreach (var prototype in startingGear.Inhand) { var inhandEntity = Spawn(prototype, coords); _handSystem.TryPickup(target, inhandEntity, checkActionBlocker: false, handsComp: handsComponent); } } // See if this starting gear is associated with a job var jobs = ProtoMan.EnumeratePrototypes(); foreach (var job in jobs) { if (job.StartingGear != gear) continue; var jobProtoId = LoadoutSystem.GetJobPrototype(job.ID); if (!ProtoMan.TryIndex(jobProtoId, out var jobProto)) break; // Don't require a player, so this works on Urists profile ??= TryComp(target, out var comp) ? HumanoidCharacterProfile.DefaultWithSpecies(comp.Species, comp.Sex) : new HumanoidCharacterProfile(); // Try to get the user's existing loadout for the role profile.Loadouts.TryGetValue(jobProtoId, out var roleLoadout); if (roleLoadout == null) { // If they don't have a loadout for the role, make a default one roleLoadout = new RoleLoadout(jobProtoId); roleLoadout.SetDefault(profile, session, ProtoMan); } // Equip the target with the job loadout _spawningSystem.EquipRoleLoadout(target, roleLoadout, jobProto); } return true; } }