using Barotrauma.Items.Components; using Microsoft.Xna.Framework; using System.Collections.Generic; using System.Linq; namespace Barotrauma { class AIObjectiveOperateItem : AIObjective { public override string DebugTag => "operate item"; private ItemComponent component, controller; private Entity operateTarget; private bool isCompleted; private bool canBeCompleted; private bool requireEquip; private bool useController; private AIObjectiveGoTo gotoObjective; public override bool CanBeCompleted { get { if (gotoObjective != null && !gotoObjective.CanBeCompleted) return false; if (useController && controller == null) return false; return canBeCompleted; } } public Entity OperateTarget { get { return operateTarget; } } public ItemComponent Component => component; public override float GetPriority(AIObjectiveManager objectiveManager) { if (gotoObjective != null && !gotoObjective.CanBeCompleted) { return 0; } if (objectiveManager.CurrentOrder == this) { return AIObjectiveManager.OrderPriority; } return base.GetPriority(objectiveManager); } public AIObjectiveOperateItem(ItemComponent item, Character character, string option, bool requireEquip, Entity operateTarget = null, bool useController = false) : base (character, option) { this.component = item ?? throw new System.ArgumentNullException("item", "Attempted to create an AIObjectiveOperateItem with a null target."); this.requireEquip = requireEquip; this.operateTarget = operateTarget; this.useController = useController; if (useController) { var controllers = component.Item.GetConnectedComponents(); if (controllers.Any()) controller = controllers[0]; } canBeCompleted = true; } protected override void Act(float deltaTime) { ItemComponent target = useController ? controller : component; if (useController && controller == null) { character.Speak(TextManager.Get("DialogCantFindController").Replace("[item]", component.Item.Name), null, 2.0f, "cantfindcontroller", 30.0f); return; } if (target.CanBeSelected) { if (Vector2.Distance(character.Position, target.Item.Position) < target.Item.InteractDistance || target.Item.IsInsideTrigger(character.WorldPosition)) { if (character.SelectedConstruction != target.Item && target.CanBeSelected) { target.Item.TryInteract(character, false, true); } if (component.AIOperate(deltaTime, character, this)) isCompleted = true; return; } AddSubObjective(gotoObjective = new AIObjectiveGoTo(target.Item, character)); } else { if (component.Item.GetComponent() == null) { //controller/target can't be selected and the item cannot be picked -> objective can't be completed canBeCompleted = false; return; } else if (!character.Inventory.Items.Contains(component.Item)) { AddSubObjective(new AIObjectiveGetItem(character, component.Item, true)); } else { if (requireEquip && !character.HasEquippedItem(component.Item)) { //the item has to be equipped before using it if it's holdable var holdable = component.Item.GetComponent(); if (holdable == null) { DebugConsole.ThrowError("AIObjectiveOperateItem failed - equipping item " + component.Item + " is required but the item has no Holdable component"); return; } for (int i = 0; i < character.Inventory.Capacity; i++) { if (character.Inventory.SlotTypes[i] == InvSlotType.Any || !holdable.AllowedSlots.Any(s => s.HasFlag(character.Inventory.SlotTypes[i]))) { continue; } //equip slot already taken if (character.Inventory.Items[i] != null) { //try to put the item in an Any slot, and drop it if that fails if (!character.Inventory.Items[i].AllowedSlots.Contains(InvSlotType.Any) || !character.Inventory.TryPutItem(character.Inventory.Items[i], character, new List() { InvSlotType.Any })) { character.Inventory.Items[i].Drop(character); } } if (character.Inventory.TryPutItem(component.Item, i, true, false, character)) { component.Item.Equip(character); break; } } return; } if (component.AIOperate(deltaTime, character, this)) isCompleted = true; } } } public override bool IsCompleted() { return isCompleted; } public override bool IsDuplicate(AIObjective otherObjective) { AIObjectiveOperateItem operateItem = otherObjective as AIObjectiveOperateItem; if (operateItem == null) return false; return (operateItem.component == component ||otherObjective.Option == Option); } } }