public override float GetPriority()
        {
            bool isOrder = objectiveManager.CurrentOrder == this;

            if (!IsAllowed || character.LockHands)
            {
                Priority = 0;
                Abandon  = !isOrder;
                return(Priority);
            }
            if (component.Item.ConditionPercentage <= 0)
            {
                Priority = 0;
            }
            else
            {
                if (isOrder)
                {
                    Priority = AIObjectiveManager.OrderPriority;
                }
                ItemComponent target     = GetTarget();
                Item          targetItem = target?.Item;
                if (targetItem == null)
                {
#if DEBUG
                    DebugConsole.ThrowError("Item or component of AI Objective Operate item was null. This shouldn't happen.");
#endif
                    Abandon  = true;
                    Priority = 0;
                    return(Priority);
                }
                var reactor = component?.Item.GetComponent <Reactor>();
                if (reactor != null)
                {
                    if (!isOrder)
                    {
                        if (reactor.LastUserWasPlayer && character.TeamID != CharacterTeamType.FriendlyNPC ||
                            HumanAIController.IsTrueForAnyCrewMember(c =>
                                                                     c.ObjectiveManager.CurrentOrder is AIObjectiveOperateItem operateOrder && operateOrder.GetTarget() == target))
                        {
                            Priority = 0;
                            return(Priority);
                        }
                    }
                    switch (Option)
                    {
                    case "shutdown":
                        if (!reactor.PowerOn)
                        {
                            Priority = 0;
                            return(Priority);
                        }
                        break;

                    case "powerup":
                        // Check that we don't already have another order that is targeting the same item.
                        // Without this the autonomous objective will tell the bot to turn the reactor on again.
                        if (objectiveManager.CurrentOrder is AIObjectiveOperateItem operateOrder && operateOrder != this && operateOrder.GetTarget() == target && operateOrder.Option != Option)
                        {
                            Priority = 0;
                            return(Priority);
                        }
                        break;
                    }
                }
                if (targetItem.CurrentHull == null ||
                    targetItem.Submarine != character.Submarine && !isOrder ||
                    targetItem.CurrentHull.FireSources.Any() ||
                    HumanAIController.IsItemOperatedByAnother(target, out _) ||
                    Character.CharacterList.Any(c => c.CurrentHull == targetItem.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c)) ||
                    component.Item.IgnoreByAI || (useController && controller.Item.IgnoreByAI))
                {
                    Priority = 0;
                }
                else
                {
                    float value = CumulatedDevotion + (AIObjectiveManager.OrderPriority * PriorityModifier);
                    float max   = isOrder ? MathHelper.Min(AIObjectiveManager.OrderPriority, 90) : AIObjectiveManager.RunPriority - 1;
                    if (!isOrder && reactor != null && reactor.PowerOn && Option == "powerup")
                    {
                        // Decrease the priority when targeting a reactor that is already on.
                        value /= 2;
                    }
                    Priority = MathHelper.Clamp(value, 0, max);
                }
            }
            return(Priority);
        }
