Пример #1
0
 private void Move(float deltaTime)
 {
     // Retreat to safety
     // TODO: aggressive behaviour, chasing?
     if (retreatTarget == null || (retreatObjective != null && !retreatObjective.CanBeCompleted))
     {
         retreatTarget = HumanAIController.ObjectiveManager.GetObjective <AIObjectiveFindSafety>().FindBestHull();
     }
     if (retreatTarget != null)
     {
         if (retreatObjective == null || retreatObjective.Target != retreatTarget)
         {
             retreatObjective = new AIObjectiveGoTo(retreatTarget, character, false, true);
         }
         retreatObjective.TryComplete(deltaTime);
     }
 }
Пример #2
0
 private void Retreat(float deltaTime)
 {
     if (retreatTarget == null || (retreatObjective != null && !retreatObjective.CanBeCompleted))
     {
         retreatTarget = HumanAIController.ObjectiveManager.GetObjective <AIObjectiveFindSafety>().FindBestHull(new List <Hull>()
         {
             character.CurrentHull
         });
     }
     if (retreatTarget != null)
     {
         if (retreatObjective == null || retreatObjective.Target != retreatTarget)
         {
             retreatObjective = new AIObjectiveGoTo(retreatTarget, character, false, true);
         }
         retreatObjective.TryComplete(deltaTime);
     }
 }
        protected override void Act(float deltaTime)
        {
            var currentHull = character.AnimController.CurrentHull;

            currenthullSafety = OverrideCurrentHullSafety == null?
                                GetHullSafety(currentHull, character) : (float)OverrideCurrentHullSafety;

            if (NeedsDivingGear())
            {
                if (!FindDivingGear(deltaTime))
                {
                    return;
                }
            }


            if (searchHullTimer > 0.0f)
            {
                searchHullTimer -= deltaTime;
            }
            else
            {
                var bestHull = FindBestHull();
                if (bestHull != null)
                {
                    goToObjective = new AIObjectiveGoTo(bestHull, character);
                }

                searchHullTimer = SearchHullInterval;
            }

            if (goToObjective != null)
            {
                var pathSteering = character.AIController.SteeringManager as IndoorsSteeringManager;
                if (pathSteering != null && pathSteering.CurrentPath != null &&
                    pathSteering.CurrentPath.Unreachable && !unreachable.Contains(goToObjective.Target))
                {
                    unreachable.Add(goToObjective.Target as Hull);
                }


                goToObjective.TryComplete(deltaTime);
            }
        }
