Exemple #1
0
        public static void UpdateDragging()
        {
            if (draggingItem != null && PlayerInput.LeftButtonReleased())
            {
                if (selectedSlot == null)
                {
                    draggingItem.ParentInventory?.CreateNetworkEvent();
                    draggingItem.Drop();
                    GUI.PlayUISound(GUISoundType.DropItem);
                }
                else if (selectedSlot.Inventory.Items[selectedSlot.SlotIndex] != draggingItem)
                {
                    Inventory selectedInventory = selectedSlot.Inventory;
                    int       slotIndex         = selectedSlot.SlotIndex;
                    if (selectedInventory.TryPutItem(draggingItem, slotIndex, true, true, Character.Controlled))
                    {
                        if (selectedInventory.slots != null)
                        {
                            selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
                        }
                        GUI.PlayUISound(GUISoundType.PickItem);
                    }
                    else
                    {
                        if (selectedInventory.slots != null)
                        {
                            selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.Red, 0.1f, 0.9f);
                        }
                        GUI.PlayUISound(GUISoundType.PickItemFail);
                    }
                    draggingItem = null;
                    draggingSlot = null;
                }

                draggingItem = null;
            }

            if (selectedSlot != null && !selectedSlot.Slot.InteractRect.Contains(PlayerInput.MousePosition))
            {
                selectedSlot = null;
            }
        }
        private void ContainUncontain(bool drop)
        {
            // flip the behavior if the item was dropped instead of inserted
            if (wasDropped)
            {
                drop = !drop;
            }

            foreach (var(slot, receiver) in Receivers)
            {
                Item item = (Item)receiver.GetReplacementOrThis();

                if (drop)
                {
                    item.Drop(null, createNetworkEvent: false);
                }
                else
                {
                    Inventory.GetReplacementOrThiS().TryPutItem(item, slot, false, false, null, createNetworkEvent: false);
                }
            }
        }
Exemple #3
0
        protected virtual void PutItem(Item item, int i, Character user, bool removeItem = true, bool createNetworkEvent = true)
        {
            if (Owner == null)
            {
                return;
            }

            if (removeItem)
            {
                item.Drop(user);
                if (item.ParentInventory != null)
                {
                    item.ParentInventory.RemoveItem(item);
                }
            }

            Items[i]             = item;
            item.ParentInventory = this;

#if CLIENT
            if (slots != null)
            {
                slots[i].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
            }
#endif

            if (item.body != null)
            {
                item.body.Enabled = false;
            }

            if (createNetworkEvent)
            {
                CreateNetworkEvent();
            }
        }