Ejemplo n.º 2
0
        protected override void Act(float deltaTime)
        {
            if (character.LockHands)
            {
                Abandon = true;
                return;
            }
            ItemComponent target = GetTarget();

            if (useController && controller == null)
            {
                character.Speak(TextManager.GetWithVariable("DialogCantFindController", "[item]", component.Item.Name, true), null, 2.0f, "cantfindcontroller", 30.0f);
                Abandon = true;
                return;
            }
            // If this is not an order...
            if (objectiveManager.CurrentOrder != this)
            {
                // Don't allow to operate an item that someone with a better skills already operates
                if (HumanAIController.IsItemOperatedByAnother(target, out _))
                {
                    // Don't abandon
                    return;
                }
                if (component.Item.IgnoreByAI || (useController && controller.Item.IgnoreByAI))
                {
                    Abandon = true;
                    return;
                }
            }
            if (operateTarget != null)
            {
                if (HumanAIController.IsTrueForAnyCrewMember(other => other != HumanAIController && other.ObjectiveManager.GetActiveObjective() is AIObjectiveOperateItem operateObjective && operateObjective.operateTarget == operateTarget))
                {
                    // Another crew member is already targeting this entity.
                    Abandon = true;
                    return;
                }
            }
            if (target.CanBeSelected)
            {
                if (!character.IsClimbing && character.CanInteractWith(target.Item, out _, checkLinked: false))
                {
                    HumanAIController.FaceTarget(target.Item);
                    if (character.SelectedConstruction != target.Item)
                    {
                        target.Item.TryInteract(character, false, true);
                    }
                    if (component.AIOperate(deltaTime, character, this))
                    {
                        isDoneOperating = completionCondition == null || completionCondition();
                    }
                }
                else
                {
                    TryAddSubObjective(ref goToObjective, () => new AIObjectiveGoTo(target.Item, character, objectiveManager, closeEnough: 50)
                    {
                        DialogueIdentifier = "dialogcannotreachtarget",
                        TargetName         = target.Item.Name,
                        endNodeFilter      = node => node.Waypoint.Ladders == null
                    },
                                       onAbandon: () => Abandon = true,
                                       onCompleted: () => RemoveSubObjective(ref goToObjective));
                }
            }
            else
            {
                if (component.Item.GetComponent <Pickable>() == null)
                {
                    //controller/target can't be selected and the item cannot be picked -> objective can't be completed
                    Abandon = true;
                    return;
                }
                else if (!character.Inventory.Items.Contains(component.Item))
                {
                    TryAddSubObjective(ref getItemObjective, () => new AIObjectiveGetItem(character, component.Item, objectiveManager, equip: true),
                                       onAbandon: () => Abandon = true,
                                       onCompleted: () => RemoveSubObjective(ref getItemObjective));
                }
                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 <Holdable>();
                        if (holdable == null)
                        {
#if DEBUG
                            DebugConsole.ThrowError($"{character.Name}: AIObjectiveOperateItem failed - equipping item " + component.Item + " is required but the item has no Holdable component");
#endif
                            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>()
                                {
                                    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))
                    {
                        isDoneOperating = completionCondition == null || completionCondition();
                    }
                }
            }
        }
Ejemplo n.º 3
0
        public override float GetPriority()
        {
            if (!IsAllowed)
            {
                Priority = 0;
                return(Priority);
            }
            if (component.Item.ConditionPercentage <= 0)
            {
                Priority = 0;
            }
            else
            {
                if (objectiveManager.CurrentOrder == this)
                {
                    Priority = AIObjectiveManager.OrderPriority;
                }
                ItemComponent target     = GetTarget();
                Item          targetItem = target?.Item;
                if (targetItem == null)
                {
#if DEBUG
                    DebugConsole.ThrowError("Item or component of AI Objective Operate item was null. This shouldn't happen.");
#endif
                    Abandon  = true;
                    Priority = 0;
                    return(Priority);
                }
                var reactor = component?.Item.GetComponent <Reactor>();
                if (reactor != null)
                {
                    switch (Option)
                    {
                    case "shutdown":
                        if (!reactor.PowerOn)
                        {
                            Priority = 0;
                            return(Priority);
                        }
                        break;

                    case "powerup":
                        // Check that we don't already have another order that is targeting the same item.
                        // Without this the autonomous objective will tell the bot to turn the reactor on again.
                        if (objectiveManager.CurrentOrder is AIObjectiveOperateItem operateOrder && operateOrder != this && operateOrder.GetTarget() == target)
                        {
                            Priority = 0;
                            return(Priority);
                        }
                        break;
                    }
                }
                if (targetItem.CurrentHull == null ||
                    targetItem.Submarine != character.Submarine && objectiveManager.CurrentOrder != this ||
                    targetItem.CurrentHull.FireSources.Any() ||
                    HumanAIController.IsItemOperatedByAnother(target, out _) ||
                    Character.CharacterList.Any(c => c.CurrentHull == targetItem.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c)))
                {
                    Priority = 0;
                }
                else
                {
                    float value = CumulatedDevotion + (AIObjectiveManager.OrderPriority * PriorityModifier);
                    float max   = objectiveManager.CurrentOrder == this ? MathHelper.Min(AIObjectiveManager.OrderPriority, 90) : AIObjectiveManager.RunPriority - 1;
                    Priority = MathHelper.Clamp(value, 0, max);
                }
            }
            return(Priority);
        }