Пример #4
0
        protected override void Act(float deltaTime)
        {
            var currentHull = character.AnimController.CurrentHull;

            if (HumanAIController.NeedsDivingGear(currentHull) && divingGearObjective == null)
            {
                bool needsDivingSuit = currentHull == null || currentHull.WaterPercentage > 90;
                bool hasEquipment    = needsDivingSuit ? HumanAIController.HasDivingSuit(character) : HumanAIController.HasDivingGear(character);
                if (!hasEquipment)
                {
                    divingGearObjective = new AIObjectiveFindDivingGear(character, needsDivingSuit);
                }
            }
            if (divingGearObjective != null)
            {
                divingGearObjective.TryComplete(deltaTime);
                if (divingGearObjective.IsCompleted())
                {
                    divingGearObjective = null;
                    Priority            = 0;
                }
                else if (divingGearObjective.CanBeCompleted)
                {
                    // If diving gear objective is active and can be completed, wait for it to complete.
                    return;
                }
                else
                {
                    divingGearObjective = null;
                    // Reset the timer so that we get a safe hull target.
                    searchHullTimer = 0;
                }
            }

            if (unreachableClearTimer > 0)
            {
                unreachableClearTimer -= deltaTime;
            }
            else
            {
                unreachableClearTimer = clearUnreachableInterval;
                unreachable.Clear();
            }

            if (searchHullTimer > 0.0f)
            {
                searchHullTimer -= deltaTime;
            }
            else if (currenthullSafety < HumanAIController.HULL_SAFETY_THRESHOLD)
            {
                var bestHull = FindBestHull();
                if (bestHull != null && bestHull != currentHull)
                {
                    if (goToObjective != null)
                    {
                        if (goToObjective.Target != bestHull)
                        {
                            // If we need diving gear, we should already have it, if possible.
                            goToObjective = new AIObjectiveGoTo(bestHull, character, getDivingGearIfNeeded: false)
                            {
                                AllowGoingOutside = HumanAIController.HasDivingSuit(character)
                            };
                        }
                    }
                    else
                    {
                        goToObjective = new AIObjectiveGoTo(bestHull, character, getDivingGearIfNeeded: false)
                        {
                            AllowGoingOutside = HumanAIController.HasDivingSuit(character)
                        };
                    }
                }
                searchHullTimer = SearchHullInterval;
            }

            if (goToObjective != null)
            {
                goToObjective.TryComplete(deltaTime);
                if (!goToObjective.CanBeCompleted)
                {
                    if (!unreachable.Contains(goToObjective.Target))
                    {
                        unreachable.Add(goToObjective.Target as Hull);
                    }
                    goToObjective = null;
                    HumanAIController.ObjectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime);
                    //SteeringManager.SteeringWander();
                }
            }
            else if (currentHull != null)
            {
                //goto objective doesn't exist (a safe hull not found, or a path to a safe hull not found)
                // -> attempt to manually steer away from hazards
                Vector2 escapeVel = Vector2.Zero;
                foreach (FireSource fireSource in currentHull.FireSources)
                {
                    Vector2 dir            = character.Position - fireSource.Position;
                    float   distMultiplier = MathHelper.Clamp(100.0f / Vector2.Distance(fireSource.Position, character.Position), 0.1f, 10.0f);
                    escapeVel += new Vector2(Math.Sign(dir.X) * distMultiplier, !character.IsClimbing ? 0 : Math.Sign(dir.Y) * distMultiplier);
                }

                foreach (Character enemy in Character.CharacterList)
                {
                    //don't run from friendly NPCs
                    if (enemy.TeamID == Character.TeamType.FriendlyNPC)
                    {
                        continue;
                    }
                    //friendly NPCs don't run away from anything but characters controlled by EnemyAIController (= monsters)
                    if (character.TeamID == Character.TeamType.FriendlyNPC && !(enemy.AIController is EnemyAIController))
                    {
                        continue;
                    }

                    if (enemy.CurrentHull == currentHull && !enemy.IsDead && !enemy.IsUnconscious &&
                        (enemy.AIController is EnemyAIController || enemy.TeamID != character.TeamID))
                    {
                        Vector2 dir            = character.Position - enemy.Position;
                        float   distMultiplier = MathHelper.Clamp(100.0f / Vector2.Distance(enemy.Position, character.Position), 0.1f, 10.0f);
                        escapeVel += new Vector2(Math.Sign(dir.X) * distMultiplier, !character.IsClimbing ? 0 : Math.Sign(dir.Y) * distMultiplier);
                    }
                }

                if (escapeVel != Vector2.Zero)
                {
                    //only move if we haven't reached the edge of the room
                    if ((escapeVel.X < 0 && character.Position.X > currentHull.Rect.X + 50) ||
                        (escapeVel.X > 0 && character.Position.X < currentHull.Rect.Right - 50))
                    {
                        character.AIController.SteeringManager.SteeringManual(deltaTime, escapeVel);
                    }
                    else
                    {
                        character.AnimController.TargetDir = escapeVel.X < 0.0f ? Direction.Right : Direction.Left;
                        character.AIController.SteeringManager.Reset();
                    }
                }
                else
                {
                    character.AIController.SteeringManager.Reset();
                }
            }
        }
