using System.Linq; using Content.Shared.Hands.Components; using Content.Shared.Hands.EntitySystems; using Content.Shared.Inventory; using Content.Shared.Preferences.Loadouts; using Content.Shared.Roles; using Content.Shared.Storage; using Content.Shared.Storage.EntitySystems; using Robust.Shared.Collections; using Robust.Shared.Prototypes; namespace Content.Shared.Station; public abstract class SharedStationSpawningSystem : EntitySystem { [Dependency] protected readonly IPrototypeManager PrototypeManager = default!; [Dependency] protected readonly InventorySystem InventorySystem = default!; [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly SharedStorageSystem _storage = default!; [Dependency] private readonly SharedTransformSystem _xformSystem = default!; private EntityQuery _handsQuery; private EntityQuery _inventoryQuery; private EntityQuery _storageQuery; private EntityQuery _xformQuery; public override void Initialize() { base.Initialize(); _handsQuery = GetEntityQuery(); _inventoryQuery = GetEntityQuery(); _storageQuery = GetEntityQuery(); _xformQuery = GetEntityQuery(); } /// /// Equips the given starting gears from a `RoleLoadout` onto an entity. /// public void EquipRoleLoadout(EntityUid entity, RoleLoadout loadout, RoleLoadoutPrototype roleProto) { // Order loadout selections by the order they appear on the prototype. foreach (var group in loadout.SelectedLoadouts.OrderBy(x => roleProto.Groups.FindIndex(e => e == x.Key))) { foreach (var items in group.Value) { if (!PrototypeManager.TryIndex(items.Prototype, out var loadoutProto)) { Log.Error($"Unable to find loadout prototype for {items.Prototype}"); continue; } if (!PrototypeManager.TryIndex(loadoutProto.Equipment, out var startingGear)) { Log.Error($"Unable to find starting gear {loadoutProto.Equipment} for loadout {loadoutProto}"); continue; } // Handle any extra data here. EquipStartingGear(entity, startingGear, raiseEvent: false); } } } /// /// /// public void EquipStartingGear(EntityUid entity, ProtoId? startingGear, bool raiseEvent = true) { PrototypeManager.TryIndex(startingGear, out var gearProto); EquipStartingGear(entity, gearProto); } /// /// Equips starting gear onto the given entity. /// /// Entity to load out. /// Starting gear to use. /// Should we raise the event for equipped. Set to false if you will call this manually public void EquipStartingGear(EntityUid entity, StartingGearPrototype? startingGear, bool raiseEvent = true) { if (startingGear == null) return; var xform = _xformQuery.GetComponent(entity); if (InventorySystem.TryGetSlots(entity, out var slotDefinitions)) { foreach (var slot in slotDefinitions) { var equipmentStr = startingGear.GetGear(slot.Name); if (!string.IsNullOrEmpty(equipmentStr)) { var equipmentEntity = EntityManager.SpawnEntity(equipmentStr, xform.Coordinates); InventorySystem.TryEquip(entity, equipmentEntity, slot.Name, silent: true, force:true); } } } if (_handsQuery.TryComp(entity, out var handsComponent)) { var inhand = startingGear.Inhand; var coords = xform.Coordinates; foreach (var prototype in inhand) { var inhandEntity = EntityManager.SpawnEntity(prototype, coords); if (_handsSystem.TryGetEmptyHand(entity, out var emptyHand, handsComponent)) { _handsSystem.TryPickup(entity, inhandEntity, emptyHand, checkActionBlocker: false, handsComp: handsComponent); } } } if (startingGear.Storage.Count > 0) { var coords = _xformSystem.GetMapCoordinates(entity); var ents = new ValueList(); _inventoryQuery.TryComp(entity, out var inventoryComp); foreach (var (slot, entProtos) in startingGear.Storage) { if (entProtos.Count == 0) continue; foreach (var ent in entProtos) { ents.Add(Spawn(ent, coords)); } if (inventoryComp != null && InventorySystem.TryGetSlotEntity(entity, slot, out var slotEnt, inventoryComponent: inventoryComp) && _storageQuery.TryComp(slotEnt, out var storage)) { foreach (var ent in ents) { _storage.Insert(slotEnt.Value, ent, out _, storageComp: storage, playSound: false); } } } } if (raiseEvent) { var ev = new StartingGearEquippedEvent(entity); RaiseLocalEvent(entity, ref ev, true); } } }