Exemple #4
0
        protected virtual void PutItem(Item item, int i, Character user, bool removeItem = true, bool createNetworkEvent = true)
        {
            if (i < 0 || i >= slots.Length)
            {
                string errorMsg = "Inventory.PutItem failed: index was out of range(" + i + ").\n" + Environment.StackTrace.CleanupStackTrace();
                GameAnalyticsManager.AddErrorEventOnce("Inventory.PutItem:IndexOutOfRange", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
                return;
            }

            if (Owner == null)
            {
                return;
            }

            Inventory prevInventory      = item.ParentInventory;
            Inventory prevOwnerInventory = item.FindParentInventory(inv => inv is CharacterInventory);

            if (createNetworkEvent)
            {
                CreateNetworkEvent();
                //also delay syncing the inventory the item was inside
                if (prevInventory != null && prevInventory != this)
                {
                    prevInventory.syncItemsDelay = 1.0f;
                }
            }

            if (removeItem)
            {
                item.Drop(user);
                if (item.ParentInventory != null)
                {
                    item.ParentInventory.RemoveItem(item);
                }
            }

            slots[i].Add(item);
            item.ParentInventory = this;

#if CLIENT
            if (visualSlots != null)
            {
                visualSlots[i]?.ShowBorderHighlight(Color.White, 0.1f, 0.4f);
            }
#endif

            if (item.body != null)
            {
                item.body.Enabled  = false;
                item.body.BodyType = FarseerPhysics.BodyType.Dynamic;
            }

#if SERVER
            if (prevOwnerInventory is CharacterInventory characterInventory && characterInventory != this && Owner == user)
            {
                var client = GameMain.Server?.ConnectedClients?.Find(cl => cl.Character == user);
                GameMain.Server?.KarmaManager.OnItemTakenFromPlayer(characterInventory, client, item);
            }
#endif
            if (this is CharacterInventory)
            {
                if (prevInventory != this && prevOwnerInventory != this)
                {
                    HumanAIController.ItemTaken(item, user);
                }
            }
            else
            {
                if (item.FindParentInventory(inv => inv is CharacterInventory) is CharacterInventory currentInventory)
                {
                    if (currentInventory != prevInventory)
                    {
                        HumanAIController.ItemTaken(item, user);
                    }
                }
            }
        }
Exemple #5
0
        protected override void Act(float deltaTime)
        {
            if (character.LockHands || targetCharacter == null || targetCharacter.CurrentHull == null || targetCharacter.Removed || targetCharacter.IsDead)
            {
                Abandon = true;
                return;
            }
            var otherRescuer = targetCharacter.SelectedBy;

            if (otherRescuer != null && otherRescuer != character)
            {
                // Someone else is rescuing/holding the target.
                Abandon = otherRescuer.IsPlayer || character.GetSkillLevel("medical") < otherRescuer.GetSkillLevel("medical");
                return;
            }
            if (targetCharacter != character)
            {
                if (targetCharacter.IsIncapacitated)
                {
                    // Check if the character needs more oxygen
                    if (!ignoreOxygen && character.SelectedCharacter == targetCharacter || character.CanInteractWith(targetCharacter))
                    {
                        // Replace empty oxygen and welding fuel.
                        if (HumanAIController.HasItem(targetCharacter, AIObjectiveFindDivingGear.HEAVY_DIVING_GEAR, out IEnumerable <Item> suits, requireEquipped: true))
                        {
                            Item suit = suits.FirstOrDefault();
                            if (suit != null)
                            {
                                AIController.UnequipEmptyItems(character, suit);
                                AIController.UnequipContainedItems(character, suit, it => it.HasTag("weldingfuel"));
                            }
                        }
                        else if (HumanAIController.HasItem(targetCharacter, AIObjectiveFindDivingGear.LIGHT_DIVING_GEAR, out IEnumerable <Item> masks, requireEquipped: true))
                        {
                            Item mask = masks.FirstOrDefault();
                            if (mask != null)
                            {
                                AIController.UnequipEmptyItems(character, mask);
                                AIController.UnequipContainedItems(character, mask, it => it.HasTag("weldingfuel"));
                            }
                        }
                        bool ShouldRemoveDivingSuit() => targetCharacter.OxygenAvailable < CharacterHealth.InsufficientOxygenThreshold && targetCharacter.CurrentHull?.LethalPressure <= 0;

                        if (ShouldRemoveDivingSuit())
                        {
                            suits.ForEach(suit => suit.Drop(character));
                        }
                        else if (suits.Any() && suits.None(s => s.OwnInventory?.AllItems != null && s.OwnInventory.AllItems.Any(it => it.HasTag(AIObjectiveFindDivingGear.OXYGEN_SOURCE) && it.ConditionPercentage > 0)))
                        {
                            // The target has a suit equipped with an empty oxygen tank.
                            // Can't remove the suit, because the target needs it.
                            // If we happen to have an extra oxygen tank in the inventory, let's swap it.
                            Item spareOxygenTank = FindOxygenTank(targetCharacter) ?? FindOxygenTank(character);
                            if (spareOxygenTank != null)
                            {
                                Item suit = suits.FirstOrDefault();
                                if (suit != null)
                                {
                                    // Insert the new oxygen tank
                                    TryAddSubObjective(ref replaceOxygenObjective, () => new AIObjectiveContainItem(character, spareOxygenTank, suit.GetComponent <ItemContainer>(), objectiveManager),
                                                       onCompleted: () => RemoveSubObjective(ref replaceOxygenObjective),
                                                       onAbandon: () =>
                                    {
                                        RemoveSubObjective(ref replaceOxygenObjective);
                                        ignoreOxygen = true;
                                        if (ShouldRemoveDivingSuit())
                                        {
                                            suits.ForEach(suit => suit.Drop(character));
                                        }
                                    });
                                    return;
                                }
                            }

                            Item FindOxygenTank(Character c) =>
                            c.Inventory.FindItem(i =>
                                                 i.HasTag(AIObjectiveFindDivingGear.OXYGEN_SOURCE) &&
                                                 i.ConditionPercentage > 1 &&
                                                 i.FindParentInventory(inv => inv.Owner is Item otherItem && otherItem.HasTag("diving")) == null,
                                                 recursive: true);
                        }
                    }
                    if (HumanAIController.GetHullSafety(targetCharacter.CurrentHull, targetCharacter) < HumanAIController.HULL_SAFETY_THRESHOLD)
                    {
                        // Incapacitated target is not in a safe place -> Move to a safe place first
                        if (character.SelectedCharacter != targetCharacter)
                        {
                            if (targetCharacter.CurrentHull != null && HumanAIController.VisibleHulls.Contains(targetCharacter.CurrentHull) && targetCharacter.CurrentHull.DisplayName != null)
                            {
                                character.Speak(TextManager.GetWithVariables("DialogFoundUnconsciousTarget", new string[2] {
                                    "[targetname]", "[roomname]"
                                },
                                                                             new string[2] {
                                    targetCharacter.Name, targetCharacter.CurrentHull.DisplayName
                                }, new bool[2] {
                                    false, true
                                }),
                                                null, 1.0f, "foundunconscioustarget" + targetCharacter.Name, 60.0f);
                            }
                            // Go to the target and select it
                            if (!character.CanInteractWith(targetCharacter))
                            {
                                RemoveSubObjective(ref replaceOxygenObjective);
                                RemoveSubObjective(ref goToObjective);
                                TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(targetCharacter, character, objectiveManager)
                                {
                                    CloseEnough        = CloseEnoughToTreat,
                                    DialogueIdentifier = "dialogcannotreachpatient",
                                    TargetName         = targetCharacter.DisplayName
                                },
                                                   onCompleted: () => RemoveSubObjective(ref goToObjective),
                                                   onAbandon: () =>
                                {
                                    RemoveSubObjective(ref goToObjective);
                                    Abandon = true;
                                });
                            }
                            else
                            {
                                character.SelectCharacter(targetCharacter);
                            }
                        }
                        else
                        {
                            // Drag the character into safety
                            if (safeHull == null)
                            {
                                if (findHullTimer > 0)
                                {
                                    findHullTimer -= deltaTime;
                                }
                                else
                                {
                                    safeHull      = objectiveManager.GetObjective <AIObjectiveFindSafety>().FindBestHull(HumanAIController.VisibleHulls);
                                    findHullTimer = findHullInterval * Rand.Range(0.9f, 1.1f);
                                }
                            }
                            if (safeHull != null && character.CurrentHull != safeHull)
                            {
                                RemoveSubObjective(ref replaceOxygenObjective);
                                RemoveSubObjective(ref goToObjective);
                                TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(safeHull, character, objectiveManager),
                                                   onCompleted: () => RemoveSubObjective(ref goToObjective),
                                                   onAbandon: () =>
                                {
                                    RemoveSubObjective(ref goToObjective);
                                    safeHull = character.CurrentHull;
                                });
                            }
                        }
                    }
                }
            }

            if (subObjectives.Any())
            {
                return;
            }

            if (targetCharacter != character && !character.CanInteractWith(targetCharacter))
            {
                RemoveSubObjective(ref replaceOxygenObjective);
                RemoveSubObjective(ref goToObjective);
                // Go to the target and select it
                TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(targetCharacter, character, objectiveManager)
                {
                    CloseEnough        = CloseEnoughToTreat,
                    DialogueIdentifier = "dialogcannotreachpatient",
                    TargetName         = targetCharacter.DisplayName
                },
                                   onCompleted: () => RemoveSubObjective(ref goToObjective),
                                   onAbandon: () =>
                {
                    RemoveSubObjective(ref goToObjective);
                    Abandon = true;
                });
            }
            else
            {
                // We can start applying treatment
                if (character != targetCharacter && character.SelectedCharacter != targetCharacter)
                {
                    if (targetCharacter.CurrentHull.DisplayName != null)
                    {
                        character.Speak(TextManager.GetWithVariables("DialogFoundWoundedTarget", new string[2] {
                            "[targetname]", "[roomname]"
                        },
                                                                     new string[2] {
                            targetCharacter.Name, targetCharacter.CurrentHull.DisplayName
                        }, new bool[2] {
                            false, true
                        }),
                                        null, 1.0f, "foundwoundedtarget" + targetCharacter.Name, 60.0f);
                    }
                }
                GiveTreatment(deltaTime);
            }
        }