Пример #5
0
        protected override void Act(float deltaTime)
        {
            FindTargetItem();
            if (targetItem == null || moveToTarget == null)
            {
                HumanAIController.ObjectiveManager.GetObjective <AIObjectiveIdle>().Wander(deltaTime);
                //SteeringManager.SteeringWander();
                return;
            }

            if (moveToTarget.CurrentHull == character.CurrentHull &&
                Vector2.DistanceSquared(character.Position, moveToTarget.Position) < MathUtils.Pow(targetItem.InteractDistance * 2, 2))
            {
                int targetSlot = -1;
                if (equip)
                {
                    var pickable = targetItem.GetComponent <Pickable>();
                    if (pickable == null)
                    {
                        canBeCompleted = false;
                        return;
                    }

                    //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
                            if (character.Inventory.Items[i] == null)
                            {
                                continue;
                            }

                            //try to move the existing item to LimbSlot.Any and continue if successful
                            if (character.Inventory.TryPutItem(character.Inventory.Items[i], character, new List <InvSlotType>()
                            {
                                InvSlotType.Any
                            }))
                            {
                                continue;
                            }

                            //if everything else fails, simply drop the existing item
                            character.Inventory.Items[i].Drop(character);
                        }
                    }
                }

                targetItem.TryInteract(character, false, true);

                if (targetSlot > -1 && !character.HasEquippedItem(targetItem))
                {
                    character.Inventory.TryPutItem(targetItem, targetSlot, false, false, character);
                }
            }
            else
            {
                if (goToObjective == null || moveToTarget != goToObjective.Target)
                {
                    //check if we're already looking for a diving gear
                    bool gettingDivingGear = (targetItem != null && targetItem.Prefab.Identifier == "divingsuit" || targetItem.HasTag("diving")) ||
                                             (itemIdentifiers != null && (itemIdentifiers.Contains("diving") || itemIdentifiers.Contains("divingsuit")));

                    //don't attempt to get diving gear to reach the destination if the item we're trying to get is diving gear
                    goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear);
                }

                goToObjective.TryComplete(deltaTime);
                if (!goToObjective.CanBeCompleted)
                {
                    targetItem   = null;
                    moveToTarget = null;
                    ignoredItems.Add(targetItem);
                }
            }
        }
Пример #6
0
        protected override void Act(float deltaTime)
        {
            FindTargetItem();
            if (targetItem == null || moveToTarget == null)
            {
                character?.AIController?.SteeringManager?.Reset();
                return;
            }

            if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.InteractDistance * 2.0f)
            {
                int targetSlot = -1;
                if (equip)
                {
                    var pickable = targetItem.GetComponent <Pickable>();
                    if (pickable == null)
                    {
                        canBeCompleted = false;
                        return;
                    }

                    //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(CharacterInventory.limbSlots[i]))
                            {
                                continue;
                            }

                            targetSlot = i;

                            //slot free, continue
                            if (character.Inventory.Items[i] == null)
                            {
                                continue;
                            }

                            //try to move the existing item to LimbSlot.Any and continue if successful
                            if (character.Inventory.TryPutItem(character.Inventory.Items[i], character, new List <InvSlotType>()
                            {
                                InvSlotType.Any
                            }))
                            {
                                continue;
                            }

                            //if everything else fails, simply drop the existing item
                            character.Inventory.Items[i].Drop();
                        }
                    }
                }

                targetItem.TryInteract(character, false, true);

                if (targetSlot > -1 && character.Inventory.IsInLimbSlot(targetItem, InvSlotType.Any))
                {
                    character.Inventory.TryPutItem(targetItem, targetSlot, false, character);
                }
            }
            else
            {
                if (goToObjective == null || moveToTarget != goToObjective.Target)
                {
                    //check if we're already looking for a diving gear
                    bool gettingDivingGear = (targetItem != null && targetItem.Prefab.NameMatches("Diving Gear") || targetItem.HasTag("diving")) ||
                                             (itemNames != null && (itemNames.Contains("diving") || itemNames.Contains("Diving Gear")));

                    //don't attempt to get diving gear to reach the destination if the item we're trying to get is diving gear
                    goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear);
                }

                goToObjective.TryComplete(deltaTime);
            }
        }
