public override void Tick() { base.Tick(); if (Local.Pawn is not Player player) { return; } // Due to S&Box RPC ent syncing bugs, we have to run some checks and fixes List <InventorySlot> inventorySlots = new(); foreach (Panel panel in Children) { if (panel is InventorySlot inventorySlot) { inventorySlots.Add(inventorySlot); } } bool invalidList = player.CurrentPlayer.Inventory.List.Count != inventorySlots.Count; if (!invalidList) { foreach (Entity entity in player.CurrentPlayer.Inventory.List) { if (entity is not ICarriableItem carriableItem) { continue; } string entName = carriableItem.Info.LibraryName; bool found = false; foreach (InventorySlot inventorySlot in inventorySlots) { if (inventorySlot.Carriable.Info.LibraryName.Equals(entName)) { found = true; break; } } if (!found) { invalidList = true; break; } } } if (invalidList) { OnCarriableItemClear(); foreach (Entity entity in player.CurrentPlayer.Inventory.List) { if (entity is ICarriableItem) { OnCarriableItemPickup(entity); } } } ICarriableItem activeItem = player.CurrentPlayer.ActiveChild as ICarriableItem; bool invalidSlot = false; foreach (Panel child in Children) { if (child is InventorySlot slot) { if (slot.Carriable == null) { invalidSlot = true; break; } slot.SetClass("rounded-top", child == Children.First()); slot.SetClass("rounded-bottom", child == Children.Last()); slot.SlotLabel.SetClass("rounded-top-left", child == Children.First()); slot.SlotLabel.SetClass("rounded-bottom-left", child == Children.Last()); slot.SetClass("active", slot.Carriable.Info.LibraryName == activeItem?.Info.LibraryName); slot.SetClass("opacity-heavy", slot.Carriable.Info.LibraryName == activeItem?.Info.LibraryName); if (slot.Carriable is Weapon weapon && weapon.CarriableInfo.Category != CarriableCategories.Melee) { slot.UpdateAmmo(FormatAmmo(weapon, player.CurrentPlayer.Inventory)); } } } if (invalidSlot) { OnSpectatingChange(player); } }
protected void ProcessClientInventorySelectionInput(InputBuilder input) { if (Local.Pawn is not Player player || player.IsSpectatingPlayer) { return; } if (Children == null || !Children.Any()) { return; } List <Panel> childrenList = Children.ToList(); ICarriableItem activeCarriable = player.ActiveChild as ICarriableItem; int keyboardIndexPressed = GetKeyboardNumberPressed(input); if (keyboardIndexPressed != -1) { List <ICarriableItem> weaponsOfSlotTypeSelected = new(); int activeCarriableOfSlotTypeIndex = -1; for (int i = 0; i < childrenList.Count; ++i) { if (childrenList[i] is InventorySlot slot) { if (Inventory.GetSlotByCategory(slot.Carriable.CarriableInfo.Category) == keyboardIndexPressed) { // Using the keyboard index the user pressed, find all carriables that // have the same slot type as the index. // Ex. "3" pressed, find all carriables with slot type "3". weaponsOfSlotTypeSelected.Add(slot.Carriable); if (slot.Carriable.Info.LibraryName == activeCarriable?.Info.LibraryName) { // If the current active carriable has the same slot type as // the keyboard index the user pressed activeCarriableOfSlotTypeIndex = weaponsOfSlotTypeSelected.Count - 1; } } } } if (activeCarriable == null || activeCarriableOfSlotTypeIndex == -1) { // The user isn't holding an active carriable, or is holding a weapon that has a different // hold type than the one selected using the keyboard. We can just select the first weapon. input.ActiveChild = weaponsOfSlotTypeSelected.FirstOrDefault() as Entity; } else { // The user is holding a weapon that has the same hold type as the keyboard index the user pressed. // Find the next possible weapon within the hold types. input.ActiveChild = weaponsOfSlotTypeSelected[GetNextWeaponIndex(activeCarriableOfSlotTypeIndex, weaponsOfSlotTypeSelected.Count)] as Entity; } } int mouseWheelIndex = input.MouseWheel; if (mouseWheelIndex != 0) { int activeCarriableIndex = childrenList.FindIndex((p) => p is InventorySlot slot && slot.Carriable.Info.LibraryName == activeCarriable?.Info.LibraryName); int newSelectedIndex = NormalizeSlotIndex(-mouseWheelIndex + activeCarriableIndex, childrenList.Count - 1); input.ActiveChild = (childrenList[newSelectedIndex] as InventorySlot)?.Carriable as Entity; } }