Exemple #6
0
        public static void UpdateDragging()
        {
            if (draggingItem != null && PlayerInput.LeftButtonReleased())
            {
                if (CharacterHealth.OpenHealthWindow != null &&
                    CharacterHealth.OpenHealthWindow.OnItemDropped(draggingItem, false))
                {
                    draggingItem = null;
                    return;
                }

                if (selectedSlot == null)
                {
                    draggingItem.ParentInventory?.CreateNetworkEvent();
                    draggingItem.Drop();
                    GUI.PlayUISound(GUISoundType.DropItem);
                }
                else if (selectedSlot.ParentInventory.Items[selectedSlot.SlotIndex] != draggingItem)
                {
                    Inventory selectedInventory = selectedSlot.ParentInventory;
                    int       slotIndex         = selectedSlot.SlotIndex;
                    if (selectedInventory.TryPutItem(draggingItem, slotIndex, true, true, Character.Controlled))
                    {
                        if (selectedInventory.slots != null)
                        {
                            selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.White, 0.1f, 0.4f);
                        }
                        GUI.PlayUISound(GUISoundType.PickItem);
                    }
                    else
                    {
                        if (selectedInventory.slots != null)
                        {
                            selectedInventory.slots[slotIndex].ShowBorderHighlight(Color.Red, 0.1f, 0.9f);
                        }
                        GUI.PlayUISound(GUISoundType.PickItemFail);
                    }
                    selectedInventory.HideTimer = 1.0f;
                    if (selectedSlot.ParentInventory?.Owner is Item parentItem && parentItem.ParentInventory != null)
                    {
                        for (int i = 0; i < parentItem.ParentInventory.capacity; i++)
                        {
                            if (parentItem.ParentInventory.HideSlot(i))
                            {
                                continue;
                            }
                            if (parentItem.ParentInventory.Items[i] != parentItem)
                            {
                                continue;
                            }

                            highlightedSubInventorySlots.Add(new SlotReference(
                                                                 parentItem.ParentInventory, parentItem.ParentInventory.slots[i],
                                                                 i, false, selectedSlot.ParentInventory));
                            break;
                        }
                    }
                    draggingItem = null;
                    draggingSlot = null;
                }

                draggingItem = null;
            }

            if (selectedSlot != null && !selectedSlot.Slot.MouseOn())
            {
                selectedSlot = null;
            }
        }
        /// <summary>
        /// Reloads the ammunition found in the inventory.
        /// If seekAmmo is true, tries to get find the ammo elsewhere.
        /// </summary>
        private bool Reload(bool seekAmmo)
        {
            if (WeaponComponent == null)
            {
                return(false);
            }
            if (!WeaponComponent.requiredItems.ContainsKey(RelatedItem.RelationType.Contained))
            {
                return(false);
            }
            var containedItems = Weapon.ContainedItems;

            // Drop empty ammo
            foreach (Item containedItem in containedItems)
            {
                if (containedItem == null)
                {
                    continue;
                }
                if (containedItem.Condition <= 0)
                {
                    containedItem.Drop(character);
                }
            }
            RelatedItem item       = null;
            Item        ammunition = null;

            string[] ammunitionIdentifiers = null;
            foreach (RelatedItem requiredItem in WeaponComponent.requiredItems[RelatedItem.RelationType.Contained])
            {
                ammunition = containedItems.FirstOrDefault(it => it.Condition > 0 && requiredItem.MatchesItem(it));
                if (ammunition != null)
                {
                    // Ammunition still remaining
                    return(true);
                }
                item = requiredItem;
                ammunitionIdentifiers = requiredItem.Identifiers;
            }
            // No ammo
            if (ammunition == null)
            {
                if (ammunitionIdentifiers != null)
                {
                    // Try reload ammunition from inventory
                    ammunition = character.Inventory.FindItem(i => ammunitionIdentifiers.Any(id => id == i.Prefab.Identifier || i.HasTag(id)) && i.Condition > 0, true);
                    if (ammunition != null)
                    {
                        var container = Weapon.GetComponent <ItemContainer>();
                        if (container.Item.ParentInventory == character.Inventory)
                        {
                            if (!container.Inventory.CanBePut(ammunition))
                            {
                                return(false);
                            }
                            character.Inventory.RemoveItem(ammunition);
                            if (!container.Inventory.TryPutItem(ammunition, null))
                            {
                                ammunition.Drop(character);
                            }
                        }
                        else
                        {
                            container.Combine(ammunition, character);
                        }
                    }
                }
            }
            if (WeaponComponent.HasRequiredContainedItems(character, addMessage: false))
            {
                return(true);
            }
            else if (ammunition == null && !HoldPosition && initialMode == CombatMode.Offensive && seekAmmo && ammunitionIdentifiers != null)
            {
                SeekAmmunition(ammunitionIdentifiers);
            }
            return(false);
        }