Пример #7
0
        protected override void Act(float deltaTime)
        {
            FindTargetItem();
            if (targetItem == null || moveToTarget == null)
            {
                return;
            }

            if (Vector2.Distance(character.Position, moveToTarget.Position) < targetItem.PickDistance * 2.0f)
            {
                int targetSlot = -1;
                if (equip)
                {
                    var pickable = targetItem.GetComponent <Pickable>();
                    if (pickable == null)
                    {
                        canBeCompleted = false;
                        return;
                    }

                    //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(CharacterInventory.limbSlots[i]))
                            {
                                continue;
                            }

                            targetSlot = i;

                            //slot free, continue
                            if (character.Inventory.Items[i] == null)
                            {
                                continue;
                            }

                            //try to move the existing item to LimbSlot.Any and continue if successful
                            if (character.Inventory.TryPutItem(character.Inventory.Items[i], new List <InvSlotType>()
                            {
                                InvSlotType.Any
                            }))
                            {
                                continue;
                            }

                            //if everything else fails, simply drop the existing item
                            character.Inventory.Items[i].Drop();
                        }
                    }
                }

                targetItem.Pick(character, false, true);

                if (targetSlot > -1 && character.Inventory.IsInLimbSlot(targetItem, InvSlotType.Any))
                {
                    character.Inventory.TryPutItem(targetItem, targetSlot, false);
                }
            }
            else
            {
                if (goToObjective == null)
                {
                    bool gettingDivingGear = itemName == "diving" || itemName == "Diving Gear";
                    goToObjective = new AIObjectiveGoTo(moveToTarget, character, false, !gettingDivingGear);
                }

                goToObjective.TryComplete(deltaTime);
            }
        }
        protected override void Act(float deltaTime)
        {
            var extinguisherItem = character.Inventory.FindItemByIdentifier("extinguisher") ?? character.Inventory.FindItemByTag("extinguisher");

            if (extinguisherItem == null || extinguisherItem.Condition <= 0.0f || !character.HasEquippedItem(extinguisherItem))
            {
                if (getExtinguisherObjective == null)
                {
                    character.Speak(TextManager.Get("DialogFindExtinguisher"), null, 2.0f, "findextinguisher", 30.0f);
                    getExtinguisherObjective = new AIObjectiveGetItem(character, "extinguisher", true);
                }
                else
                {
                    getExtinguisherObjective.TryComplete(deltaTime);
                }

                return;
            }

            var extinguisher = extinguisherItem.GetComponent <RepairTool>();

            if (extinguisher == null)
            {
                DebugConsole.ThrowError("AIObjectiveExtinguishFire failed - the item \"" + extinguisherItem + "\" has no RepairTool component but is tagged as an extinguisher");
                return;
            }

            foreach (FireSource fs in targetHull.FireSources)
            {
                bool inRange = fs.IsInDamageRange(character, MathHelper.Clamp(fs.DamageRange * 1.5f, extinguisher.Range * 0.5f, extinguisher.Range));
                if (targetHull == character.CurrentHull && (inRange || useExtinquisherTimer > 0.0f))
                {
                    useExtinquisherTimer += deltaTime;
                    if (useExtinquisherTimer > 2.0f)
                    {
                        useExtinquisherTimer = 0.0f;
                    }

                    character.CursorPosition = fs.Position;
                    character.SetInput(InputType.Aim, false, true);
                    if (!character.IsClimbing)
                    {
                        character.AIController.SteeringManager.Reset();
                    }
                    extinguisher.Use(deltaTime, character);

                    if (!targetHull.FireSources.Contains(fs))
                    {
                        character.Speak(TextManager.Get("DialogPutOutFire").Replace("[roomname]", targetHull.Name), null, 0, "putoutfire", 10.0f);
                    }
                    return;
                }
                else
                {
                    //go to the first firesource
                    if (gotoObjective == null || !gotoObjective.CanBeCompleted || gotoObjective.IsCompleted())
                    {
                        gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(fs.Position), character);
                    }
                    else
                    {
                        gotoObjective.TryComplete(deltaTime);
                    }
                    break;
                }
            }
        }