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