Exemple #8
0
        public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
        {
            List <Item> prevItems = new List <Item>(Items);

            byte itemCount = msg.ReadByte();

            ushort[] newItemIDs = new ushort[itemCount];
            for (int i = 0; i < itemCount; i++)
            {
                newItemIDs[i] = msg.ReadUInt16();
            }

            if (c == null || c.Character == null)
            {
                return;
            }

            bool accessible = c.Character.CanAccessInventory(this);

            if (this is CharacterInventory && accessible)
            {
                if (Owner == null || !(Owner is Character))
                {
                    accessible = false;
                }
                else if (!((CharacterInventory)this).AccessibleWhenAlive && !((Character)Owner).IsDead)
                {
                    accessible = false;
                }
            }

            if (!accessible)
            {
                //create a network event to correct the client's inventory state
                //otherwise they may have an item in their inventory they shouldn't have been able to pick up,
                //and receiving an event for that inventory later will cause the item to be dropped
                CreateNetworkEvent();
                for (int i = 0; i < capacity; i++)
                {
                    if (!(Entity.FindEntityByID(newItemIDs[i]) is Item item))
                    {
                        continue;
                    }
                    item.PositionUpdateInterval = 0.0f;
                    if (item.ParentInventory != null && item.ParentInventory != this)
                    {
                        item.ParentInventory.CreateNetworkEvent();
                    }
                }
                return;
            }

            List <Inventory> prevItemInventories = new List <Inventory>(Items.Select(i => i?.ParentInventory));

            for (int i = 0; i < capacity; i++)
            {
                Item newItem = newItemIDs[i] == 0 ? null : Entity.FindEntityByID(newItemIDs[i]) as Item;
                prevItemInventories.Add(newItem?.ParentInventory);

                if (newItemIDs[i] == 0 || (newItem != Items[i]))
                {
                    if (Items[i] != null)
                    {
                        Item   droppedItem = Items[i];
                        Entity prevOwner   = Owner;
                        droppedItem.Drop(null);

                        var previousInventory = prevOwner switch
                        {
                            Item itemInventory => (itemInventory.FindParentInventory(inventory => inventory is CharacterInventory) as CharacterInventory),
                            Character character => character.Inventory,
                            _ => null
                        };

                        if (previousInventory != null && previousInventory != c.Character?.Inventory)
                        {
                            GameMain.Server?.KarmaManager.OnItemTakenFromPlayer(previousInventory, c, droppedItem);
                        }

                        if (droppedItem.body != null && prevOwner != null)
                        {
                            droppedItem.body.SetTransform(prevOwner.SimPosition, 0.0f);
                        }
                    }
                    System.Diagnostics.Debug.Assert(Items[i] == null);
                }
            }

            for (int i = 0; i < capacity; i++)
            {
                if (newItemIDs[i] > 0)
                {
                    if (!(Entity.FindEntityByID(newItemIDs[i]) is Item item) || item == Items[i])
                    {
                        continue;
                    }

                    if (GameMain.Server != null)
                    {
                        var holdable = item.GetComponent <Holdable>();
                        if (holdable != null && !holdable.CanBeDeattached())
                        {
                            continue;
                        }

                        if (!prevItems.Contains(item) && !item.CanClientAccess(c))
                        {
#if DEBUG || UNSTABLE
                            DebugConsole.NewMessage($"Client {c.Name} failed to pick up item \"{item}\" (parent inventory: {(item.ParentInventory?.Owner.ToString() ?? "null")}). No access.", Color.Yellow);
#endif
                            if (item.body != null && !c.PendingPositionUpdates.Contains(item))
                            {
                                c.PendingPositionUpdates.Enqueue(item);
                            }
                            item.PositionUpdateInterval = 0.0f;
                            continue;
                        }
                    }
                    TryPutItem(item, i, true, true, c.Character, false);
                    for (int j = 0; j < capacity; j++)
                    {
                        if (Items[j] == item && newItemIDs[j] != item.ID)
                        {
                            Items[j] = null;
                        }
                    }
                }
            }

            CreateNetworkEvent();
            foreach (Inventory prevInventory in prevItemInventories.Distinct())
            {
                if (prevInventory != this)
                {
                    prevInventory?.CreateNetworkEvent();
                }
            }

            foreach (Item item in Items.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!prevItems.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " picked up " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " placed " + item.Name + " in " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
            foreach (Item item in prevItems.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!Items.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " dropped " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(GameServer.CharacterLogName(c.Character) + " removed " + item.Name + " from " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
        }
        protected override void Act(float deltaTime)
        {
            if (character.LockHands)
            {
                Abandon = true;
                return;
            }
            if (targetItem == null)
            {
                FindTargetItem();
                if (targetItem == null || moveToTarget == null)
                {
                    if (targetItem != null && moveToTarget == null)
                    {
#if DEBUG
                        DebugConsole.ThrowError($"{character.Name}: Move to target is null!");
#endif
                        Abandon = true;
                    }
                    objectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime);
                    return;
                }
            }
            if (character.IsItemTakenBySomeoneElse(targetItem))
            {
#if DEBUG
                DebugConsole.NewMessage($"{character.Name}: Found an item, but it's already equipped by someone else. Aborting.", Color.Yellow);
#endif
                Abandon = true;
            }
            if (character.CanInteractWith(targetItem, out _, checkLinked: false))
            {
                var pickable = targetItem.GetComponent <Pickable>();
                if (pickable == null)
                {
#if DEBUG
                    DebugConsole.NewMessage($"{character.Name}: Target not pickable. Aborting.", Color.Yellow);
#endif
                    Abandon = true;
                    return;
                }
                targetItem.TryInteract(character, forceSelectKey: true);
                if (equip)
                {
                    int targetSlot = -1;
                    //check if all the slots required by the item are free
                    foreach (InvSlotType slots in pickable.AllowedSlots)
                    {
                        if (slots.HasFlag(InvSlotType.Any))
                        {
                            continue;
                        }
                        for (int i = 0; i < character.Inventory.Items.Length; i++)
                        {
                            //slot not needed by the item, continue
                            if (!slots.HasFlag(character.Inventory.SlotTypes[i]))
                            {
                                continue;
                            }
                            targetSlot = i;
                            //slot free, continue
                            var otherItem = character.Inventory.Items[i];
                            if (otherItem == null)
                            {
                                continue;
                            }
                            //try to move the existing item to LimbSlot.Any and continue if successful
                            if (character.Inventory.TryPutItem(otherItem, character, new List <InvSlotType>()
                            {
                                InvSlotType.Any
                            }))
                            {
                                continue;
                            }
                            //if everything else fails, simply drop the existing item
                            otherItem.Drop(character);
                        }
                    }
                    if (character.Inventory.TryPutItem(targetItem, targetSlot, false, false, character))
                    {
                        IsCompleted = true;
                    }
                    else
                    {
#if DEBUG
                        DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red);
#endif
                        Abandon = true;
                    }
                }
                else
                {
                    targetItem.ParentInventory.RemoveItem(targetItem);
                    if (character.Inventory.TryPutItem(targetItem, null, new List <InvSlotType>()
                    {
                        InvSlotType.Any
                    }))
                    {
                        IsCompleted = true;
                    }
                    else
                    {
                        Abandon = true;
#if DEBUG
                        DebugConsole.NewMessage($"{character.Name}: Failed to equip/move the item '{targetItem.Name}' into the character inventory. Aborting.", Color.Red);
#endif
                        targetItem.Drop(character);
                    }
                }
            }
            else
            {
                TryAddSubObjective(ref goToObjective,
                                   constructor: () =>
                {
                    return(new AIObjectiveGoTo(moveToTarget, character, objectiveManager, repeat: false, getDivingGearIfNeeded: AllowToFindDivingGear));
                },
                                   onAbandon: () =>
                {
                    targetItem   = null;
                    moveToTarget = null;
                    ignoredItems.Add(targetItem);
                    RemoveSubObjective(ref goToObjective);
                },
                                   onCompleted: () => RemoveSubObjective(ref goToObjective));
            }
        }
Exemple #10
0
        protected override void Act(float deltaTime)
        {
            if (container == null)
            {
                Abandon = true;
                return;
            }
            Item itemToContain = item ?? character.Inventory.FindItem(i => CheckItem(i) && i.Container != container.Item, recursive: true);

            if (itemToContain != null)
            {
                if (character.CanInteractWith(container.Item, out _, checkLinked: false))
                {
                    if (RemoveEmpty)
                    {
                        foreach (var emptyItem in container.Inventory.Items)
                        {
                            if (emptyItem == null)
                            {
                                continue;
                            }
                            if (emptyItem.Condition <= 0)
                            {
                                emptyItem.Drop(character);
                            }
                        }
                    }
                    // Contain the item
                    if (itemToContain.ParentInventory == character.Inventory)
                    {
                        if (!container.Inventory.CanBePut(itemToContain))
                        {
                            Abandon = true;
                        }
                        else
                        {
                            character.Inventory.RemoveItem(itemToContain);
                            if (container.Inventory.TryPutItem(itemToContain, null))
                            {
                                IsCompleted = true;
                            }
                            else
                            {
                                itemToContain.Drop(character);
                                Abandon = true;
                            }
                        }
                    }
                    else
                    {
                        if (container.Combine(itemToContain, character))
                        {
                            IsCompleted = true;
                        }
                        else
                        {
                            Abandon = true;
                        }
                    }
                }
                else
                {
                    TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(container.Item, character, objectiveManager, getDivingGearIfNeeded: AllowToFindDivingGear)
                    {
                        DialogueIdentifier = "dialogcannotreachtarget",
                        TargetName         = container.Item.Name
                    },
                                       onAbandon: () => Abandon = true,
                                       onCompleted: () => RemoveSubObjective(ref goToObjective));
                }
            }
            else
            {
                // No matching items in the inventory, try to get an item
                TryAddSubObjective(ref getItemObjective, () =>
                                   new AIObjectiveGetItem(character, itemIdentifiers, objectiveManager, equip: Equip, checkInventory: checkInventory)
                {
                    GetItemPriority             = GetItemPriority,
                    ignoredContainerIdentifiers = ignoredContainerIdentifiers,
                    ignoredItems          = containedItems,
                    AllowToFindDivingGear = this.AllowToFindDivingGear
                }, onAbandon: () =>
                {
                    Abandon = true;
                }, onCompleted: () =>
                {
                    if (getItemObjective.TargetItem != null)
                    {
                        containedItems.Add(getItemObjective.TargetItem);
                    }
                    else
                    {
                        if (container.Inventory.FindItem(i => CheckItem(i), recursive: false) != null)
                        {
                            IsCompleted = true;
                        }
                        else
                        {
                            Abandon = true;
                        }
                    }
                    RemoveSubObjective(ref getItemObjective);
                });
            }
        }