Ejemplo n.º 4
0
        protected override float GetPriority()
        {
            bool isOrder = objectiveManager.IsOrder(this);

            if (!IsAllowed || character.LockHands)
            {
                Priority = 0;
                Abandon  = !isOrder;
                return(Priority);
            }
            if (!isOrder && component.Item.ConditionPercentage <= 0)
            {
                Priority = 0;
            }
            else
            {
                if (isOrder)
                {
                    Priority = objectiveManager.GetOrderPriority(this);
                }
                ItemComponent target     = GetTarget();
                Item          targetItem = target?.Item;
                if (targetItem == null)
                {
#if DEBUG
                    DebugConsole.ThrowError("Item or component of AI Objective Operate item was null. This shouldn't happen.");
#endif
                    Abandon  = true;
                    Priority = 0;
                    return(Priority);
                }
                var reactor = component?.Item.GetComponent <Reactor>();
                if (reactor != null)
                {
                    if (!isOrder)
                    {
                        if (reactor.LastUserWasPlayer && character.TeamID != CharacterTeamType.FriendlyNPC)
                        {
                            // The reactor was previously operated by a player -> ignore.
                            Priority = 0;
                            return(Priority);
                        }
                    }
                    switch (Option)
                    {
                    case "shutdown":
                        if (!reactor.PowerOn)
                        {
                            Priority = 0;
                            return(Priority);
                        }
                        break;

                    case "powerup":
                        // Check that we don't already have another order that is targeting the same item.
                        // Without this the autonomous objective will tell the bot to turn the reactor on again.
                        if (IsAnotherOrderTargetingSameItem(objectiveManager.ForcedOrder) || objectiveManager.CurrentOrders.Any(o => IsAnotherOrderTargetingSameItem(o.Objective)))
                        {
                            Priority = 0;
                            return(Priority);
                        }
                        bool IsAnotherOrderTargetingSameItem(AIObjective objective)
                        {
                            return(objective is AIObjectiveOperateItem operateObjective && operateObjective != this && operateObjective.GetTarget() == target && operateObjective.Option != Option);
                        }

                        break;
                    }
                }
                else if (!isOrder)
                {
                    var steering = component?.Item.GetComponent <Steering>();
                    if (steering != null && (steering.AutoPilot || HumanAIController.IsTrueForAnyCrewMember(c => c != HumanAIController && c.Character.IsCaptain)))
                    {
                        // Ignore if already set to autopilot or if there's a captain onboard
                        Priority = 0;
                        return(Priority);
                    }
                }
                if (targetItem.CurrentHull == null ||
                    targetItem.Submarine != character.Submarine && !isOrder ||
                    targetItem.CurrentHull.FireSources.Any() ||
                    HumanAIController.IsItemOperatedByAnother(target, out _) ||
                    Character.CharacterList.Any(c => c.CurrentHull == targetItem.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c)) ||
                    component.Item.IgnoreByAI(character) || useController && controller.Item.IgnoreByAI(character))
                {
                    Priority = 0;
                }
                else
                {
                    if (isOrder)
                    {
                        float max   = objectiveManager.GetOrderPriority(this);
                        float value = CumulatedDevotion + (max * PriorityModifier);
                        Priority = MathHelper.Clamp(value, 0, max);
                    }
                    else
                    {
                        float value = CumulatedDevotion + (AIObjectiveManager.LowestOrderPriority * PriorityModifier);
                        float max   = AIObjectiveManager.LowestOrderPriority - 1;
                        if (reactor != null && reactor.PowerOn && reactor.FissionRate > 1 && reactor.AutoTemp && Option == "powerup")
                        {
                            // Already on, no need to operate.
                            value = 0;
                        }
                        Priority = MathHelper.Clamp(value, 0, max);
                    }
                }
            }
            return(Priority);
        }
Ejemplo n.º 5
0
        public override float GetPriority()
        {
            if (!IsAllowed)
            {
                Priority = 0;
                return(Priority);
            }
            if (component.Item.ConditionPercentage <= 0)
            {
                Priority = 0;
            }
            else
            {
                if (objectiveManager.CurrentOrder == this)
                {
                    Priority = AIObjectiveManager.OrderPriority;
                }
                Item targetItem = GetTarget()?.Item;
                if (targetItem == null)
                {
#if DEBUG
                    DebugConsole.ThrowError("Item or component of AI Objective Operate item wass null. This shouldn't happen.");
#endif
                    Abandon  = true;
                    Priority = 0;
                    return(0.0f);
                }
                if (targetItem.CurrentHull == null || targetItem.CurrentHull.FireSources.Any() || HumanAIController.IsItemOperatedByAnother(GetTarget(), out _))
                {
                    Priority = 0;
                }
                else if (Character.CharacterList.Any(c => c.CurrentHull == targetItem.CurrentHull && !HumanAIController.IsFriendly(c) && HumanAIController.IsActive(c)))
                {
                    Priority = 0;
                }
                else
                {
                    float value = CumulatedDevotion + (AIObjectiveManager.OrderPriority * PriorityModifier);
                    float max   = MathHelper.Min((AIObjectiveManager.OrderPriority - 1), 90);
                    Priority = MathHelper.Clamp(value, 0, max);
                }
            }
            return(Priority);
        }