Exemple #11
0
        public void ServerRead(ClientNetObject type, NetBuffer msg, Client c)
        {
            List <Item> prevItems = new List <Item>(Items);

            ushort[] newItemIDs = new ushort[capacity];

            for (int i = 0; i < capacity; i++)
            {
                newItemIDs[i] = msg.ReadUInt16();
            }


            if (c == null || c.Character == null)
            {
                return;
            }

            bool accessible = c.Character.CanAccessInventory(this);

            if (this is CharacterInventory && accessible)
            {
                if (Owner == null || !(Owner is Character))
                {
                    accessible = false;
                }
                else if (!((CharacterInventory)this).AccessibleWhenAlive && !((Character)Owner).IsDead)
                {
                    accessible = false;
                }
            }

            if (!accessible)
            {
                //create a network event to correct the client's inventory state
                //otherwise they may have an item in their inventory they shouldn't have been able to pick up,
                //and receiving an event for that inventory later will cause the item to be dropped
                CreateNetworkEvent();
                for (int i = 0; i < capacity; i++)
                {
                    if (!(Entity.FindEntityByID(newItemIDs[i]) is Item item))
                    {
                        continue;
                    }
                    item.PositionUpdateInterval = 0.0f;
                    if (item.ParentInventory != null && item.ParentInventory != this)
                    {
                        item.ParentInventory.CreateNetworkEvent();
                    }
                }
                return;
            }

            List <Inventory> prevItemInventories = new List <Inventory>(Items.Select(i => i?.ParentInventory));

            for (int i = 0; i < capacity; i++)
            {
                Item newItem = newItemIDs[i] == 0 ? null : Entity.FindEntityByID(newItemIDs[i]) as Item;
                prevItemInventories.Add(newItem?.ParentInventory);

                if (newItemIDs[i] == 0 || (newItem != Items[i]))
                {
                    if (Items[i] != null)
                    {
                        Item   droppedItem = Items[i];
                        Entity prevOwner   = Owner;
                        droppedItem.Drop(null);
                        if (droppedItem.body != null && prevOwner != null)
                        {
                            droppedItem.body.SetTransform(prevOwner.SimPosition, 0.0f);
                        }
                    }
                    System.Diagnostics.Debug.Assert(Items[i] == null);
                }
            }

            for (int i = 0; i < capacity; i++)
            {
                if (newItemIDs[i] > 0)
                {
                    if (!(Entity.FindEntityByID(newItemIDs[i]) is Item item) || item == Items[i])
                    {
                        continue;
                    }

                    if (GameMain.Server != null)
                    {
                        var holdable = item.GetComponent <Holdable>();
                        if (holdable != null && !holdable.CanBeDeattached())
                        {
                            continue;
                        }

                        if (!prevItems.Contains(item) && !item.CanClientAccess(c))
                        {
                            item.PositionUpdateInterval = 0.0f;
                            continue;
                        }
                    }
                    TryPutItem(item, i, true, true, c.Character, false);
                    for (int j = 0; j < capacity; j++)
                    {
                        if (Items[j] == item && newItemIDs[j] != item.ID)
                        {
                            Items[j] = null;
                        }
                    }
                }
            }

            CreateNetworkEvent();
            foreach (Inventory prevInventory in prevItemInventories.Distinct())
            {
                if (prevInventory != this)
                {
                    prevInventory?.CreateNetworkEvent();
                }
            }

            foreach (Item item in Items.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!prevItems.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(c.Character.LogName + " picked up " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(c.Character.LogName + " placed " + item.Name + " in " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
            foreach (Item item in prevItems.Distinct())
            {
                if (item == null)
                {
                    continue;
                }
                if (!Items.Contains(item))
                {
                    if (Owner == c.Character)
                    {
                        GameServer.Log(c.Character.LogName + " dropped " + item.Name, ServerLog.MessageType.Inventory);
                    }
                    else
                    {
                        GameServer.Log(c.Character.LogName + " removed " + item.Name + " from " + Owner, ServerLog.MessageType.Inventory);
                    }
                }
            }
        }
        protected override void Act(float deltaTime)
        {
            Item itemToDecontain = targetItem ?? sourceContainer.Inventory.FindItem(i => itemIdentifiers.Any(id => i.Prefab.Identifier == id || i.HasTag(id) && !i.IgnoreByAI), recursive: false);

            if (itemToDecontain == null)
            {
                Abandon = true;
                return;
            }
            if (itemToDecontain.IgnoreByAI)
            {
                Abandon = true;
                return;
            }
            if (targetContainer == null)
            {
                if (sourceContainer == null)
                {
                    Abandon = true;
                    return;
                }
                if (itemToDecontain.Container != sourceContainer.Item)
                {
                    IsCompleted = true;
                    return;
                }
            }
            else if (targetContainer.Inventory.Contains(itemToDecontain))
            {
                IsCompleted = true;
                return;
            }
            if (getItemObjective == null && !itemToDecontain.IsOwnedBy(character))
            {
                TryAddSubObjective(ref getItemObjective,
                                   constructor: () => new AIObjectiveGetItem(character, targetItem, objectiveManager, Equip)
                {
                    TakeWholeStack = this.TakeWholeStack
                },
                                   onAbandon: () => Abandon = true);
                return;
            }
            if (targetContainer != null)
            {
                TryAddSubObjective(ref containObjective,
                                   constructor: () => new AIObjectiveContainItem(character, itemToDecontain, targetContainer, objectiveManager)
                {
                    MoveWholeStack              = TakeWholeStack,
                    Equip                       = Equip,
                    RemoveEmpty                 = false,
                    GetItemPriority             = GetItemPriority,
                    ignoredContainerIdentifiers = sourceContainer != null ? new string[] { sourceContainer.Item.Prefab.Identifier } : null
                },
                                   onCompleted: () => IsCompleted = true,
                                   onAbandon: () => Abandon       = true);
            }
            else
            {
                itemToDecontain.Drop(character);
                IsCompleted = true;
            }
        }
        protected override void Act(float deltaTime)
        {
            Item itemToDecontain = targetItem ?? sourceContainer.Inventory.FindItem(i => itemIdentifiers.Any(id => i.Prefab.Identifier == id || i.HasTag(id)), recursive: false);

            if (itemToDecontain == null)
            {
                Abandon = true;
                return;
            }
            if (targetContainer == null)
            {
                if (sourceContainer == null)
                {
                    Abandon = true;
                    return;
                }
                if (itemToDecontain.Container != sourceContainer.Item)
                {
                    IsCompleted = true;
                    return;
                }
            }
            else
            {
                if (targetContainer.Inventory.Items.Contains(itemToDecontain))
                {
                    IsCompleted = true;
                    return;
                }
            }
            if (goToObjective == null && !itemToDecontain.IsOwnedBy(character))
            {
                if (sourceContainer == null)
                {
                    Abandon = true;
                    return;
                }
                if (!character.CanInteractWith(sourceContainer.Item, out _, checkLinked: false))
                {
                    TryAddSubObjective(ref goToObjective,
                                       constructor: () => new AIObjectiveGoTo(sourceContainer.Item, character, objectiveManager)
                    {
                        // If the container changes, the item is no longer where it was
                        abortCondition     = () => itemToDecontain.Container != sourceContainer.Item,
                        DialogueIdentifier = "dialogcannotreachtarget",
                        TargetName         = sourceContainer.Item.Name
                    },
                                       onAbandon: () => Abandon = true);
                    return;
                }
            }
            if (targetContainer != null)
            {
                TryAddSubObjective(ref containObjective,
                                   constructor: () => new AIObjectiveContainItem(character, itemToDecontain, targetContainer, objectiveManager)
                {
                    Equip                       = this.Equip,
                    RemoveEmpty                 = false,
                    GetItemPriority             = this.GetItemPriority,
                    ignoredContainerIdentifiers = sourceContainer != null ? new string[] { sourceContainer.Item.Prefab.Identifier } : null
                },
                                   onCompleted: () => IsCompleted = true,
                                   onAbandon: () =>
                {
                    if (DropIfFailsToContain)
                    {
                        itemToDecontain.Drop(character);
                    }
                    Abandon = true;
                });
            }
            else
            {
                itemToDecontain.Drop(character);
                IsCompleted = true;
            }
        }